GAS業務自動化 |

GASでSlack通知を自動送信する方法|Webhook連携の手順

GASとSlack Incoming Webhookを連携して業務通知を自動化するイメージ図

スプレッドシートの更新やフォームの回答があるたびに、Slackを開いて手動で報告する。こうした作業を毎日繰り返していると、1回あたりは数十秒でも、月単位では無視できない時間になります。Google Apps Script(GAS)とSlackのIncoming Webhookを組み合わせれば、こうした通知作業をゼロにできます。この記事では、Webhook URLの取得からGASのコード実装、運用時に押さえておきたいエラー処理やセキュリティ対策まで、Slack通知の自動化に必要な手順を一つずつ解説します。

GASとSlack Webhookで通知を自動化する仕組み

GASからSlackへ通知を送る仕組みは、Incoming Webhookという機能を使います。Incoming Webhookは、Slackが提供するURLに対してHTTPリクエスト(POST)を送信すると、指定したチャンネルにメッセージが投稿される仕組みです。

GASにはUrlFetchAppというHTTP通信用のクラスが標準で用意されています。このUrlFetchAppのfetchメソッドを使い、Webhook URLに対してJSON形式のペイロードをPOSTするだけで、Slackにメッセージを投稿できます。外部ライブラリのインストールやサーバーの構築は不要です。

全体の処理フロー

処理の流れを整理すると、次のようになります。

  1. Slackワークスペースの管理画面でIncoming Webhook Appを追加し、Webhook URLを発行する
  2. GASのスクリプトエディタにコードを書き、Webhook URLに対してPOSTリクエストを送る関数を作成する
  3. GASのトリガー機能で「スプレッドシート編集時」「フォーム送信時」「毎日○時」などの条件を設定する
  4. 条件が満たされると自動的にGASが起動し、Slackの指定チャンネルにメッセージが届く

この仕組みのメリットは、Google Workspaceの各アプリケーション(スプレッドシート、フォーム、カレンダーなど)と直接連携できる点にあります。GASはこれらのアプリケーションのデータに直接アクセスできるため、「スプレッドシートの特定セルの値が変わったら通知」「フォームの回答内容をそのまま通知」といった連携がコードだけで完結します。

Incoming WebhookとSlack APIの違い

Slackへの通知方法は、大きく分けてIncoming WebhookとSlack API(Web API)の2種類があります。用途に合わせて選ぶ必要がありますが、「決まったチャンネルにメッセージを送るだけ」であればIncoming Webhookで十分です。

比較項目 Incoming Webhook Slack Web API
セットアップ URLを1つ取得するだけ OAuth認証とスコープ設定が必要
送信先 URL発行時に固定されたチャンネル 任意のチャンネルやDMに動的に指定可能
機能範囲 メッセージ投稿のみ メッセージ投稿・ファイルアップロード・チャンネル操作など多機能
適した用途 定型通知・アラート・日報 双方向のやりとりが必要なBot開発

この記事では、導入のハードルが低く実務での利用頻度が高いIncoming Webhookを中心に解説します。

事前準備 ── Slack側でWebhook URLを取得する

GASのコードを書く前に、まずSlack側でWebhook URLを発行します。この作業はSlackのワークスペース管理者、またはアプリのインストール権限を持つメンバーが行えます。

手順1: Slack Appを作成する

Slack APIの公式サイト(api.slack.com/apps)にアクセスし、「Create New App」をクリックします。作成方法は「From scratch」を選択してください。App Nameには「GAS通知」など用途がわかる名前を入力し、通知を送りたいワークスペースを選択します。

手順2: Incoming Webhookを有効化する

作成したAppの設定画面で、左側メニューから「Incoming Webhooks」を選び、画面上部のトグルスイッチをONにします。

手順3: Webhook URLを発行する

「Add New Webhook to Workspace」ボタンをクリックすると、通知先のチャンネルを選択する画面が表示されます。投稿先のチャンネルを選んで「許可する」をクリックすると、Webhook URLが発行されます。

発行されるURLは以下の形式です。

https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX

このURLは認証情報そのものです。外部に漏洩すると、誰でもそのチャンネルにメッセージを投稿できてしまいます。URLの管理方法については後半のセキュリティの章で詳しく解説します。

GASでSlack通知を送る基本コード

