業務自動化

GAS×LINE Messaging APIで予定リマインドを月¥0で自動化

予約管理・締切管理をスプレッドシートで行っている美容室・整体院・士業・小規模チームなどの中小企業/個人事業主 の業務自動化レシピ
業種予約管理・締切管理をスプレッドシートで行っている美容室・整体院・士業・小規模チームなどの中小企業/個人事業主
ツールGoogle Apps Script × LINE Messaging API
難易度★★☆ 中
設定時間約 35 分

スプレッドシートに書いた予約や締切を、指定した時刻になったら自動でLINEに送る——Google Apps ScriptからLINE Messaging APIを直接呼び出せば、外部の連携サービスを契約せずに月¥0で組めます。設定手順とそのまま動くコードを公開します。

読了時間 約9分 / 設定所要時間 約35分 / 月額固定費 ¥0(送信量が増えた場合のみ有料プラン検討)

編集長の見解:「LINEでリマインドを送る」自動化はノーコード連携サービスでも組めますが、月額課金が発生するものが大半です。予約や締切のリマインドという単純な処理であれば、Google Apps ScriptからLINE Messaging APIを直接呼び出す構成のほうが、費用を抑えながら「何が起きているか」を自分でコントロールできます。仕組みを理解して手を動かせる事業者には、この直結構成をおすすめします。

🔍 なぜGASからLINEを直接呼ぶのか

「LINEに自動通知」と聞くと、真っ先に候補に挙がるのはLINE Notifyかもしれません。ですがLINE Notifyは提供終了済みのサービスです。現在プログラムからLINEへ通知を送る場合は、LINE公式アカウントに付属するLINE Messaging API(外部のプログラムからLINEへメッセージを送受信するための公式の窓口)を使うのが標準的な方法になります。

Zapier や Make.com といったノーコード連携サービス(プログラムを書かずに画面操作だけで自動化を組めるサービス)にも、LINE連携のモジュールは用意されています。編集部でもZapier経由でLINE公式アカウントに問合せ通知を送るレシピGoogle スプレッドシートの更新をMake.com経由でLINEに送るレシピを紹介済みです。これらは画面操作だけで組める手軽さが利点ですが、多くのプランは連携数やタスク実行回数に応じた追加の月額課金が発生します。

GASからMessaging APIを直接呼び出す場合、費用構造がシンプルです。

対価として必要になるのは「コードを貼る」「LINE公式アカウントの設定を自分で行う」という一手間です。次のセクションで仕組み全体を確認します。

🗺 全体フロー — 「受信」と「送信」2つの仕組み

この構成には2つの独立した仕組みがあります。1つは相手のLINE userIdを取得するための受信側、もう1つは指定時刻にリマインドを送る送信側です。userIdとは、LINEが利用者一人ひとりに割り当てる英数字の識別番号で、「誰に送るか」を指定するために使います。

スプレッドシート予定→LINE自動リマインドの全体像
💬
01
LINEでuserIdを取得
友だち追加後、何か送信するとGASがuserIdを返信
📝
02
スプレッドシートに予定を記入
送信日時・userId・本文を1行ずつ入力
03
時間主導型トリガーが定期チェック
5分おきに実行し、送信時刻を迎えた行を検出
📱
04
LINEへ自動送信
Messaging APIのPush送信で本人のLINEへ通知

userIdの取得は最初の1回だけ、以降は送信側が自動で繰り返し動く

登場する部品を整理します。

部品役割公式ドキュメント
LINE公式アカウントMessaging APIの発行元。Webhook受信・Push送信の窓口LINE Official Account Manager
Webhook(doPost)外部からの通知を受け取る仕組み。友だちがメッセージを送った時にuserIdを取得する受信口Webhookイベント
時間主導型トリガー数分おきにスプレッドシートを確認する定期処理時間主導型トリガー
Push Message API指定したuserIdへ能動的にメッセージを送るAPIMessaging APIリファレンス

