Google Formsの投稿をGASでSlackに通知する仕組みを作った

複数のWebサイトを運営していて、それぞれにGoogle Formを設置しています。投稿に気づかず対応が遅れることがあったので、GASでSlackに自動通知する仕組みを作りました。

やりたかったこと

  • Google Formに回答が来たらSlackに通知
  • フォームごとに通知先チャンネルを変えたい
  • フォームが増えても同じコードを何度も書きたくない

構成

GASではスクリプトがフォームと1対1で紐づく(「コンテナ」と呼ばれる制約)ので、1つのスクリプトを複数フォームで共有できません。そこで入口と本体を分離しました。

  • 入口スクリプト — 各フォームに配置。呼び出すだけの数行
  • Parser — 共通ライブラリ。フォームのレスポンスを解析して通知テキストを組み立てる
  • Slack送信 — 共通ライブラリ。Slack APIを叩いて投稿する

GAS:Google Form → Slack 通知の構成

入口はこれだけです。

function call(form) {
  GoogleFormParser.parse(form)
}

フォーム追加時は入口スクリプトを置いて、スクリプトエディタからトリガー(フォーム送信時に call を実行)を設定するだけ。本体の修正は共通ライブラリ側で完結します。

Slack App を使う

Slackへの通知はIncoming Webhook(レガシー)とSlack Appの2択です。

  • レガシーWebhook: 設定は簡単だが、Slack公式が非推奨
  • Slack App: 初期設定はやや手間だが、Bot Tokenのスコープ制御・チャンネル指定が柔軟

将来使えなくなるリスクを避けてSlack Appを選びました。Incoming Webhookは hooks.slack.com/services/... 形式のURLにPOSTする方式ですが、こちらはSlack Web APIの chat.postMessage をBot Token認証で呼んでいます。

トークンはGASの PropertiesService に保存しています。

const token = PropertiesService.getScriptProperties().getProperty("SLACK_BOT_TOKEN");

function callWebApi(apiMethod, payload) {
  const response = UrlFetchApp.fetch(
    `https://slack.com/api/${apiMethod}`,
    {
      method: "post",
      contentType: "application/json; charset=utf-8",
      headers: { "Authorization": `Bearer ${token}` },
      payload: JSON.stringify(payload),
    }
  );
  return response;
}

function sendMessage(textMessage, channel) {
  if (!channel) {
    channel = "#general";
  }

  callWebApi("chat.postMessage", {
    text: textMessage,
    channel: channel
  });
}

Related Posts