Intercom とスプレッドシートのみでヘルススコアを管理できないか試してみた
これは TOWN Advent Calendar 2018 24日目のエントリーです。
本日は、カスタマーサクセスまわりの少々テクニカルなエントリーになります。
ヘルススコア(顧客の健康状態を示す指標)の管理方法について、色々と模索をしているのですが、HiCustomer のような専門のプラットフォームを導入するか独自実装を行うか。弊社では Intercom を使い倒しているので、Intercom に蓄積されているデータの活用でどこまでできるか試してみました。
1. セグメントでヘルススコア条件を表現
Company の属性をフィルタリングして GOOD/POOR セグメントを作成します。ヘルススコアに必要な情報はカスタム属性としてAPI経由で送信しておきます。
2. 顧客のステージとヘルススコア条件を掛け合わせたセグメントを作成
ここではトライアル中のステージに合わせて Trial-GOOD/Trial-POOR セグメントを作成しました。また、GOOD/POOR の条件に入らない Trial-AVERAGE セグメントも合わせて作成しておきます。
3. GASでセグメントの状態をプロット
以下の updateIntercomSegments 関数をトリガーで定期実行されるように設定します。毎日1行ずつ当日の行が追加され、各セグメント内の顧客件数がプロットされるようになります。
function updateIntercomSegments() {
var spreadsheetObj = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheetObj.getSheetByName("segments");
var formatToday = insertToday("segments");
var con = connect('','');
var column = 1;
var results = con.getSegments();
var segments = results.segments;
var range = sheet.getRange("B1:G1"); // セグメント名をシートに記載しておく
range.getValues()[0].forEach(function(item, index){
var name = item;
column++;
if(name) {
for (var idx in segments) {
if(segments[idx].name == name) {
var results2 = con.getCompanies(1, segments[idx].id);
sheet.getRange(sheet.getLastRow(),column).setValue(results2.total_count);
}
}
}
});
}
function insertToday(sheetName) {
var spreadsheetObj = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheetObj.getSheetByName(sheetName);
var today = new Date();
var formatToday = Utilities.formatDate(today, "Asia/Tokyo", "yyyy-MM-dd");
var lastRow = sheet.getLastRow();
var range = sheet.getRange(lastRow,1);
var dateColumn = range.getValue();
if(Utilities.formatDate(dateColumn, "Asia/Tokyo", "yyyy-MM-dd") != formatToday) {
var newRow = sheet.getRange(lastRow+1,1);
newRow.setValue(formatToday);
}
return formatToday;
}
Intercom の API からデータを引っ張ってくるスクリプトは以下のようになります。
function connect(app_id, app_secret){
return new Intercom(app_id, app_secret);
};
function Intercom(app_id, app_secret){
this.app_id = app_id;
this.app_secret = app_secret;
this.accessToken = '';
}
Intercom.prototype.run = function(url, payload, method){
var headers = {
'Authorization':'Bearer ' + this.accessToken,
"Accept": 'application/json'
};
if(!method) {
method = "get";
}
var options = {
"method" : method,
"contentType": 'application/json',
"headers": headers,
muteHttpExceptions: true,
}
if(payload != null) {
options["payload"] = JSON.stringify(payload);
}
return UrlFetchApp.fetch(url, options);
}
Intercom.prototype.getCompanies = function(page, segment_id){
var url = "https://api.intercom.io/companies?page=" + page + "&segment_id=" + segment_id;
var data = {};
return JSON.parse(this.run(url, null).getContentText());
};
Intercom.prototype.getUsers = function(page){
var url = "https://api.intercom.io/users?page=" + page;
var data = {};
return JSON.parse(this.run(url, null).getContentText());
};
Intercom.prototype.getSegments = function(){
var url = "https://api.intercom.io/segments?type=company";
var data = {};
return JSON.parse(this.run(url, null).getContentText());
};
4. スプレッドシートでグラフ作成
プロットされたデータから、以下のようにヘルススコアの推移をグラフ化できました。グラフ画像は Slack に飛ばすようにします(省略)。
まとめ
ひとまず全体の目標推移を追うくらいのことはできました。ここから個別の顧客のスコアの変化からアラートを起こすというのをやりたいのですが、もう一手間あるので今回はここまで。
Intercom の仕様上以下の課題が残りました。
・カスタム属性は時系列で蓄積されないので、「◯◯日内の◯◯件投稿」といった条件については、送信側で一工夫が必要
・Company に Event を送信できない(Event は User のみ)のが地味に痛い、Event でフィルタリングできると楽なのですが・・
・ヘルススコア条件ごとの推移を表現できるかどうか
必要となるヘルススコア条件にもよるのですが、複雑なルールが必要であればやはり専用のプラットフォームを導入するのが良さそうですかね。