マルケトと kintone を連携してみよう

目次

caution
警告

はじめに

標準機能だけを使用してkintoneをMAツールとして用いることは難しいです。
そこで今回は、強力なMAツールの「マルケト」と連携する方法を紹介します。

マルケトの詳細は、公式サイトを確認してください。
MA(マーケティングオートメーション)の市場リーダー | Adobe Marketo Engage (External link)

完成イメージ

今回のシナリオでは上図の2と4の連携部分にあたるカスタマイズ方法を紹介します。

連携では、マルケトに新規顧客が登録されたことをトリガーとして、kintoneへレコードを追加します。
また、kintoneからマルケトのリード更新は、kintoneアプリ詳細画面に設置したボタンから行います。

下準備

kintone

kintoneアプリストアから「案件管理」のアプリを作成してください。
アプリの詳細をクリックして「サンプルデータを含める」のチェックを外してください。

右側の歯車アイコンから設定画面に進み、「設定 > APIトークン」でAPIトークンを作成してください。
権限は「レコード追加」の権限が付与してあれば大丈夫です。
生成したAPIトークンはのちほど利用するので、メモしてください。

「フォーム」タブに移動し、マルケトのリードIDを保存するフィールドを追加します。
フィールドは「数値フィールド」フィールドコードは「leadID」で設定します。
また、ユニークなキーとなるため、「値の重複を禁止する」にチェックを入れます。
設置したフィールドの右上の歯車アイコンから変更できます。

さらに、既存フィールドのフィールドコードも変更します。
下表のとおりに変更してください。

フィールド名 フィールドコード
会社名 companyName
部署名 division
先方担当者 contactName
TEL tel
FAX fax
メールアドレス mail
確度 accuracy

最後にkintoneのアプリIDを確認します。
設定が完了したら、「アプリを公開」(または「アプリを更新」)をクリックしてください。

先ほど作成したkintoneアプリを開きURLを確認してください。
URLのhttps://sample.cybozu.com/k/APP_ID/の「APP_ID」がアプリIDなのでメモしてください。

マルケト

マルケトデベロッパーサイト

Marketo API Documentation | Getting Started (External link) を参考に、マルケトのREST API用のユーザーを追加してください。
ロールの権限は「APIへのアクセス」にチェックを入れてください。

次に、LanchPointを作成し、クライアントIDとクライアントシークレットをメモしてください。

最後にマルケト管理画面でEndpointとIdentity(ID)を確認する必要があります。
下記リンクと画像を参考に確認し、メモしてください。

Market Documentation | Authentication (External link)

以上で準備は完了です。

マルケト設定

マルケト Webhook を作成する

まず、マルケトからkintoneにデータを登録するためのWebhookを作成します。

下図のとおり、マルケトの管理画面からWebhookの設定画面に遷移し、新規Webhookを作成してください。

次に、下図のようなWebhook作成画面が開きます。
それぞれ以下を設定します。

  • URL:自身の環境に合わせて以下を設定します。

    1
    
    https://sample.cybozu.com/k/v1/record.json
  • リクエストタイプ:POST

  • テンプレート:後述の JSON サンプルを元に、appの値だけ先ほど作成したkintoneのアプリIDに変更して貼り付けてください。

  • リクエストトークンのエンコード:JSON

  • 応答タイプ:JSON

JSON サンプル
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
    "app": xx,
    "record": {
        "companyName": {
            "value": {{company.Company Name}}
        },
        "division": {
            "value": {{lead.Job Title}}
        },
        "contactName": {
            "value": {{lead.Full Name}}
        },
        "mail": {
            "value": {{lead.Email Address}}
        },
        "tel": {
            "value": {{lead.Phone Number}}
        },
        "fax": {
            "value": {{lead.Fax Number}}
        },
        "leadID": {
            "value": {{Lead.id}}
        },
        "accuracy": {
            "value": {{lead.Lead Status:default=C}}
        }
    }
}

次にカスタムヘッダーを設定します。

それぞれ以下を設定します。

  • Content-Type:application/json
  • X-Cybozu-API-Token:先ほど作成したkintoneアプリのAPIトークン

以上でマルケトWebhookの作成は完了です。

新規顧客が作成されたとき Webhook が動くようにする

先ほど作成したWebhookを、新規顧客が作成されたら動くようにします。

マルケト画面左上のアイコンをクリックし、「マーケティング活動」から、Webhookを実行させたいワークスペースを選択し、新規スマートキャンペーンを作成します。
フォルダーや名前は任意に設定してください。