この4つをつなぐコードは、次の設定手順の中でまとめて提示します。

💰 必要なものと費用の目安

送信量が少ない個人事業主・小規模チームであれば、追加の支出なしで運用できます。

必要なもの役割費用の目安
Googleアカウント(無料 or Workspace)スプレッドシート・GASの実行無料(Workspaceは既存契約で可)
Google Apps Script定時チェック・API呼び出しの実行環境無料
LINE公式アカウント(コミュニケーションプラン)Messaging APIの発行元月額¥0・無料メッセージ200通/月
LINE公式アカウント(ライトプラン、必要な場合のみ)送信量が増えた場合のアップグレード先月額¥5,000(税別)・無料メッセージ5,000通/月

友だちから届いたメッセージに返す応答(リプライ)メッセージは、料金プランの通数にカウントされません。一方、本記事の主役であるPush送信(こちらから能動的に送る通知)は月200通の無料枠を消費します。1日1件の自分宛てリマインドであれば月30通程度で収まりますが、複数人・複数件を通知する場合は事前に見積もってください。最新の料金はLINE Messaging APIの料金ページで確認できます。

💡 編集部の判断材料:すでにMake.comやZapierを契約中で、他の業務でも使い倒しているなら、無理に乗り換える必要はありません。GASが向くのは「これから始める」「連携サービスの月額を増やしたくない」「送信ロジックを自分で細かく制御したい」ケースです。ノーコードで手早く済ませたい方は、前述のZapierでLINE公式アカウントに通知するレシピGASでGoogleカレンダー→Slackに朝会リマインドするレシピも参考にしてください。

判断がついたら、実際の構築に進みます。

🛠 設定手順 — 約35分で完成

作業は「LINE公式アカウントを作る」「userId取得用のWebhookを設置する」「スプレッドシートとリマインド送信コードを設定する」の3段階です。

GAS × LINE Messaging API 自動リマインドの構築手順
STEP 1
LINE公式アカウントを作成
LINE Official Account Managerで無料の公式アカウントを開設します(既存のアカウントがあれば流用可)。
STEP 2
Messaging APIを有効化してトークンを発行
LINE Developers コンソールでMessaging APIチャネルを有効化し、「チャネルアクセストークン(長期)」を発行して控えます。これはGASからLINEへ送信するときの合鍵にあたる文字列なので、他人に見せない場所に保管してください。
STEP 3
GASプロジェクトを作成しコードを貼り付け
script.google.comで新規プロジェクトを作成し、下記の2つの関数(Webhook受信用・リマインド送信用)を貼り付けます。
STEP 4
ウェブアプリとしてデプロイしWebhook URLを登録
「デプロイ」(作ったスクリプトを外部から呼び出せる状態にする操作)→「新しいデプロイ」→種類「ウェブアプリ」、アクセスできるユーザーを「全員」にして発行されたURLを、LINE DevelopersのWebhook URL欄に登録し「Webhookの利用」をオンにします。
STEP 5
自分のuserIdを取得
作成した公式アカウントを友だち追加し、何かメッセージを送信します。GASからのリプライで自分のuserIdが返ってくるので、スプレッドシートに貼り付けます。
STEP 6
スプレッドシートに予定を入力し時間主導型トリガーを設定
列構成に沿って予定を入力し、エディタ左の時計アイコンから「トリガーを追加」、イベントのソースを「時間主導型」→「分ベースのタイマー」→「5分おき」に設定します。

1. Webhook受信用コード(userId取得用)

まず、友だちが送ってきたメッセージからuserIdを取り出し、本人にリプライで返すコードです。これは初回のuserId取得にだけ使います。

/**
 * LINE公式アカウントのWebhook受信口
 * 友だちが何かメッセージを送ると、そのuserIdをリプライで返す
 * (userIdをスプレッドシートに登録するための、最初の1回だけ使う仕組み)
 */