Webhook URLを取得したら、GASのスクリプトエディタでコードを書いていきます。スプレッドシートの「拡張機能」メニューから「Apps Script」を開くか、script.google.comに直接アクセスしてプロジェクトを新規作成してください。

最小構成のコード

まずは動作確認用の最小コードです。このコードを実行して、Slackにメッセージが届くことを確認してください。

function sendSlackNotification() {
  const webhookUrl = PropertiesService.getScriptProperties().getProperty('SLACK_WEBHOOK_URL');

  const payload = {
    text: 'GASからのテスト通知です。'
  };

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

  const response = UrlFetchApp.fetch(webhookUrl, options);
  Logger.log(response.getContentText());
}

UrlFetchApp.fetchの戻り値であるHTTPResponseオブジェクトのgetContentTextメソッドを呼ぶと、正常に送信できた場合は「ok」という文字列が返ります。エラーの場合は「invalid_payload」などのエラーメッセージが返ります。

Webhook URLをスクリプトプロパティに保存する

上のコードでは、Webhook URLをソースコードに直接書かず、スクリプトプロパティから読み込んでいます。Webhook URLは認証情報に該当するため、コード内にハードコードするのは避けるべきです。

スクリプトプロパティの設定手順は次のとおりです。

  1. Apps Scriptエディタの左側メニューで歯車アイコン(プロジェクトの設定)をクリックする
  2. 画面下部の「スクリプトプロパティ」セクションで「スクリプトプロパティを追加」をクリックする
  3. プロパティ名に「SLACK_WEBHOOK_URL」、値にWebhook URLを貼り付けて保存する

これにより、コードをGitHubなどで共有する場合でもWebhook URLが漏洩するリスクを回避できます。

送信者名とアイコンをカスタマイズする

payloadオブジェクトに「username」と「icon_emoji」を追加すると、通知の送信者名とアイコンを変更できます。

const payload = {
  text: '日次売上レポートを送信します。',
  username: '売上レポートBot',
  icon_emoji: ':bar_chart:'
};

ただし、この機能はSlack Appの設定で「Customize the name and icon」が有効になっている場合のみ動作します。Slack Appの管理画面で設定を確認してください。

無料ダウンロード

業務自動化でできること100選

経理・人事・営業・CS・総務・ITの6部門100事例を収録。各事例に月間削減時間と導入難易度を明記。今日から始められるチェックリスト付き。

無料ダウンロード

実務で使える応用パターン5選

基本の送信方法が理解できたら、実務で頻出するパターンを見ていきましょう。いずれもGASの標準機能だけで実装できます。

パターン1: スプレッドシートの更新をSlackに通知する

最も利用頻度が高いパターンです。スプレッドシートのonEditトリガーを使い、特定のセルが変更されたときにSlackへ通知を送ります。

function onEditNotification(e) {
  const sheet = e.source.getActiveSheet();
  const range = e.range;

  // 「受注管理」シートのステータス列(C列)が変更された場合のみ通知
  if (sheet.getName() !== '受注管理' || range.getColumn() !== 3) return;

  const row = range.getRow();
  const clientName = sheet.getRange(row, 1).getValue();
  const projectName = sheet.getRange(row, 2).getValue();
  const newStatus = range.getValue();

  const message = `*ステータス更新*\n顧客: ${clientName}\n案件: ${projectName}\n新ステータス: ${newStatus}`;

  sendToSlack(message);
}

function sendToSlack(text) {
  const webhookUrl = PropertiesService.getScriptProperties().getProperty('SLACK_WEBHOOK_URL');
  const options = {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify({ text: text })
  };
  UrlFetchApp.fetch(webhookUrl, options);
}

onEditトリガーはGASの「編集時」イベントで発火します。シート名やカラム番号で条件を絞ることで、不要な通知を防げます。

パターン2: Googleフォームの回答をSlackに即時通知する

問い合わせフォームやアンケートの回答が届いたときに、Slackで即座にチームに共有するパターンです。

function onFormSubmit(e) {
  const responses = e.namedValues;

  let message = '*新しいお問い合わせ*\n';
  for (const key in responses) {
    message += `${key}: ${responses[key]}\n`;
  }

  sendToSlack(message);
}

このスクリプトはフォームに紐づくApps Scriptプロジェクトに配置し、「フォーム送信時」トリガーを設定します。e.namedValuesを使うと、フォームの質問名をキーとして回答を取得できるため、通知メッセージに質問と回答をそのまま含められます。

