【営業 自動化】 セールスはマメで口うるさい相棒をつくろう!SlackBotをGASで実装
ども、スタートアップで働くなかしま(@nakashimayugo)です!
営業というとアポイントのイメージが強いですが、事前準備やお礼メール・カレンダー設定など細かい作業が沢山あります。
「マメで仕事漏れがない秘書さんや事務さんに手伝ってほしいな。できれば美人で優しくて・・・」と思ったことが何度もあります。
しかし美人だと緊張して仕事が手につかなくなるので、代わりに24時間働いてくれる相棒をつくることにしました。
こんな感じで営業支援Botとチャンネルを作って色々やってもらっています
ということでこの記事では僕のSlackの相棒を紹介し、実際に業務で使っている機能の一部としてアポ前後に動く内容を紹介します。
セールスはSpredsheetやAnalyticsなどGoogleSuiteを利用する機会が多いと思いますが、そんな時にGASをいじれると便利なのでその一つの事例として。(興味ある人は一緒に勉強しましょう!)
お気持ち。自動化の本質は営業業務をフローからストック型に変えること
記事の主旨から外れますが、自動化の本質は単純に業務時間を短縮することではなく、営業活動をフロー型からストック型に変えることだと思っていて、誰でもできる単純な作業の代替だけでなく、難しかったり時間のかかる内容の再現性を高める目的で使いたいと考えています。
まず営業マン本人が仮説検証の為の動きをして、その動きの細分化・単純化を経て、再現文脈で自動化を取り入れることが重要だと思っています。MA、SFAツールを使うにも、その過程がないと全然役にたたないよねというハナシ(自戒)。
何ができるの?
今回紹介するBotはこんなことをしてくれます。
①アポ前になると顧客名などをカレンダーから抜きだし、その名前を利用して事前準備サイト送ってくれたり、ヒアリングシートを送ってくれたりする
②アポが終わるとリマインド予定をカレンダーに登録しといてくれたりする。
グラフとかないので映えないですねー笑
ポイントとしては自分のカレンダーの予定に沿って勝手に動いてくれるという点なので、色々やりたい人は色々加えてやってください。
全体の処理は簡単です。
まずスケジュール調整はツールを使う
当たり前のことかもしれませんが、日程を調整する際にカレンダーを目視して日付を書いて・・・としていると1件につきかなり時間を使います。私はHubSpotの機能を使っていますが、もし手入力の人がいればツールの利用をおすすめします(それかGasで空き時間を出すスクリプトを作る)
こんな感じでツールから定型の顧客データ<企業名/担当者名/メールアドレス 等>がカレンダーに入ることになります。
メールアドレスがあれば企業のHPも分かりますね。いちいちGoogleで検索する必要もありません。
そして登録してもらった予定はこんな感じで入っているので、そこから「お打ち合わせ」と入ってる内容だけ抜き出して処理します。
Bot対応① 商談前にヒアリングフォームと訪問先の下調べ
アポは慣れてくると毎回同じような商品説明に陥りがちです。必須の事前準備や、アポ内容を事前に頭に入れることでクオリティを一定に保つことができます。コピペや検索などは単純作業なのでBotにお願いしましょう。
ボタンをポチポチすると、こんな感じになったり
こんな感じになって
サイトに飛んだりします(手前味噌感しかないんですが、事前準備のサイトをつくったので自分だけでも使おうと必死です)
これで今から行く企業が、どんなサイトを利用していて出している内容はなにかバッチリです。そしてヒアリング内容も改めて頭にある状態です。
(ヒアリングフォームは適当な内容です)
Bot対応② 商談後リマインドの予定をカレンダーに登録
商談が終わると、後日再連絡をするのを忘れがちですが非常に重要なことなのでBotにめんどくさい登録をやってもらうことにしました。
Yesを押すと
こんな感じ
アポから帰るときの電車でワンポチすれば1週間後の予定が登録されます。楽ちんです。
Noを押すと・・・
・・・口うるさい
その他
今回は簡単に2つの対応でしたが、例えばアポの数を数えて定期的に進捗具合を教えてくれたり、訪問場所からGoogleカレンダーで経路検索・出発時間を教えてくれたり、Gmailと連動させてメールを自動送信したり。もっと言うと顧客の属性を自動で調べてスコアリング、対応を分岐させてワンアクションでそれぞれの対応を走らせたりといったこともできます。結局は自動化といっても営業本人の仕事の代用でしかないので、仕事を楽にすることに集中するのではなくクオリティを上げていくことが大事ですね。
今回の機能の作り方
まずSlackのBot設定はこの記事をみれば分かりやすいと思います。
http://www.pre-practice.net/2017/11/slack-botmessage-buttons.html
GASの設定はたくさんの記事があるので、こちらをもとに色々辿っていくのが良いかと。
https://tonari-it.com/gas-web-application-beginner/
僕のモノすっごい雑なコードだけ下に書いておきます。これを張って、アプリケーションとして公開すればOKです。(以前作ったものにどんどん足していったのでかなり不出来ですが、まあ、動くので勘弁してください。)
アポ前にSlackに投稿するスクリプトはこちら。時間トリガーは2時間おきに実行されるようにしています。
//カレンダーから予定を取得
function CalendarTrigerPostdata() {
var calendar = CalendarApp.getCalendarById('メールアドレス');
// 次のアポ
var start_time = new Date();
start_time.setHours(start_time.getHours());//直前予定のアポを取りたい
var end_time = new Date();
end_time.setHours(end_time.getHours()+1);
var events = calendar.getEvents(start_time, end_time);
if (events != ""){
return events;
}
else {
return "予定まったくなし";
}}
//eventsからアポの予定を取得
function Apodata_parser() {
var events = CalendarTrigerPostdata() ;
if (events !== "予定まったくなし"){
var company_adress_list = [];
var company_name_list = [];
var client_name_list = [];
for (var i=0; i < events.length; i++) {
company_adress_list
var title = events[i].getTitle();
//.getEvents optionにsearchをセットしてもできる
if (title.match(/^(?=.*お打ち合わせ).*$/)){
//タイトルにお打ち合わせが入っていればそれぞれパーサーで抜き出す
var company_name = Parser.data(title)
.from('】')
.to('/')
.iterate()
var client_name = Parser.data(title)
.from('/')
.to('&')
.iterate()
var guests = events[i].getGuestList();
//それぞれのリストに格納
if (guests != ""){
company_adress_list.push(guests[0].getEmail().match(/@.*$/)[0].replace( "@", "https://www."));
}
else {
company_adress_list.push("不明");
}
company_name_list.push(company_name);
client_name_list.push(client_name);
}}
Logger.log(company_adress_list);
return [company_adress_list, company_name_list, client_name_list];
}}
function post_slack_message_apo_start(){
var Data = Apodata_parser();
if (Data[0].length > 0){
var company_name_list = Data[1];
var client_name_list = Data[2];
var i = company_name_list.length -1;
var apo_data = company_name_list[i] + "/" + client_name_list[i] + "さんのアポ楽しんでいこー!\n";
var data = {
"text": apo_data,
"attachments": [{
"text": "ヒアリングフォームと事前準備データが必要ですか?",
"fallback": "fallback message",
"callback_id": "callback_button",
"color": "#3AA3E3",
"attachment_type": "default",
"actions": [{
"name": "Question_sheet",
"text": "Question_sheet",
"type": "button",
"value": "Question_sheet"
},
{
"name": "Activity_search",
"text": "Activity_search",
"type": "button",
"value": "Activity_search"
}
]
}]
}
var url = "webhookのURL"
var options = {
"method" : "POST",
"headers": {"Content-type": "application/json"},
"channel" : "#nakashima-bot",
"payload" : JSON.stringify(data)
};
UrlFetchApp.fetch(url, options);
}}
アポ終わりに連絡するスクリプトはこちら。前半部分は時間の指定を変えてるだけなので合体させちゃってもOK。私の場合違うファイルにしているので別に書いてるだけです。
//カレンダーから予定を取得
function CalendarTrigerPostdata() {
var calendar = CalendarApp.getCalendarById('メールアドレス');
// 次のアポ
var start_time = new Date();
start_time.setHours(start_time.getHours()-1);//直前のアポを取りたい
var end_time = new Date();
end_time.setHours(end_time.getHours());
var events = calendar.getEvents(start_time, end_time);
if (events != ""){
return events;
}
else {
return "予定まったくなし";
}}
//eventsからアポの予定を取得
function Apodata_parser() {
var events = CalendarTrigerPostdata() ;
if (events !== "予定まったくなし"){
var company_adress_list = [];
var company_name_list = [];
var client_name_list = [];
for (var i=0; i < events.length; i++) {
company_adress_list
var title = events[i].getTitle();
//.getEvents optionにsearchをセットしてもできる
if (title.match(/^(?=.*お打ち合わせ).*$/)){
//タイトルにお打ち合わせが入っていればそれぞれパーサーで抜き出す
var company_name = Parser.data(title)
.from('】')
.to('/')
.iterate()
var client_name = Parser.data(title)
.from('/')
.to('&')
.iterate()
var guests = events[i].getGuestList();
//それぞれのリストに格納
if (guests != ""){
company_adress_list.push(guests[0].getEmail().match(/@.*$/)[0].replace( "@", "https://www."));
}
else {
company_adress_list.push("不明");
}
company_name_list.push(company_name);
client_name_list.push(client_name);
}}
Logger.log(company_adress_list);
return [company_adress_list, company_name_list, client_name_list];
}}
function post_slack_message_apo_end(){
var Data = Apodata_parser();
if (Data[0].length > 0){
var company_name_list = Data[1];
var client_name_list = Data[2];
var i = company_name_list.length -1;
var apo_data = company_name_list[i] + "/" + client_name_list[i] + "さんのアポおつかれ!\n";
var data = {
"text": apo_data,
"attachments": [{
"text": "カレンダーにリマインド予定を設定しますか?",
"fallback": "fallback message",
"callback_id": "callback_button",
"color": "#3AA3E3",
"attachment_type": "default",
"actions": [{
"name": "Calender_set_Yes",
"text": "Yes",
"type": "button",
"value": "Yes"
},
{
"name": "Calender_set_No",
"text": "No",
"type": "button",
"value": "No"
}
]
}]
}
var url = "webhookのURL"
var options = {
"method" : "POST",
"headers": {"Content-type": "application/json"},
"channel" : "#nakashima-bot",
"payload" : JSON.stringify(data)
};
UrlFetchApp.fetch(url, options);
}}
Slack上のアクションに対する各スクリプトはひとまとめにしちゃってます。こんな感じ。
function doPost(e) {
var payload = JSON.parse(e["parameter"]["payload"]);
var value = payload["actions"][0]["value"];
//事前準備ア「Question_sheet」のアクション
if (value == "Question_sheet") {
debuck_spredsheet(value);
var set_company_and_name = unescape(payload["original_message"]["text"]).replace("さんのアポ楽しんでいこー!\n","");
var set_text = "--------------------------------------------------\n■社名・名前\n" + set_company_and_name + "\n\n■知ったきっかけ\n\n■担当領域、決済者\n\n■既存利用サービスと結果\n\n■採用計画\n\n■採用人材像\n\n■懸念点\n\n■その他\n\n--------------------------------------------------";
var reply = {
"replace_original": false,
"response_type": "in_channel",
"text": set_text,
};
}
//事前準備ア「Activity_search」のアクション
if (value == "Activity_search") {
debuck_spredsheet(value);
var set_companyname = unescape(payload["original_message"]["text"]).replace(/\u002f.*/,"").replace("\n","");
var reply = {
"replace_original": false,
"response_type": "in_channel",
"text": set_companyname + "の採用活動を調べます。こちらをクリックしてください。\n\n" + "https://demo-hrsearch.herokuapp.com/?csrfmiddlewaretoken=pURw2ppQvOIItg6ezaJAJP4eTxQw5QMVWS6aJYzbHPJglZH5ZC4KlvHpaaLkUzso&company_name=" + set_companyname,
};
}
//事後アンケート「Yes」のアクション
if (value == "Yes") {
debuck_spredsheet(value);
var set_title = unescape(payload["original_message"]["text"]).replace("のアポおつかれ!","");
createEvents(set_title)//登録関数を呼び出し
var reply = {
"replace_original": false,
"response_type": "in_channel",
"text": "カレンダーにリマインド予定を登録しました"
};
}
//事後アンケート「No」のアクション
if (value == "No") {
debuck_spredsheet(value);
var reply = {
"replace_original": false,
"response_type": "in_channel",
"text": value + "ですね。HubSpotに理由を記録しましょう。"
};
}
var output = ContentService.createTextOutput(JSON.stringify(reply));
output.setMimeType(ContentService.MimeType.JSON);
return output
}
//slackのpostを受け取り、カレンダーにリマインド日を登録する関数を定義
function createEvents(set_title, set_day) {
var calendar = CalendarApp.getDefaultCalendar();
var title = "【リマインド連絡】" + set_title;
var start_day = new Date();
start_day.setDate(start_day.getDate() + 7);//1週間後をセット
var end_day = new Date();
end_day.setDate(start_day.getDate()+ 3);//3日間リマインドを表示させたい
var option = {
description: '〇〇',
location: '■■'
}
calendar.createAllDayEvent(title, start_day, end_day, option);
}
//エラー確認用
function debuck_spredsheet(value) {
var spreadsheet = SpreadsheetApp.openById("シートID");
var sheet = spreadsheet.getSheetByName("出力用");
sheet.appendRow([new Date(),value + "までは来てる"]);
}
いつもありがとうございます!Twitterも良ければフォローお願いします!https://twitter.com/nakashimayugo