function doPost(e) {
  const accessToken = PropertiesService
    .getScriptProperties()
    .getProperty('LINE_CHANNEL_ACCESS_TOKEN');

  const body = JSON.parse(e.postData.contents);
  const events = body.events || [];

  events.forEach(function (event) {
    if (event.type !== 'message' || !event.replyToken) return;

    const userId = event.source && event.source.userId;
    const replyText = userId
      ? 'あなたのuserIdは以下です。スプレッドシートのuserId列に貼り付けてください。\n' + userId
      : 'userIdを取得できませんでした(グループ・複数人トークからの送信は個人のuserIdを取得できません)。';

    replyToLine_(accessToken, event.replyToken, replyText);
  });

  return ContentService.createTextOutput(JSON.stringify({ status: 'ok' }))
    .setMimeType(ContentService.MimeType.JSON);
}

function replyToLine_(accessToken, replyToken, text) {
  const options = {
    method: 'post',
    contentType: 'application/json',
    headers: { Authorization: 'Bearer ' + accessToken },
    payload: JSON.stringify({
      replyToken: replyToken,
      messages: [{ type: 'text', text: text }]
    }),
    muteHttpExceptions: true
  };
  UrlFetchApp.fetch('https://api.line.me/v2/bot/message/reply', options);
}

2. リマインド送信用コード(本体)

次に、スプレッドシートの予定を確認し、送信時刻を迎えた行だけLINEにPush送信するコードです。5分おきの時間主導型トリガーからこのcheckAndSendRemindersを呼び出します。

想定するスプレッドシートの列構成(1行目はヘッダー)は次の通りです。

A列B列C列D列E列
送信日時宛先名(メモ用)LINE userId本文送信済み
/**
 * スプレッドシートの予定を確認し、送信時刻を迎えた未送信の行を
 * LINE Messaging APIのPush送信でリマインドする
 * トリガー: 時間主導型(分ベースのタイマー、5分おき)
 */
function checkAndSendReminders() {
  const accessToken = PropertiesService
    .getScriptProperties()
    .getProperty('LINE_CHANNEL_ACCESS_TOKEN');
  if (!accessToken) {
    throw new Error('LINE_CHANNEL_ACCESS_TOKEN がスクリプトプロパティに未設定です');
  }

  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('リマインド一覧');
  if (!sheet) {
    throw new Error('シート「リマインド一覧」が見つかりません(シート名を確認してください)');
  }

  const rows = sheet.getDataRange().getValues();
  const now = new Date();
  // トリガー間隔(5分)より少し広めの窓を取り、実行タイミングのズレで
  // 送信が漏れないようにする(過去10分〜現在までを対象)
  const windowStart = new Date(now.getTime() - 10 * 60 * 1000);

  for (let i = 1; i < rows.length; i++) {
    const [sendAt, name, userId, message, sent] = rows[i];

    if (sent === true || sent === 'TRUE') continue;
    if (!(sendAt instanceof Date) || !userId || !message) continue;
    if (sendAt < windowStart || sendAt > now) continue;

    try {
      pushToLine_(accessToken, userId, message);
      sheet.getRange(i + 1, 5).setValue(true); // E列に送信済みを記録
    } catch (err) {
      console.error('送信失敗: 行' + (i + 1) + ' name=' + name + ' error=' + err.message);
    }
  }
}

function pushToLine_(accessToken, userId, text) {
  const options = {
    method: 'post',
    contentType: 'application/json',
    headers: { Authorization: 'Bearer ' + accessToken },
    payload: JSON.stringify({
      to: userId,
      messages: [{ type: 'text', text: text }]
    }),
    muteHttpExceptions: true
  };

  const res = UrlFetchApp.fetch('https://api.line.me/v2/bot/message/push', options);
  const code = res.getResponseCode();

  if (code !== 200) {
    throw new Error('LINE送信失敗 (HTTP ' + code + ') ' + res.getContentText());
  }
}

チャネルアクセストークンの登録(コードに直書きしない)