パターン3: 毎朝の日次レポートを定時送信する

スプレッドシートの集計結果を毎朝9時にSlackへ送信するパターンです。時間主導型トリガーを使います。

function sendDailyReport() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('売上サマリ');
  const today = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/MM/dd');
  const totalSales = sheet.getRange('B2').getValue();
  const orderCount = sheet.getRange('C2').getValue();

  const message = `*${today} 日次レポート*\n売上合計: ${totalSales.toLocaleString()}円\n受注件数: ${orderCount}件`;

  sendToSlack(message);
}

パターン4: エラー発生時にアラートを飛ばす

GASで別の自動処理(データ連携やファイル生成など)を動かしている場合、その処理がエラーで失敗したときにSlackへアラートを飛ばせると便利です。try-catchで例外を捕捉し、エラー情報をSlackに送ります。

function runDataSync() {
  try {
    // データ連携処理
    syncExternalData();
  } catch (error) {
    const message = `*エラー発生*\n関数: runDataSync\nエラー: ${error.message}\nスタック: ${error.stack}`;
    sendToSlack(message);
  }
}

パターン5: 期限切れタスクを毎日チェックして通知する

スプレッドシートのタスク管理表を毎日チェックし、期限が今日または過ぎているタスクをSlackに通知するパターンです。

function checkDeadlines() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('タスク');
  const data = sheet.getDataRange().getValues();
  const today = new Date();
  today.setHours(0, 0, 0, 0);

  const overdueTasks = [];

  for (let i = 1; i < data.length; i++) {
    const taskName = data[i][0];
    const deadline = new Date(data[i][2]);
    const status = data[i][3];

    deadline.setHours(0, 0, 0, 0);

    if (status !== '完了' && deadline <= today) {
      overdueTasks.push(`- ${taskName}(期限: ${Utilities.formatDate(deadline, 'Asia/Tokyo', 'MM/dd')})`);
    }
  }

  if (overdueTasks.length > 0) {
    const message = `*期限切れ・本日期限のタスク(${overdueTasks.length}件)*\n${overdueTasks.join('\n')}`;
    sendToSlack(message);
  }
}

Block Kit対応 ── 通知のデザインを整える

テキストだけの通知でも十分に機能しますが、Slackの「Block Kit」を使うと、見出し・区切り線・ボタンなどの視覚要素を含んだリッチなメッセージを送れます。通知の量が増えてきたときに情報の視認性を上げる手段として有効です。

Block Kitの基本構造

Block KitはJSON配列でメッセージのブロックを定義します。payloadの「blocks」プロパティに配列を渡すことで、複数のブロックを組み合わせたメッセージを構築できます。

function sendRichNotification() {
  const webhookUrl = PropertiesService.getScriptProperties().getProperty('SLACK_WEBHOOK_URL');

  const payload = {
    blocks: [
      {
        type: 'header',
        text: { type: 'plain_text', text: '月次売上レポート' }
      },
      {
        type: 'section',
        fields: [
          { type: 'mrkdwn', text: '*売上合計*\n1,250,000円' },
          { type: 'mrkdwn', text: '*前月比*\n+12.5%' }
        ]
      },
      { type: 'divider' },
      {
        type: 'section',
        text: { type: 'mrkdwn', text: '詳細はスプレッドシートをご確認ください。' },
        accessory: {
          type: 'button',
          text: { type: 'plain_text', text: 'シートを開く' },
          url: 'https://docs.google.com/spreadsheets/d/xxxxx'
        }
      }
    ]
  };

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

  UrlFetchApp.fetch(webhookUrl, options);
}

よく使うBlock Kitのブロックタイプ

ブロックタイプ 用途 使用例
header メッセージのタイトルを大きく表示する 「月次レポート」「アラート」などの見出し
section テキストやフィールドを表示する 本文の表示、KPIの並列表示
divider 水平の区切り線を表示する セクション間の視覚的な区切り
actions ボタンやメニューを配置する 「承認する」「確認する」ボタン
context 補足情報を小さい文字で表示する 送信日時、データソースの注記

Block Kitのレイアウトを視覚的に設計したい場合は、Slackが提供するBlock Kit Builderが便利です。画面上でブロックを配置しながらJSONを生成できるため、コードに手で書くよりも効率的に設計できます。