スマートキャンペーンを作成したら、スマートリストから「顧客を作成」のトリガーを選択します。

次にフローで「ウェブフックを呼び出し」を選択し、ドロップダウンから先ほど作成したWebhookを選択します。

最後にスケジュールから有効化をクリックして設定は完了です。

これで、マルケトからkintoneへのデータの設定が完了しました。

kintone 設定

サンプルコード

次のサンプルコードをjsファイルとして保存してください。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/*
 * kintone to marketo sample program
 * Copyright (c) 2018 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
*/

(function(swal) {
  'use strict';

  const clientId = 'MARKETO_CLIENT_ID';
  const clientSecret = 'MARKETO_CLIENT_SECRET';
  const IdentityURL = 'MARKETO_IDENTITY_URL';
  const EndpointURL = 'MARKETO_ENDPOINT_URL';

  // リード送信時のsweetalert
  function showSwalQues() {
    return swal({
      title: 'マルケトリードの情報を更新しますか?',
      type: 'warning',
      showCancelButton: true,
      confirmButtonColor: '#3085d6',
      cancelButtonColor: '#d33',
      confirmButtonText: 'はい',
      cancelButtonText: 'いいえ'
    });
  }

  // マルケトのAuthTokenを取得する
  function getAuthToken() {
    const url = IdentityURL + '/oauth/token?' +
            'grant_type=client_credentials&client_id=' + clientId +
            '&client_secret=' + clientSecret;

    return kintone.proxy(url, 'GET', {}, {})
      .then((resp) => {
        const obj = JSON.parse(resp[0]);
        return obj;
      });
  }

  // 更新ボタン作成関数
  function createPutButton() {
    const button = new kintoneUIComponent.Button({
      text: 'マルケトのリードを更新する',
      type: 'normal'
    });
    kintone.app.record.getHeaderMenuSpaceElement().appendChild(button.render());
    return button;
  }

  // マルケトにリードを送信する
  function putLeads(record, authToken) {
    const name = record.contactName.value.split(' ');
    const first = name[0];
    const last = name[1];
    const body = {
      action: 'updateOnly',
      lookupField: 'id',
      input: [{
        id: record.leadID.value,
        firstName: first,
        lastName: last,
        title: record.division.value,
        company: record.companyName.value,
        email: record.mail.value,
        phone: record.tel.value,
        fax: record.fax.value,
        leadStatus: record.accuracy.value,
      }]
    };
    const url = EndpointURL + '/v1/leads.json?access_token=' + authToken;
    kintone.proxy(url, 'POST', {'Content-Type': 'application/json'}, body)
      .then((resp) => {
        console.log(resp);
      }).catch((err) => {
        console.log(err);
      });
  }

  // 更新ボタンを押したときに動く
  function buttonAction(button, record) {
    const spinner = new kintoneUIComponent.Spinner();
    kintone.app.record.getHeaderMenuSpaceElement().appendChild(spinner.render());
    button.on('click', (e) => {
      return showSwalQues().then((resp) => {
        if (resp.dismiss === 'cancel') {
          throw new Error();
        }
        spinner.show();
        return getAuthToken();
      }).then((authResp) => {
        return putLeads(record, authResp.access_token);
      }).then((resp) => {
        spinner.hide();
        return swal('リードを更新しました。');
      }).then((r) => {
        location.reload();
      }).catch((err) => {
        console.log(err);
      });
    });
  }

  kintone.events.on('app.record.detail.show', (event) => {
    const record = event.record;
    const putButton = createPutButton();
    buttonAction(putButton, record);
    return event;
  });

})(swal);

12〜15行目は下準備でメモした情報を記入してください。

本来12行目と13行目に記述する認証情報は、プラグイン化するなど、情報を秘匿する必要があります。
参考: kintoneプラグイン開発入門 【Part1: メリット編】

JavaScript / CSSカスタマイズ設定

アプリの設定 > 設定タブ > JavaScript / CSSでカスタマイズの順に遷移し、下図のとおり設定します。
「connect-to-Marketo.js」は先ほど作成したサンプルコードです。

kintone UI Component

マルケトリード更新ボタンとスピナーの表示にkintone UI Componentを使用しています。
kintone-labs/kintone-ui-component の Releases (External link) よりv0.1で始まる最新バージョンをダウンロードして解凍し、jsファイルとcssファイルをアプリに適用します。
使用方法は 「kintone UI Component v0」を使って簡単に kintone ライクな UI を設置するの記事を確認してください。

Cybozu CDN

