🌊

【自動化】GASを用いてGoogleフォームの回答をSlackへ通知する仕組みを実装

に公開

はじめに

「フォームの回答が来たら、すぐにSlackで気付きたい」

業務でGoogleフォームを使っていると、こんな場面によく遭遇します。問い合わせフォーム、申込みフォーム、社内アンケート……気付くのが遅れて対応漏れにつながることもありますよね。

この記事では、Google Apps Script(GAS)を使って、Googleフォームの回答をSlackに自動通知する仕組みをハンズオン形式で作っていきます。

こんな方におすすめ

  • GASを勉強中で、実用的なサンプルで手を動かしたい方
  • 業務効率化や自動化に興味がある方
  • Webhookを使ったAPI連携を体験してみたい方

この記事で学べること

  • SlackのIncoming Webhookの設定方法
  • GASから外部APIへのHTTPリクエストの送り方
  • フォーム送信をトリガーにしたGASの実行方法
  • Block Kitでリッチな通知メッセージを作る方法

完成イメージ

最終的に、以下の流れの自動化が完成します。

[Googleフォーム送信] → [スプレッドシートに記録] → [GASが起動] → [Slackに通知]

Slackには、回答内容と一緒にスプレッドシートへのリンクも届きます。担当者はSlackの通知をタップするだけで、すぐに回答を確認できます。

フォームからの回答画面

チャネルへの通知画面

事前準備

