Googleフォームの問合せをSlackに自動で通知してみよう
このレッスンのゴール
このレッスンでは、Googleフォームから、問い合わせがあった時にその結果をSlackに通知する方法を学びます。 完成すると、以下のような通知Botが起動して、フォームの内容を共有してくれます。
Googleフォームと、Slackを連携できると例えば、
- ライターさんが入稿を完了したときに報告するフォームの内容を、Slack通知する
- 入社書類の送信完了を、人事側で確認する
など、いろいろな用途に応用することが可能です。
このレッスンでできるようになること
このレッスンのプログラムを完成させることで、以下のことができるようになります。
- Googleフォームの送信をトリガーにGoogleAppsScriptを実行できる
- GoogleAppsScriptでGoogleフォームの情報を取得できる
- GoogleAppsScriptでメッセージをSlackへ通知できる
レッスン開始前のチェックリスト
このレッスンを始める前に、次に当てはまる方は、このレッスンを受講する前に必要な準備を終わらせましょう!
- Google Apps Scriptという用語を聞いたことがない
→前のレッスン「Google Apps Scriptとは?」をまずは受講しましょう - JavaScriptを書いたことがない
→まずはProgateでJavasrciptの基本を学びましょう - Googleのアカウントを持っていない
→GASの利用にはGoogleアカウントが必要です。こちらからアカウント作成をしましょう - SlackのIncoming Webhookを使ったことがない
→前のチュートリアル「Google Apps Script実践①」をまずは受講しましょう
このレッスンの流れ
それでははじめていきたいと思います。手順としては、以下のようになります。
- Slackの設定情報を定義する
- Googleフォームをトリガーに設定する
- Googleフォームの情報を受取る関数を実装する
- Slackにメッセージを送る関数を実装する
内容に入る前に、2つ事前準備があるのでそちらの設定をしていきましょう。
事前準備その1:Googleフォームを用意する
今回はGoogleフォームからの通知を、Slackへ送付するプログラムを作るので、Googleフォームをまずは用意する必要があります。 Google Driveにアクセスして、スプレッドシートを作成してください。
※すでに、Googleアカウントが存在する場合は、URLにspreadsheet.new
と入力すると、新規でスプレッドシートを作成することができます。 [無題のスプレッドシート]という名前になっているので、「問い合わせフォーム」という名前に変更しておきましょう。
次に、Google Spreadsheetの[ツール] > [フォーム作成]をクリックします。
フォームを作成したら、適当な質問を設定しておきましょう。
下記の画像では具体例を示しています。参考にしてみてください。
- 名前:記述式
- メールアドレス:記述式
- 質問内容:段落
次にGoogleフォームから、GoogleAppsScriptのエディタを開きましょう。
新規で作成すると、「無題のプロジェクト」となっているはずなので、[問い合わせスクリプト]に変更しておきましょう。 スクリプトエディアは、Google Apps Scriptを起動するためのツールです。
事前準備その2:SlackチャンネルとIncoming Webhookを用意する
次に、Slackチャンネルと、Incoming Webhookの設定をしましょう。Incoming Webhookとは、外部からSlackにデータを送った時に、そのデータを受け取るWebhookURLを取得するアプリのことです。
次の手順で取得できます。詳細はこちらのレッスンで画像付で流れを解説していますので、ご覧ください。
- SlackをWEBブラウザで開いて、画面右上の歯車のマークから、アプリを追加するを選ぶ
- 検索窓にincomingを入力し、Incoming Webhookアプリを選択する
- 設定を追加をクリックする
- チャンネルを選び、Incoming Webhookインテグレーションの追加をクリックする
- WebhookURLをコピーする
※注意:Incoming Webhookは、Slackの管理者、開発者権限がないと、利用することができません。会社で利用する場合、権限の関係でできない可能性があります。
これで事前準備は完了です!それではプログラムを実装していきましょう。
プログラムの全体像を確認しよう
それでは、さっそく実装していきましょう。 最終的なコードはこちらになります。
今すぐ全てが理解できなくて大丈夫です。詳細はこれから説明していきますので、ざっと全体を眺めておきましょう。
const CHANNEL = "contact"
const WEBHOOL_URL = "https://hooks.slack.com/services/XXXXXXXXXX"
function onFormSubmit(e){
let body = "";
const itemResponses = e.response.getItemResponses();
for (const index in itemResponses){
const itemResponse = itemResponses[index];
const title = itemResponse.getItem().getTitle();
const response = itemResponse.getResponse();
body += Utilities.formatString(title + ":" + response + "\n\n");
}
sendToSlack(body);
}
function sendToSlack(body) {
const data = {
"channel" : CHANNEL,
"text" : body,
"username" : "お問い合わせ通知",
"icon_url" : "https://4.bp.blogspot.com/-mfqbB0DfCDo/UTbWrZXNlPI/AAAAAAAAOic/lkRI5dseik4/s400/bird_hato.png"
};
const payload = JSON.stringify(data);
const options = {
"method" : "POST",
"contentType" : "application/json",
"payload" : payload
};
UrlFetchApp.fetch(WEBHOOL_URL, options);
}
このコードは、大きく2つの関数に分かれています。
- Google フォームからデータを受け取るonFormSubmit関数
- Slackにデータを送信するsendToSlack関数
この後詳細を説明していきます。一緒に頑張りましょう!
Step1. Slackの設定情報を定義しよう
最初に通知するSlackのチャンネル名と、Webhook URLを定義します。
WebhookURLには事前準備で取得した内容をコピーペーストしましょう
const CHANNEL = "contact"
const WEBHOOL_URL = "https://hooks.slack.com/services/XXXXXXXXXXXXXX"
Step2. Googleフォームをトリガーに設定しよう
次にGoogleフォームが送信されたときに、関数が実行されるようにトリガーを設定しましょう。
最初にonFormSubmit関数を定義しておきます。実際の処理は次のステップで実装します。
const CHANNEL = "contact"
const WEBHOOL_URL = "https://hooks.slack.com/services/XXXXXXXXXXXX"
function onFormSubmit(e){
}
e
次にトリガーを設定します。 トリガーとは、「こんな時に、こういう処理をしてね!」という設定を行うことができる機能です。
- IF : もし~したら
- THEN: ~する
の、IFにあたる部分と、THENにあたる部分を設定できます。今回は、
- IF: フォームが送信されたときに
- THEN: Slack通知する関数を起動する
というアクションになります。 それではさっそく設定していきましょう。下記の画像に沿って設定してみましょう。
トリガーは次のように設定します。
- イベントのソースを選択:フォームから
- イベントの種類を選択:フォーム送信時
[保存]をクリックすると、Googleアカウントに許可を出す画面が出てくるので、案内に従って承認をしてください。
これでStep1が完了です。
Step3. Googleフォームの情報を受取る関数を実装しよう
それでは、onFormSubmit関数を実装します。コードの中身は以下のようになっています。
一つひとつ詳細を見ていきましょう。
const CHANNEL = "contact"
const WEBHOOL_URL = "https://hooks.slack.com/services/XXXXXXXXXXX"
function onFormSubmit(e){
let body = "";
const itemResponses = e.response.getItemResponses();
for (const index in itemResponses){
const itemResponse = itemResponses[index];
const title = itemResponse.getItem().getTitle();
const response = itemResponse.getResponse();
body += Utilities.formatString(title + ":" + response + "\n\n");
}
sendToSlack(body);
}
onFormSubmit関数を設定する
function onFormSubmit(e){ }
まず事前にセットしておいた、onFormSubmit関数は、実はGoogle Apps Script上で事前に用意されている関数(組み込み関数)です。フォームが送信されたときに、起動される関数で、引数のeには、フォームの申込情報が入るようになっています。
こちらのリンクで関数の説明が見れますので、一度見てみてください。英語ですが、プログラミングの学習にAPIのライブラリ情報を見るのは重要なので、ぜひ挑戦してみましょう。
https://developers.google.com/apps-script/reference/script/form-trigger-builder#onformsubmit
ログを残して、データを受け取れているか確認する
それでは試しに関数を起動させて、情報が受け取れているか確認してみましょう。
上記のコードに、ログを残すことで、実行されたか確認してみます。
まずは確認するために、console.log(e)を追記します。
const CHANNEL = "contact"
const WEBHOOL_URL = "https://hooks.slack.com/services/XXXXXXXXXXXXX"
function onFormSubmit(e){
console.log (e); //1 ログを残すために、console.logで出力します
}
Google Formから試しに回答を一度送ってみましょう。
先ほど作成したGoogleフォームの送信
をクリックし、フォームの回答URLへアクセスして、適当な内容で回答を送信しましょう。
Google Apps Scriptでログを確認する場合は、[実行数]を選びましょう。トリガーで起動したonFormSubmit
関数がきちんと動いていることが確認できたら、成功です!
フォームの内容を取得する
次に、フォームの内容を取得するための処理を書いていきたいと思います。
先ほど追加した、console.log(e)は確認用のコードなので削除して、続きを書いていきます。
const CHANNEL = "contact"
const WEBHOOL_URL = "https://hooks.slack.com/services/XXXXXXXXXXX"
function onFormSubmit(e){
let body = "";
}
まずSlackに通知するメッセージを格納する、bodyという変数を定義します。
letにしている理由は、今後再代入して、メッセージを追加していくためです。constを利用してしまうと、値を再代入できません。
getItemResponses関数の値の中身を取得する
次に、Googleフォームから受け取った情報を、どうやって確認するか見てみましょう。
Google Formから受け取った情報はFormResponse
オブジェクトとして、e.response
で取得することができます。
そのFormResponse
オブジェクトに対して、getItemResponses
関数を実行することで、中身を取得することができます。
const CHANNEL = "contact"
const WEBHOOL_URL = const WEBHOOL_URL = "https://hooks.slack.com/services/XXXXXXXXXXXXXXX"
function onFormSubmit(e){
let body = "";
const itemResponses = e.response.getItemResponses();
}
取得したitemResponsesは、次のような構成になっています。
itemResponsesの中には、title(質問文)とresponse(その回答)から構成されるitemResponseがたくさん入っている、という構成です。itemResponsesが取得できたら、今度はそこからitemResponseを取り出し、更にそこからtitleとresponseをそれぞれ取得する、という流れになります。
詳細を見ていく前に、一度Google Formの公式APIドキュメントを見てみましょう。
Class FormResponse
日本語に翻訳すると、以下のように書いてあります。
フォーム全体に対するレスポンス。FormResponse は 3 つの方法で使用することができます: 回答者によって提出された回答にアクセスする (getItemResponses() を参照)、プログラムによってフォームに回答を送信する (withItemResponse(response) と submit() を参照)、そして提供された回答を使ってフィールドをプリフィルするフォームの URL を生成することです。FormResponses はフォームから作成したりアクセスしたりすることができます。
リファレンスにあるサンプルコードを見てみます。
このコードを参考に、質問と回答を取得していきます。
// Open a form by ID and log the responses to each question.
var form = FormApp.openById('1234567890abcdefghijklmnopqrstuvwxyz');
var formResponses = form.getResponses();
for (var i = 0; i < formResponses.length; i++) {
var formResponse = formResponses[i];
var itemResponses = formResponse.getItemResponses();
for (var j = 0; j < itemResponses.length; j++) {
var itemResponse = itemResponses[j];
Logger.log('Response #%s to the question "%s" was "%s"',
(i + 1).toString(),
itemResponse.getItem().getTitle(),
itemResponse.getResponse());
}
}
itemResponsesオブジェクトから、itemResponseを取り出す
さて、それではitemResponseのリストであるitemResponsesが現在取得できているので、これからそれぞれの回答を取得していきます。
リストから一つずつ値を展開する場合は、for in
を利用します。
const CHANNEL = "contact"
const WEBHOOL_URL = const WEBHOOL_URL = "https://hooks.slack.com/services/XXXXXXXXXXXXXXX"
function onFormSubmit(e){
let body = "";
const itemResponses = e.response.getItemResponses();
for (const index in itemResponses){
//取得したitemResponsesを、一つずつfor文で書き出す }
}
}
複数のリストオブジェクトに対して、インデックス番号を指定してあげると、中身のオブジェクトを取得することができます。 それでは、次に質問内容を取得してみましょう。
const CHANNEL = "contact"
const WEBHOOL_URL = "https://hooks.slack.com/services/XXXXXXXXXXXXXXX"
function onFormSubmit(e){
let body = "";
const itemResponses = e.response.getItemResponses();
for (const index in itemResponses){
const itemResponse = itemResponses[index];
}
}
質問と回答を取得する
次に質問と答えのセットとなったitemResponseオブジェクトから、質問内容のタイトルと回答を取得します。
それぞれ、getTitle()とgetResponse()という関数を使って取得できます。
const CHANNEL = "contact"
const WEBHOOL_URL = "https://hooks.slack.com/services/XXXXXXXXXXXXXXX"
function onFormSubmit(e){
let body = "";
const itemResponses = e.response.getItemResponses();
for (const index in itemResponses){
const itemResponse = itemResponses[index];
const title = itemResponse.getItem().getTitle(); //質問と答えのセットとなったitemResponseオブジェクトから、質問内容のタイトルを取得する
const response = itemResponse.getResponse(); //質問と答えのセットとなったitemResponseオブジェクトからgetResponse関数で答えを出力する
}
}
Slackに送信するテキストの内容を作成する
これでGoogleフォームの質問と回答を取得できました。
それではこのステップの最後に、Slackに送信するためのテキストの内容を作成しましょう。
内容はシンプルで、最初に定義しておいたbodyに、取得したtitleとresponseを追加するだけです。
const CHANNEL = "contact"
const WEBHOOL_URL = "https://hooks.slack.com/services/XXXXXXXXXXXXXXX"
function onFormSubmit(e){
let body = "";
const itemResponses = e.response.getItemResponses();
for (const index in itemResponses){
const itemResponse = itemResponses[index];
const title = itemResponse.getItem().getTitle(); //質問と答えのセットとなったitemResponseオブジェクトから、質問内容のタイトルを取得する
const response = itemResponse.getResponse(); //質問と答えのセットとなったitemResponseオブジェクトからgetResponse関数で答えを出力する
body += title + ":" + response + "\n\n";
}
}
Slackに送信する関数を先に定義しておく
それでは、次のステップで作るSlackにメッセージを送るための関数、sendToSlack()関数を最後に呼び出すコードを追記します。
sendToSlack関数は、先ほど作成したbodyを引数にして呼び出します。
const CHANNEL = "contact"
const WEBHOOL_URL = "https://hooks.slack.com/services/XXXXXXXXXXXXXXX"
function onFormSubmit(e){
let body = "";
const itemResponses = e.response.getItemResponses();
for (const index in itemResponses){
const itemResponse = itemResponses[index];
const title = itemResponse.getItem().getTitle(); //質問と答えのセットとなったitemResponseオブジェクトから、質問内容のタイトルを取得する
const response = itemResponse.getResponse(); //質問と答えのセットとなったitemResponseオブジェクトからgetResponse関数で答えを出力する
body += title + ":" + response + "\n\n";
}
sendToSlack(body);
}
これでこのステップが完了です!次はいよいよsendToSlack関数を実装していきます。
Step4. Slackにメッセージを送る関数を実装する
このステップでは、Slackにメッセージを送るsendToSlack()関数を実装します。
最終的には次のようなコードになります。
function sendToSlack(body) {
const data = {
"channel" : CHANNEL,
"text" : body,
"username" : "お問い合わせ通知",
"icon_url" : "https://4.bp.blogspot.com/-mfqbB0DfCDo/UTbWrZXNlPI/AAAAAAAAOic/lkRI5dseik4/s400/bird_hato.png"
};
const payload = JSON.stringify(data);
const options = {
"method" : "POST",
"contentType" : "application/json",
"payload" : payload
};
UrlFetchApp.fetch(WEBHOOL_URL, options);
}
コード全体
順番にコードを解説していきたいところなのですが、その前に、まずはGoogleフォームと連携せず「test」とだけSlackにメッセージを送る仕様で実装してみましょう。実際にメッセージが送れることを確認したら、送信内容を送りたいメッセージに変更していきます。
では順番に解説していきます。
sendToSlack関数を定義する
まずは関数を定義します。見た目がシンプルになるように、前のステップで作った部分は今回は写していません。コードの下に追記していきましょう。
function sendToSlack(){
}
JSONで送信したい内容を連想配列形式で設定しよう
次に、メッセージの内容や、送付先のチャンネル名、ユーザー名やアイコンなどを設定します。
今回は変数dataの中に、連想配列形式で、データをセットします。ここで入れる値はテスト用なので、実装が確認できたら後から変更します。
function sendToSlack() {
const data = {
"channel" : "contact",
"text" : "test",
"username" : "お問い合わせ通知",
"icon_url" : "https://4.bp.blogspot.com/-mfqbB0DfCDo/UTbWrZXNlPI/AAAAAAAAOic/lkRI5dseik4/s400/bird_hato.png"
};
}
この設定では、下記のように表示されるはずです。
- チャンネル名:contact
- 送付されるメッセージ:test
- ユーザネーム:お問合せ通知
- アイコン:鳩のアイコン
連想配列をJSON化しよう
次に、Slack Web APIで利用できるJSON形式に、連想配列dataを変更します。
ここではJSON.stringify()という関数を利用します。
function sendToSlack() {
const data = {
"channel" : "contact",
"text" : "test",
"username" : "お問い合わせ通知",
"icon_url" : "https://4.bp.blogspot.com/-mfqbB0DfCDo/UTbWrZXNlPI/AAAAAAAAOic/lkRI5dseik4/s400/bird_hato.png"
};
const payload = JSON.stringify(data);
}
Optionを設定しよう
次にSlackへメッセージを送るために必要な値をOptionで指定します。指定するのは、method、contentType、payloadの3つです。
function sendToSlack() {
const data = {
"channel" : "contact",
"text" : "test",
"username" : "お問い合わせ通知",
"icon_url" : "https://4.bp.blogspot.com/-mfqbB0DfCDo/UTbWrZXNlPI/AAAAAAAAOic/lkRI5dseik4/s400/bird_hato.png"
};
const payload = JSON.stringify(data);
const options = {
"method" : "POST",
"contentType" : "application/json",
"payload" : payload
};
}
URLFetchApp.fetch()を使ってSlackへ送信する
では最後に設定した内容を、取得しておいたWEBHOOK_URLを利用して送付しましょう。
function sendToSlack() {
const data = {
"channel" : "contact",
"text" : "test",
"username" : "お問い合わせ通知",
"icon_url" : "https://4.bp.blogspot.com/-mfqbB0DfCDo/UTbWrZXNlPI/AAAAAAAAOic/lkRI5dseik4/s400/bird_hato.png"
};
const payload = JSON.stringify(data);
const options = {
"method" : "POST",
"contentType" : "application/json",
"payload" : payload
};
const response = UrlFetchApp.fetch(WEBHOOK_URL, options);
}
ここまで設定できたら、実行してみましょう。今回はテスト用に、sendToSlack関数だけで実行できるようにしてあるので、GoogleAppsScriptのエディタから、実行する関数を「sendToSlack」に変更してから実行ボタンを押しましょう。
実行すると、許可が求められるので、指示に従って権限を許可してください。
指定したSlackのチャンネルに、鳩から画像のようにメッセージがくれば成功です!
Googleフォームの回答をSlackに送る仕様を実装する
それでは最後に、Googleフォームの回答内容をSlackに送る仕様に、sendToSlack関数を変更しましょう。
変更した箇所は3箇所です。
- sendToSlack関数の引数にbodyを追加する
- "channel"の値を、コードの最初で定義した変数CHANNELに変更する
- "text"の値を、引数に入れたbodyに変更する
function sendToSlack(body) {
const data = {
"channel" : CHANNEL,
"text" : body,
"username" : "お問い合わせ通知",
"icon_url" : "https://4.bp.blogspot.com/-mfqbB0DfCDo/UTbWrZXNlPI/AAAAAAAAOic/lkRI5dseik4/s400/bird_hato.png"
};
const payload = JSON.stringify(data);
const options = {
"method" : "POST",
"contentType" : "application/json",
"payload" : payload
};
const response = UrlFetchApp.fetch(WEBHOOK_URL, options);
}
これで完成!と言いたいところなのですが、もう一つだけやることがあります。
Google Apps Scriptでは、Slackなど他のアプリと連携をする際には、実行の許可をする必要があります。今回はGoogleAppsScriptからSlackへの通知は許可しているのですが、別途Googleフォームの情報を外部アプリに通知を出す際にも許可が必要です。
そこで、事前に作成していた、onFormSubmitにFormApp.getActiveForm();を追記して、GoogleAppsScriptエディタから一度関数を実行しておきます。実行する関数を「onFormSubmit」に変更してから実行ボタンを押しましょう。うまくいっていれば許可を求められるので、許可をして、追加した行を削除します。
function onFormSubmit(e){
FormApp.getActiveForm(); //許可を与えるために追加した行
let body = "";
const itemResponses = e.response.getItemResponses();
for (const index in itemResponses){
const itemResponse = itemResponses[index];
const title = itemResponse.getItem().getTitle();
const response = itemResponse.getResponse();
body += Utilities.formatString(title + ":" + response + "\n\n");
}
sendToSlack(body);
}
お疲れ様でした、これで完成です!
最後に全体のプログラムを確認してみましょう。
const CHANNEL = "contact"
const WEBHOOL_URL = "https://hooks.slack.com/services/XXXXXXXXXXXX"
function onFormSubmit(e){
let body = "";
const itemResponses = e.response.getItemResponses();
for (const index in itemResponses){
const itemResponse = itemResponses[index];
const title = itemResponse.getItem().getTitle();
const response = itemResponse.getResponse();
body += Utilities.formatString(title + ":" + response + "\n\n");
}
sendToSlack(body);
}
function sendToSlack(body) {
const data = {
"channel" : CHANNEL,
"text" : body,
"username" : "お問い合わせ通知",
"icon_url" : "https://4.bp.blogspot.com/-mfqbB0DfCDo/UTbWrZXNlPI/AAAAAAAAOic/lkRI5dseik4/s400/bird_hato.png"
};
const payload = JSON.stringify(data);
const options = {
"method" : "POST",
"contentType" : "application/json",
"payload" : payload
};
UrlFetchApp.fetch(WEBHOOL_URL, options);
}
それでは動作テストをしてみましょう。 Apps Scriptエディタを起動して、ログを見れる状態にしたまま、Google Formを送信してみましょう。 うまくいくと、contactというチャンネルに、メッセージが送信されます。