STEP 2で発行したチャネルアクセストークンは、コードに直接書かず「スクリプトプロパティ」に保存します。

  1. Apps Scriptエディタ左の**歯車アイコン(プロジェクトの設定)**を開く
  2. 最下部の「スクリプト プロパティ」で「スクリプト プロパティを追加」をクリック
  3. プロパティ名にLINE_CHANNEL_ACCESS_TOKEN、値にSTEP 2で発行したトークンを入力

💡 編集部メモ:複数人にリマインドを送りたい場合も、スプレッドシートの行を増やすだけで対応できます。宛先ごとにuserIdが違う行を並べれば、担当者Aには9時に、担当者Bには10時に、といった個別のリマインドを同じシートで管理できます。

保存とトリガー設定が終わったら、スプレッドシートに数分後の日時を入れた行を1件追加し、実際に届くか手動実行でテストしてください。次のセクションで、つまずきやすい点を整理します。

⚠️ 失敗パターンと運用上の注意

編集部が特に注意すべきと考える点を挙げます。

⚠️ 失敗パターン1:友だち追加していない相手にPushしようとして失敗する。LINE Messaging APIのPush送信は、送信先が公式アカウントを友だち追加していない、またはブロックしている場合エラーになります。userIdを取得する前に必ず本人が友だち追加を済ませているか確認してください。

⚠️ 失敗パターン2:トリガー間隔と送信時刻がぴったり一致すると思い込む。GASの時間主導型トリガーは「指定した間隔で実行」であり、秒単位で狙った時刻に実行が保証されるわけではありません。本記事のコードは過去10分の窓で判定することで実行タイミングのズレを吸収していますが、間隔を長くする場合は窓も合わせて広げてください。

本記事のWebhook受信コードは、動作確認のしやすさを優先してX-Line-Signatureヘッダーによる署名検証(届いたデータが本当にLINEから送られたものかを確かめる処理)を省略した最小構成です。個人・小規模チームでの自分宛て運用であれば実害は限定的です。複数人が使う環境や本番運用で長く使う場合は、Webhookの署名検証を必ず実装してください。

トラブル起こりやすい原因編集部の対策
リマインドが届かないトリガー未作成、シート名の不一致シート名がリマインド一覧と完全一致しているか確認
Webhookの返信が来ないデプロイURLの登録漏れ、アクセス権限の設定ミス「アクセスできるユーザー」を「全員」にして再デプロイ
Push送信でエラーになる友だち未追加、トークンの誤り友だち追加状況とスクリプトプロパティの値を再確認
同じ内容が2回届く送信済みフラグの列がズレているE列(5列目)に確実に書き込まれているかコードと列構成を確認

なおGASには1日あたりの実行時間や外部通信回数の上限がありますが、通知1件あたりの処理は数秒で終わるため、通常の個人・小規模チーム規模では上限に届きません。詳細はApps Scriptの割り当てと制限を確認してください。次のセクションで、この35分の投資が経営上どう返ってくるかを整理します。

🚀 経営者はこの35分をどう回収するか

編集部の想定シナリオを1つ挙げます。従業員のいない整体院を1人で営む個人事業主が、予約前日の夜に「明日の予約時間」を自分のLINEで確認したいケースです(実在の事業者の事例ではありません)。

かかった費用は¥0、かかった時間は初回の35分だけです。基本形が動いたら、次の応用も同じコードの延長で組めます。

当サイトでは、GASやLINE連携の自動化を複数紹介しています。あわせて読むと設計の引き出しが増えます。

編集部のまとめ:このレシピの本質は「予定確認という毎日の反復作業を、目視からシステムへ移す」ことです。LINE Notifyが終了した今、GASからLINE Messaging APIを直接呼び出す構成を知っておけば、ノーコード連携サービスの追加課金なしで同じ効果を月¥0で持てます。まずは自分宛てのリマインドで動作を確認し、そのうえで複数人への展開や前日まとめ通知といった応用に進むのが堅実な順序です。

出典・参考情報


Mira / AI経営ラボ 編集長