エラー処理とリトライの実装

GASからSlackへの通知は通常であれば安定して動作しますが、ネットワークの一時的な問題やSlack側の障害によって送信に失敗するケースがあります。特に業務の重要な通知に使う場合は、エラー処理とリトライの仕組みを入れておくと安心です。

HTTPステータスコードによるエラー判定

UrlFetchApp.fetchは、HTTPステータスコードが200以外の場合に例外をスローします。muteHttpExceptionsオプションをtrueに設定すると例外を抑制でき、ステータスコードを自分で判定できるようになります。

function sendToSlackWithRetry(text, maxRetries) {
  maxRetries = maxRetries || 3;
  const webhookUrl = PropertiesService.getScriptProperties().getProperty('SLACK_WEBHOOK_URL');

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

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    const response = UrlFetchApp.fetch(webhookUrl, options);
    const statusCode = response.getResponseCode();

    if (statusCode === 200) {
      Logger.log('送信成功');
      return true;
    }

    Logger.log('送信失敗 (試行 ' + attempt + '/' + maxRetries + '): ' + statusCode + ' - ' + response.getContentText());

    if (attempt < maxRetries) {
      Utilities.sleep(2000 * attempt); // 指数バックオフ風に待機
    }
  }

  Logger.log('全リトライ失敗');
  return false;
}

よく発生するエラーと対処法

ステータスコード 原因 対処法
400 payloadのJSON形式が不正 JSON.stringifyの結果をログで確認する
403 Webhook URLが無効化された Slack Appの管理画面でWebhookが有効か確認する
404 Webhook URLが削除された 新しいWebhook URLを再発行する
429 レート制限に該当した(1秒1リクエスト超過) 送信間隔を空ける。バッチ処理の場合はUtilities.sleepを挟む
500 Slack側の障害 時間をおいてリトライする

特に注意が必要なのは429(レート制限)です。Incoming Webhookは1秒あたり1リクエストが目安とされています。ループ処理で連続送信する場合はUtilities.sleep(1000)を挟んで、1秒以上の間隔を確保してください。

セキュリティとWebhook URLの管理

Incoming Webhookは手軽に使える反面、URLの管理を怠るとセキュリティリスクにつながります。Webhook URLを知っている人は、認証なしでそのチャンネルにメッセージを投稿できるためです。

Webhook URLの安全な管理方法

前述のとおり、GASのスクリプトプロパティに保存するのが基本です。加えて以下の点を守ることで、漏洩リスクを下げられます。

  • ソースコードにWebhook URLを直接記述しない。スクリプトプロパティかGASのシークレットマネージャーを使う
  • Webhook URLをメールやチャットで共有しない。必要な場合はSlack Appの管理画面のURLを案内し、権限のあるメンバーが自分で確認する
  • Webhook URLを含むスクリプトファイルをGitHubなどのパブリックリポジトリにプッシュしない
  • 使わなくなったWebhook URLはSlack Appの管理画面から削除する

チャンネルごとにWebhookを分ける

複数のチャンネルに通知を送る場合は、チャンネルごとに個別のWebhook URLを発行してください。1つのWebhook URLは1つのチャンネルに紐づく仕様のため、複数チャンネルへの通知にはそれぞれ別のURLが必要です。

スクリプトプロパティには複数の値を保存できるため、「SLACK_WEBHOOK_SALES」「SLACK_WEBHOOK_SUPPORT」のようにプロパティ名を分けて管理すると、コードの可読性も上がります。

定期的なURLのローテーション

長期間同じWebhook URLを使い続けると、退職者や異動者が過去のURLを保持している可能性があります。半年に1回程度、Webhook URLを再発行してスクリプトプロパティの値を更新することで、不正利用のリスクを低減できます。

トリガー設定で完全自動化する

ここまでのコードは手動で実行しても動作しますが、GASのトリガー機能を使うことで完全に自動化できます。トリガーには大きく分けて「イベント駆動型」と「時間主導型」の2種類があります。

イベント駆動型トリガー

スプレッドシートの編集やフォームの送信といったイベントをきっかけに関数を実行します。

トリガー種別 発火タイミング 適用例
onEdit スプレッドシートのセルが編集されたとき ステータス変更通知
onChange 構造変更(行追加・シート追加)があったとき 新規データ追加通知
onFormSubmit Googleフォームに回答が送信されたとき 問い合わせ通知

