目次
Googleカレンダーの予定は、Apps Scriptで対象期間を検索し、Google Chatの受信Webhookへ送信できます。最初に作るなら、チーム用カレンダーの当日予定を1日1回まとめて通知する構成が適しています。個人カレンダーのタイトルをそのまま流さず、日次一覧、会議前リマインド、予定変更通知を別の仕組みとして設計してください。
本記事は2026年6月29日時点のGoogle公式情報をもとにしています。Calendar、Apps Script、Google Chatの仕様、割り当て、管理者設定は変更される可能性があります。実装前に公式ドキュメントと自社環境を確認してください。
Expert Q&A
カレンダー通知を作る前に確認すること
湯田英也SakuraAI株式会社 代表 / ソフトウェアエンジニアQ. 最初に作るなら日次一覧と会議前通知のどちらですか?
A. 日次一覧です。1日1回なら通知量と重複を管理しやすく、チーム用カレンダーで効果を確認できます。会議前通知は、誰に何分前に知らせるかを決めてから追加します。
Q. 個人の予定タイトルをチームChatへ流してよいですか?
A. 原則として流しません。個人カレンダーには面談、通院、顧客名などが入ります。共有目的なら専用のチームカレンダーを作るか、タイトルを予定ありへ置き換えます。
Q. 更新トリガーで変更された予定をすぐ取れますか?
A. トリガーから分かるのは、対象カレンダーで更新が起きたことまでです。どの予定がどう変わったかはCalendar APIの増分同期で取得します。
Googleカレンダーの通知は、予定を取得してChatへ投稿するだけなら短いコードで作れます。難しいのは、通知する範囲です。個人予定のタイトルをどこまで見せるか、変更や削除をどう扱うか、同じ予定を何度も通知しないかを決める必要があります。
この記事では、当日予定の一覧を基本形にして、開始前リマインドと変更通知の違いまで整理します。Webhookの準備はWebhookの使い方、Apps Scriptの基礎はApps Scriptで通知する方法も参照してください。
一つ立場をはっきりさせておくと、予定をたくさん通知するのが良い通知ではありません。チーム用カレンダーから必要な情報だけをまとめて送る——ここを外すと、個人の予定タイトルが漏れたり、通知が増えて誰も見なくなったりします。
3つの通知方式を分ける
| 通知方式 | 実行方法 | 向く用途 | 状態管理 | 主な注意点 |
|---|---|---|---|---|
| 日次・翌日一覧 | 時間主導トリガー | 朝会、当番、チーム予定共有 | 同じ日に1回送ったか | 指定時刻からずれることがある |
| 開始前リマインド | 短い間隔の定期検索 | 会議準備、締切前通知 | 予定IDと開始時刻 | 重複防止と変更後の再通知が必要 |
| 作成・変更・削除通知 | 更新トリガーと増分同期 | 共有予定の監査、連携処理 | nextSyncTokenと予定の差分 | トリガーだけでは変更予定を特定できない |
この記事の実装例は日次一覧です。開始前リマインドは通知済み状態の保存が必要になり、変更通知はCalendar APIの増分同期が必要です。要件が違うため、同じ関数へ詰め込みません。
日次一覧の処理フロー
時間主導トリガー
朝の時間帯に定期実行
対象カレンダー
チーム用カレンダーを指定
当日予定を取得
終日と時刻指定を分ける
公開範囲を調整
タイトルや参加者を絞る
受信Webhook
固定スペースへ一方向送信
Google Chat
1日分をまとめて共有
予定1件につき1投稿すると通知が増えるため、日次一覧は1つのメッセージへまとめます。予定の詳細確認はCalendarへ戻し、Chatを予定情報の正本にしません。
対象カレンダーと公開範囲を決める
通知先より先に、どのカレンダーを対象にするかを決めます。
| 対象 | 推奨度 | 通知する内容 | 注意点 |
|---|---|---|---|
| チーム用共有カレンダー | 高い | 時刻、予定タイトル、担当 | 運用目的と参加者が一致しやすい |
| プロジェクト用カレンダー | 高い | 締切、会議、リリース予定 | プロジェクト外の情報を混ぜない |
| 会議室・設備カレンダー | 中 | 予約時間、利用状況 | 予約者名を出す必要があるか確認する |
| 個人のメインカレンダー | 低い | 原則は時間帯だけ | 顧客名、面談、私用予定が混ざる |
| 組織全体のカレンダー | 用途次第 | 全社行事、休業日 | 投稿頻度と対象スペースを絞る |
個人カレンダーの内容をチームへ出す必要がある場合も、初期設定ではタイトルを予定ありに置き換えます。予定の説明、参加者、添付、Meet URLは、業務上必要な場合だけ追加します。
| 項目 | Chatへの掲載 | 判断理由 |
|---|---|---|
| 開始・終了時刻 | 掲載する | チームの行動判断に必要 |
| 予定タイトル | 共有カレンダーだけ掲載 | 個人・顧客情報を含む可能性がある |
| 主催者・参加者 | 原則掲載しない | 個人情報と組織情報を広げない |
| 説明欄 | 掲載しない | 会議メモや機密情報が入りやすい |
| Meet URL | 参加者が一致する場合だけ | URLを知る範囲を広げない |
| 添付ファイル | Chatへ複製しない | Drive側の権限で管理する |
| 場所 | 必要な場合だけ | 訪問先や個人情報を含む可能性がある |
Webhookと設定値を用意する
ブラウザ版Google Chatで通知先スペースを開き、アプリとインテグレーションから受信Webhookを追加します。Webhook URLはApps ScriptのスクリプトプロパティへCHAT_WEBHOOK_URLとして保存します。
対象カレンダーのIDもCALENDAR_IDとして保存します。コードへ直接書かず、環境ごとに設定を切り替えられるようにします。
Google ChatとGoogleカレンダーの設定画面は、公開前に運用環境で手動撮影した実画面へ差し替えます。アカウント名、予定名、参加者、カレンダーID、Webhook URLをマスキングしてから掲載してください。
当日の予定をまとめて通知する
次のコードは、指定カレンダーの当日予定を取得し、1つのChatメッセージへまとめます。SHOW_TITLESをfalseにすると、タイトルを予定ありへ置き換えます。
const SHOW_TITLES = false;
function notifyTodayEvents() {
const properties = PropertiesService.getScriptProperties();
const calendarId = properties.getProperty('CALENDAR_ID');
if (!calendarId) {
throw new Error('CALENDAR_IDが設定されていません。');
}
const calendar = CalendarApp.getCalendarById(calendarId);
if (!calendar) {
throw new Error('対象カレンダーが見つからないか、権限がありません。');
}
const events = calendar.getEventsForDay(new Date())
.sort((a, b) => a.getStartTime().getTime() - b.getStartTime().getTime());
const timeZone = calendar.getTimeZone();
const dateLabel = Utilities.formatDate(new Date(), timeZone, 'M月d日');
const lines = events.length === 0
? ['予定はありません。']
: events.map((event) => formatEvent(event, timeZone));
sendToChat([
`*${dateLabel}の予定*`,
...lines,
].join('\n'));
}
function formatEvent(event, timeZone) {
const time = event.isAllDayEvent()
? '終日'
: Utilities.formatDate(event.getStartTime(), timeZone, 'HH:mm');
const title = SHOW_TITLES
? truncate(event.getTitle(), 80)
: '予定あり';
return `${time} ${title}`;
}
function truncate(value, maxLength) {
const text = String(value || '名称未設定');
return text.length <= maxLength
? text
: `${text.slice(0, maxLength)}...`;
}
function sendToChat(message) {
const url = PropertiesService.getScriptProperties()
.getProperty('CHAT_WEBHOOK_URL');
if (!url) {
throw new Error('CHAT_WEBHOOK_URLが設定されていません。');
}
const response = UrlFetchApp.fetch(url, {
method: 'post',
contentType: 'application/json; charset=UTF-8',
payload: JSON.stringify({ text: message }),
muteHttpExceptions: true,
});
const status = response.getResponseCode();
if (status < 200 || status >= 300) {
throw new Error(`Chat通知に失敗しました。HTTP ${status}`);
}
}
getCalendarByIdは、カレンダーが存在しない場合だけでなく、実行者がアクセスできない場合や購読していない場合もnullを返します。取得結果を確認せずに処理を続けないようにします。
Apps Scriptのタイムゾーンとカレンダーのタイムゾーンが違うと、日付や表示時刻がずれる可能性があります。対象カレンダー、Apps Scriptプロジェクト、通知先チームの基準タイムゾーンを確認してください。
時間主導トリガーを設定する
Apps Scriptのトリガー画面からnotifyTodayEventsを時間主導トリガーへ登録します。毎朝の予定共有なら、日付ベースのタイマーで希望する時間帯を選びます。
Google公式では、時間主導トリガーの実行時刻は指定時間帯の中で多少ずれると案内されています。8時台の通知には使えますが、8時00分ちょうどの実行を前提にしません。
| 通知タイミング | 向く用途 | 実装 | 注意点 |
|---|---|---|---|
| 当日朝 | 朝会、当番、チーム予定 | 1日1回の時間主導トリガー | 実行時刻は時間帯内でずれる |
| 前日夕方 | 翌日の準備、会議資料確認 | 翌日の日付で予定を取得 | 夜間の予定変更は反映されない |
| 15〜30分前 | 会議前リマインド | 短い間隔で今後の予定を検索 | 重複防止が必要 |
| 変更直後 | 変更・中止の連絡 | 更新トリガーと増分同期 | CalendarAppだけでは差分を特定できない |
インストール型トリガーは作成者の権限で実行されます。作成者の退職やアカウント停止で止まらないよう、所有者、対象カレンダー、プロパティ、通知先を引き継ぎ資料へ残します。
会議前リマインドでは重複を防ぐ
会議前リマインドは、5分ごとなど短い間隔で対象期間を検索します。同じ予定が複数回の検索窓に入るため、予定IDと開始時刻を組み合わせたキーを保存します。
| 状態管理 | 利点 | 限界 | 向く規模 |
|---|---|---|---|
| PropertiesService | Apps Scriptだけで完結する | 保存容量と監査性に限界がある | 小規模なリマインド |
| スプレッドシート | 通知履歴を人が確認できる | 同時更新と行数増加に注意 | 部門単位の運用 |
| データベース・キュー | 再送、期限、監査を設計しやすい | 構築と監視が必要 | 大量・重要な通知 |
予定時刻が変更された場合、同じ予定IDでも開始時刻が変わります。開始時刻をキーへ含めれば、変更後の時刻で再通知できます。中止予定や繰り返し予定の扱いもテストが必要です。
変更通知には増分同期が必要
Apps Scriptのカレンダー更新トリガーは、予定が作成、編集、削除されたときに動きます。ただし、イベントオブジェクトから分かるのは対象カレンダーIDまでで、どの予定がどう変わったかは分かりません。
Google公式が案内する変更検知の流れは次のとおりです。
- Calendarの高度なサービスを有効にする
- 対象カレンダーを初回同期する
- 取得した
nextSyncTokenを保存する - 更新トリガーが動いたら、保存済みトークンで増分同期する
- 作成、更新、削除された予定を判定する
- 新しい
nextSyncTokenへ更新する 410でトークンが無効になった場合は完全同期し直す
予定変更通知は、当日一覧のコードへ数行追加するだけでは実装できません。変更前後の比較、削除、繰り返し予定、同期トークンの失効まで扱う別機能として設計します。
テストで確認する項目
| 確認項目 | テスト方法 | 合格条件 |
|---|---|---|
| 終日予定 | 終日と複数日の予定を登録する | 終日として日次一覧へ表示される |
| タイムゾーン | 異なるタイムゾーンの予定を登録する | 基準タイムゾーンで正しく表示される |
| 非公開予定 | 個人情報を含む予定を登録する | タイトルや参加者がChatへ出ない |
| 予定なし | 対象日の予定をゼロにする | 期待した文言または無通知になる |
| 送信失敗 | テスト用の無効Webhookで実行する | 失敗が実行履歴に残る |
| 権限不足 | 対象カレンダーの共有を外す | 分かるエラーで停止する |
| 引き継ぎ | 別の管理担当が設定を追跡する | カレンダーID、プロパティ、トリガーを確認できる |
本番運用で見る指標
Decision chart
カレンダー通知で優先して監視する項目
予定共有への影響をもとにSakuraAIが整理した優先度です。
予定があってもチームへ届かない
個人情報や顧客情報の漏えいにつながる
通知疲れと見落としを増やす
会議への遅刻や準備不足につながる
通知が行動に結び付いているかを見る
Apps Scriptの実行履歴と失敗通知を確認し、Calendar、URL Fetch、トリガーの割り当ても公式資料で確認します。大量の予定を同じスペースへ1件ずつ送らず、一覧へ集約します。
Apps Script方式が向かないケース
- 秒単位の正確な通知時刻が必要
- 大量のカレンダーを組織横断で監視する
- 変更前後の履歴を監査対象として保存する
- 通知の再送、配信保証、失敗キューが必要
- 複数のシステムへ同じ予定イベントを配信する
この場合は、Calendar API、Cloud Scheduler、キュー、データベース、監視基盤を含めて設計します。Apps Scriptは小規模な日次共有には向きますが、厳密なイベント配信基盤ではありません。
専門家に聞く運用判断
Expert Q&A
公開前に湯田へ確認すること
湯田英也SakuraAI株式会社 代表 / ソフトウェアエンジニアQ. どのカレンダーから始めますか?
A. 個人カレンダーではなく、目的と閲覧者が決まっているチーム用カレンダーです。当日の予定を1日1回まとめ、通知量と公開範囲を確認します。
Q. 予定の説明をAIで要約して通知してもよいですか?
A. 説明欄には機密情報が入りやすいため、最初からAIへ渡しません。要約が本当に必要な用途だけを選び、入力範囲、保存先、誤要約時の確認方法を決めます。
Q. 会議前リマインドが二重に飛びます。なぜ?
A. 多くは、同じ予定に対してリマインド送信済みかどうかを記録していないためです。予定IDと通知種別を組みにして『送ったか』を保存し、送る前に確認する。これだけで重複はほぼ止まります。タイムゾーンの取り違えも時刻ずれの定番なので、あわせて確認してください。
Q. 運用を始めてから何を改善しますか?
A. 通知の件数ではなく、失敗・重複・非公開情報の誤掲載・時刻ずれを見ます。使われない通知を増やすより、対象カレンダーとタイミングを絞るほうが、結局よく読まれます。
関連レシピ
日程調整と予定作成まで含めた設計はカレンダー日程調整の自動化、フォーム回答の通知はフォーム回答をChatに通知する方法、Drive更新の通知はDrive更新をChatに通知する方法を参照してください。
SakuraAIで支援できること
SakuraAIは、Googleカレンダーの日次共有、会議前リマインド、変更検知、Google Chat通知を設計・実装します。通知を作るだけで終わらせず、公開範囲、タイムゾーン、重複防止、増分同期、失敗監視、担当者の引き継ぎまで含めて構築します。
よくある質問
会議の前にリマインドできますか?
できます。時間主導トリガーで今後の一定時間内に始まる予定を検索し、予定IDと開始時刻をキーに通知済み状態を管理します。ただし、時間主導トリガーは厳密な秒単位の実行を保証しません。
特定のカレンダーだけ通知できますか?
できます。CalendarApp.getCalendarByIdで対象カレンダーを指定します。取得結果がnullの場合は、IDの誤り、権限不足、未購読を確認します。
予定の変更も通知できますか?
できますが、カレンダー更新トリガーだけでは変更された予定を特定できません。Google公式が案内するCalendar APIの増分同期を使い、nextSyncTokenで差分を取得する必要があります。
毎朝8時ちょうどに通知できますか?
Apps Scriptの時間主導トリガーは指定時間帯の中で実行時刻がずれることがあります。8時台の共有には使えますが、8時00分ちょうどが業務要件なら別のスケジューラを検討します。
非公開予定のタイトルもChatへ流れますか?
実装次第です。個人カレンダーをチームへ通知する場合は、初期設定ではタイトルを出さず予定ありと表示する方が安全です。タイトルを載せるなら、通知先の参加者と予定の公開範囲を確認します。
参考・一次情報
開発相談
Google Chat Bot・Webhook開発を相談する
通知・承認・問い合わせ連携のBotとAPI実装を支援します。
開発を相談する