以下を用意してください。

  • Googleアカウント
  • 通知先のSlackワークスペース
  • 通知用のSlackチャンネル(例:#form-notifications)

実装手順

Step 1: SlackのIncoming Webhook URLを取得する

まずはSlack側の設定です。Incoming Webhookは、外部サービスからSlackへメッセージを送るための仕組みです。

  1. Slack APIにアクセスし、「Create New App」をクリック
  2. 「From scratch」を選び、アプリ名(例:Form Notifier)とワークスペースを設定
  3. 左メニューから「Incoming Webhooks」を選び、トグルを「On」に切り替え
  4. 「Add New Webhook to Workspace」をクリックし、通知先のチャンネルを選択
  5. 発行されたhttps://hooks.slack.com/services/...形式のURLをコピー

Step 2: Googleフォームとスプレッドシートを準備する

  1. Googleドライブで新しいフォームを作成
  2. 質問項目を追加(例:お名前メールアドレスお問い合わせ内容)
  3. 「回答」タブから「スプレッドシートにリンク」をクリックし、新規スプレッドシートを作成

これでフォーム回答がスプレッドシートに自動で蓄積される状態になります。

Step 3: Webhook URLをスクリプトプロパティに登録する

Webhook URLをコードに直書きすると、コードを共有したときに第三者へ漏れるリスクがあります。GASには「スクリプトプロパティ」という安全な設定値置き場があるので、コードを書く前にここへ登録しておきましょう。

  1. リンクしたスプレッドシートを開き、メニューから 拡張機能Apps Script を選択
  2. エディタ左メニュー下部の「プロジェクトの設定」(歯車アイコン)をクリック
  3. 「スクリプト プロパティ」セクションまでスクロールし、「スクリプト プロパティを追加」をクリック
  4. 以下を入力して「スクリプト プロパティを保存」をクリック
    • プロパティ:SLACK_WEBHOOK_URL
    • 値:Step 1でコピーしたWebhook URL

Step 4: GASでSlack通知のコードを書く

エディタに戻り、デフォルトのfunction myFunction()を削除して以下のコードを貼り付けてください。

// スクリプトプロパティからWebhook URLを取得
const SLACK_WEBHOOK_URL =
  PropertiesService.getScriptProperties().getProperty('SLACK_WEBHOOK_URL');

/**
 * フォーム送信時に実行される関数
 * @param {Object} e フォーム送信イベントオブジェクト
 */
function notifyOnFormSubmit(e) {
  // フォームの回答を取得
  const itemResponses = e.namedValues;

  // 通知メッセージを組み立てる
  let message = '📨 新しいフォーム回答が届きました\n\n';
  for (const question in itemResponses) {
    const answer = itemResponses[question][0];
    message += `*${question}*\n${answer}\n\n`;
  }

  // スプレッドシートのURLを末尾に追加
  const sheetUrl = SpreadsheetApp.getActiveSpreadsheet().getUrl();
  message += `<${sheetUrl}|スプレッドシートで確認する>`;

  // Slackに送信
  sendToSlack(message);
}

/**
 * Slackにメッセージを送信する
 * @param {string} text 送信するテキスト
 */
function sendToSlack(text) {
  const payload = { text: text };

  const options = {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify(payload),
  };

  UrlFetchApp.fetch(SLACK_WEBHOOK_URL, options);
}

コードのポイント解説

  • e.namedValues:フォームの質問名と回答が{質問: [回答]}の形式で格納されたオブジェクトです
  • UrlFetchApp.fetch():GASから外部URLにHTTPリクエストを送るメソッドです
  • Slackの記法では、*テキスト*で太字、<URL|表示テキスト>でリンク表示になります

Step 5: フォーム送信トリガーを設定する

GASをフォーム送信時に自動実行するように、トリガーを設定します。

  1. GASエディタの左メニューから「トリガー」(時計アイコン)を選択
  2. 右下の「トリガーを追加」をクリック
  3. 以下のように設定する
    • 実行する関数を選択:notifyOnFormSubmit
    • イベントのソース:スプレッドシートから
    • イベントの種類:フォーム送信時
  4. 「保存」をクリック(初回は権限の承認画面が表示されます)

Step 6: 動作確認

実際にフォームから回答を送信してみます。Slackに通知が届けば成功です。

通知が届かない場合は、以下を確認しましょう。

  • Webhook URLが正しくコピーされているか
  • 関数名がトリガー設定と一致しているか
  • GASエディタの「実行数」または「実行ログ」でエラーが出ていないか

応用編:Block Kitでリッチな通知にする

シンプルなテキスト通知でも十分ですが、SlackのBlock Kitを使うとレイアウトの整った見やすい通知が作れます。

sendToSlack関数を以下のように書き換えてみましょう。

function sendToSlack(itemResponses, sheetUrl) {
  // 質問と回答をフィールド配列に詰める
  const fields = [];
  for (const question in itemResponses) {
    fields.push({
      type: 'mrkdwn',
      text: `*${question}*\n${itemResponses[question][0]}`,
    });
  }

  const payload = {
    blocks: [
      {
        type: 'header',
        text: { type: 'plain_text', text: '📨 新しいフォーム回答', emoji: true },
      },
      {
        type: 'section',
        fields: fields,
      },
      {
        type: 'actions',
        elements: [
          {
            type: 'button',
            text: { type: 'plain_text', text: 'スプレッドシートを開く' },
            url: sheetUrl,
            style: 'primary',
          },
        ],
      },
    ],
  };

  const options = {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify(payload),
  };

  UrlFetchApp.fetch(SLACK_WEBHOOK_URL, options);
}

合わせて、呼び出し側のnotifyOnFormSubmitも以下のように書き換えます。

function notifyOnFormSubmit(e) {
  const sheetUrl = SpreadsheetApp.getActiveSpreadsheet().getUrl();
  sendToSlack(e.namedValues, sheetUrl);
}

これで、ヘッダー・本文・ボタンが整理されたリッチな通知が届くようになります。

Block Kitのレイアウトを試したい方へ

Slack公式のBlock Kit Builderを使うと、ブラウザ上でビジュアル的にレイアウトを作れます。生成されたJSONをblocksにコピーするだけで利用できるので、デザインの試行錯誤がはかどります。

つまずきやすいポイント

実装中に詰まりがちな箇所をまとめます。

トリガーの選択肢を間違える

トリガー設定には似た選択肢が複数あります。今回正しいのは 「スプレッドシートから」+「フォーム送信時」 の組み合わせです。「フォームから」を選ぶとフォーム編集時の発火になり、回答送信ではトリガーされません。

e.namedValuesundefinedになる

GASエディタから手動でnotifyOnFormSubmitを実行すると、引数eが渡されないためundefinedになります。動作確認はかならず実際のフォームから送信して行ってください。

デバッグ時にWebhook URLをログ出力しない

Logger.log(SLACK_WEBHOOK_URL)のように実行ログにURLを出力すると、プロジェクトの閲覧権限を持つ人にURLが見えてしまいます。デバッグ用のログ出力は、確認後すぐに削除する習慣をつけましょう。

万一URLが漏れたときはすぐに再発行する

スクリプトプロパティで管理していても、共有ミスなどでURLが外部に漏れる可能性はゼロではありません。漏洩の疑いがある場合は、Slack App管理画面から該当のIncoming Webhookを削除し、新しいURLを発行します。新URLでスクリプトプロパティを更新すれば、旧URL経由の不正投稿は遮断されます。

まとめ

GASとSlackのIncoming Webhookを組み合わせると、フォーム回答の見落としを防ぐ通知システムが30分ほどで作れます。

ポイントを振り返ります。

  • SlackのIncoming Webhookが連携の入り口
  • スクリプトプロパティでWebhook URLを安全に管理する
  • UrlFetchApp.fetch()で外部APIにリクエストを送れる
  • 「フォーム送信時」トリガーで自動実行を実現できる
  • Block Kitを使えば見やすい通知メッセージが作れる

この仕組みは応用が効きます。たとえば次のような展開が可能です。

  • 特定のキーワードを含む回答だけ通知する
  • 営業時間外の問い合わせは別チャンネルに振り分ける
  • Chatworkに通知先を変える(エンドポイントとリクエスト形式を差し替える)

業務に合わせてカスタマイズしてみてください。次回はChatwork版や、複数の通知先を条件で出し分けるパターンを書く予定です。

最後まで読んでいただき、ありがとうございました。

Discussion