時間主導型トリガー

指定した時間間隔や時刻で関数を実行します。日次レポートや定期チェックに使います。

トリガーの設定は、Apps Scriptエディタの左側メニューにある時計アイコン(トリガー)から行います。「トリガーを追加」をクリックし、実行する関数・イベントソース・時間を選択してください。

トリガー設定時の注意点

GASのトリガーにはいくつかの制限があります。実務で運用する前に把握しておくと、トラブルを防げます。

  • 1つのプロジェクトに設定できるトリガーは最大20個です。通知の種類が多い場合は、1つの関数内で条件分岐するか、プロジェクトを分けてください
  • GASの実行時間は1回あたり最大6分です。大量のデータを処理して通知する場合は、処理対象をページ分割するなどの工夫が必要です
  • シンプルトリガー(function onEdit)ではUrlFetchAppが使えません。スプレッドシート編集時の通知にはインストーラブルトリガー(Apps Scriptエディタから設定)を使ってください
  • 時間主導型トリガーで「毎日午前9時〜10時」を指定した場合、実際の実行時刻は9時00分〜9時59分のどこかになります。正確な秒単位の制御はできません

よくある質問

QIncoming Webhookは無料で使えますか。

Aはい、Incoming Webhookの利用自体に追加料金はかかりません。Slackの無料プラン・有料プランのどちらでも利用できます。ただし、無料プランでは過去のメッセージ閲覧に制限があるため、通知の履歴を長期間保持したい場合は有料プランの利用を検討してください。

Q1つのWebhook URLで複数のチャンネルに送信できますか。

Aいいえ、1つのWebhook URLは発行時に指定した1つのチャンネルに紐づきます。複数のチャンネルに通知を送りたい場合は、チャンネルごとにWebhook URLを発行し、スクリプトプロパティで個別に管理してください。

QGASの実行が「承認が必要です」と表示されて動きません。

AGASからUrlFetchAppなどの外部通信を行う関数を初めて実行する際に、Googleアカウントによる承認が必要になります。「権限を確認」をクリックし、Googleアカウントでログインして「許可」を選択してください。トリガーで自動実行する場合も、初回の手動実行時に承認を済ませておく必要があります。

QSlack側のレート制限はどのくらいですか。

AIncoming Webhookのレート制限は、1つのWebhook URLにつき1秒あたり1リクエストが目安です。短時間に大量のリクエストを送ると429エラーが返されます。ループ処理で複数の通知を送る場合はUtilities.sleep(1000)以上の待機を挟んでください。

Qメンション(@ユーザー名)を通知に含めるにはどうすればよいですか。

AIncoming Webhookのメッセージ内でメンションを送るには、表示名ではなくSlackのユーザーIDを使います。形式は <@U01XXXXXXX> です。ユーザーIDはSlackのプロフィール画面で確認できます。チャンネル全体への通知には <!channel> や <!here> を使用します。

まとめ

この記事のポイント

  • GASのUrlFetchAppとSlack Incoming Webhookを組み合わせると、コードだけでSlack通知を自動化できる
  • Webhook URLはスクリプトプロパティに保存し、ソースコードへの直接記述は避ける
  • スプレッドシート編集・フォーム回答・定時実行など、GASのトリガー機能で用途に合わせた自動化が可能
  • Block Kitを使うとリッチな通知メッセージを構築できる
  • エラー時のリトライ処理とレート制限(1秒1リクエスト目安)への対応を入れておくと運用が安定する
  • Webhook URLは定期的にローテーションし、不要になったURLは速やかに削除する

吉元大輝

よしもとひろき

株式会社BoostX 代表取締役

福岡を拠点に、中小企業の生成AI導入を支援する「生成AI伴走顧問」サービスを提供。業務可視化から定着支援まで、一気通貫で企業のAI活用を推進している。

※本記事の情報は2026年4月時点のものです。

SNSで共有する
無料個別相談

貴社の業務に、 AIという確かな選択肢を。

「何から始めればいいか分からない」という段階でも構いません。現状の課題を伺い、最適な導入計画をプロと一緒に整理します。

\ 専門家による30分のヒアリング /

無料相談を予約する

オンライン対応可能・強引な勧誘なし

まずは資料で情報収集したい方へ

サービス概要・料金・導入事例をまとめた資料を無料でお送りします。

資料をダウンロード