URL指定で Cybozu CDNのSweetAlert2を使用しています。

  • https://js.cybozu.com/sweetalert2/v7.28.2/sweetalert2.min.js
  • https://js.cybozu.com/sweetalert2/v7.28.2/sweetalert2.min.css

動作確認

マルケト新規顧客作成 → kintone レコード追加

kintone レコード詳細画面から更新ボタン → マルケトリード更新

サンプルコード解説

showSwalQues

16
17
18
19
20
21
22
23
24
25
26
27
// リード送信時のsweetalert
function showSwalQues() {
  return swal({
    title: 'マルケトリードの情報を更新しますか?',
    type: 'warning',
    showCancelButton: true,
    confirmButtonColor: '#3085d6',
    cancelButtonColor: '#d33',
    confirmButtonText: 'はい',
    cancelButtonText: 'いいえ'
  });
}

SweetAlert2 (External link) を使用してボタン押下時のアラートを作成しています。

getAuthToken

29
30
31
32
33
34
35
36
37
38
39
40
// マルケトのAuthTokenを取得する
function getAuthToken() {
  const url = IdentityURL + '/oauth/token?' +
        'grant_type=client_credentials&client_id=' + clientId +
        '&client_secret=' + clientSecret;

  return kintone.proxy(url, 'GET', {}, {})
    .then((resp) => {
      const obj = JSON.parse(resp[0]);
      return obj;
    });
}

外部の API を実行する APIを使用して マルケトの認証トークンを取得する API (External link) を実行しています。

createPutButton

42
43
44
45
46
47
48
49
50
// 更新ボタン作成関数
function createPutButton() {
  const button = new kintoneUIComponent.Button({
    text: 'マルケトのリードを更新する',
    type: 'normal'
  });
  kintone.app.record.getHeaderMenuSpaceElement().appendChild(button.render());
  return button;
}

kintone UI Componentの ボタンに関する関数 (External link) を使用してボタンを作成しています。

putLeads

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// マルケトにリードを送信する
function putLeads(record, authToken) {
  const name = record.contactName.value.split(' ');
  const first = name[0];
  const last = name[1];
  const body = {
    action: 'updateOnly',
    lookupField: 'id',
    input: [{
      id: record.leadID.value,
      firstName: first,
      lastName: last,
      title: record.division.value,
      company: record.companyName.value,
      email: record.mail.value,
      phone: record.tel.value,
      fax: record.fax.value,
      leadStatus: record.accuracy.value,
    }]
  };
  const url = EndpointURL + '/v1/leads.json?access_token=' + authToken;
  kintone.proxy(url, 'POST', {'Content-Type': 'application/json'}, body)
    .then((resp) => {
      console.log(resp);
    }).catch((err) => {
      console.log(err);
    });
}

外部の API を実行する APIを使用して マルケトのリードを更新する API (External link) を実行しています。
マルケトのREST APIはPOSTメソッドで作成と更新を実施するUpsert APIなので、更新時もPOSTメソッドを使用します。
詳細はドキュメントを確認してください。

buttonAction

 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
// 更新ボタンを押したときに動く
function buttonAction(button, record) {
  const spinner = new kintoneUIComponent.Spinner();
  kintone.app.record.getHeaderMenuSpaceElement().appendChild(spinner.render());
  button.on('click', (e) => {
    return showSwalQues().then((resp) => {
      if (resp.dismiss === 'cancel') {
        throw new Error();
      }
      spinner.show();
      return getAuthToken();
    }).then((authResp) => {
      return putleads(record, authResp.access_token);
    }).then((resp) => {
      spinner.hide();
      return swal('リードを更新しました。');
    }).then((r) => {
      location.reload();
    }).catch((err) => {
      console.log(err);
    });
  });
}

ボタン押下時のアクションを設定しています。
マルケトのリード更新処理が終了するまで、kintone UI Componentの スピナー (External link) を表示しています。

おわりに

いかがでしょうか。
kintoneとマルケトの相互連携が実現できたと思います。
他にも以下のカスタマイズが実装できそうですね。

  • kintoneアプリのステータス変更時にマルケトリードを更新する。
  • kintoneレコードの値が変更されたときマルケトリードを更新する。
  • kintoneレコード詳細画面にリアルタイムでマルケトリードスコアを表示する。

マルケトのREST APIはリード情報を操作するAPIだけではなく豊富に用意されているのでさまざまなことが可能そうです。
詳細は次のマルケトデベロッパーサイトを確認してください。
Marketo Documentation (External link)

information

このTipsは、2018年10月版kintoneで動作を確認しています。