Notionシステム研究所 > GASとNotion APIを連携する方法|1ページを更新するコードから始める
2026年10月22日
•約7分で読めます
Google Apps ScriptからNotion APIを呼び、検証用ページの数値と日時を更新するコードを掲載。Script Properties、APIバージョン、列名と型の検査、時間主導トリガーの運用を解説します。
Google Apps Script(GAS)からNotionへデータを送るには、UrlFetchApp でNotion APIを呼び出します。最初は、新しいページを大量に作る処理より、決めた1ページの2項目だけを更新する処理で接続を確かめると、問題を切り分けやすくなります。
この記事では、検証用ページの「集計件数」と「連携確認日時」を更新する最小例を扱います。フォーム回答の受信やCSVの照合は別の処理なので、Googleフォーム連携、CSVの差分更新を参照してください。
本番DBとは別に検証用DBを作り、次のプロパティを追加します。
| 名前 | Notionの型 | 今回の役割 |
|---|---|---|
| 名前 | タイトル | 「GAS接続確認」など任意の名称 |
| 集計件数 | 数値 | サンプル値12を書き込む |
| 連携確認日時 | 日付 | コードを実行した時刻を書き込む |
DBに「GAS接続確認」というページを1件作ります。ページ本文には確認用のメモを置いて構いません。今回のコードはこの本文を変更しません。
次にNotionの内部コネクションを作成し、読み取り・更新に必要な権限を設定して、検証用DBへ接続します。ページにアクセスできる自分の権限と、コネクションの権限は別です。設定の全体像はNotionインテグレーションの基本で確認できます。
Apps Scriptのプロジェクト設定で、次のスクリプトプロパティを登録します。
| キー | 登録する値 |
|---|---|
NOTION_TOKEN |
内部コネクションのトークン |
NOTION_PAGE_ID |
検証用DBの中に作った1ページのID |
ここで使うのはページIDです。DB全体のIDやデータソースIDを入れると、更新対象が違います。APIの取得結果等でページIDを確認し、URL全体やビューを指定するパラメーターを混ぜないでください。
スクリプトプロパティを使うと、コード本文へのトークンの直書きを避けられます。ただし、プロジェクトの編集者から秘密を隔離する保管庫ではありません。プロジェクトの共有範囲も絞ります。Google公式:Properties Service
以下は、架空の集計値12を送る学習用コードです。実データを集計する処理は含みません。APIバージョンは 2026-03-11 を指定しています。Notion公式:APIバージョン
function updateNotionSample() {
const lock = LockService.getScriptLock();
if (!lock.tryLock(1000)) {
throw new Error('別の実行が進行中です');
}
try {
const config = PropertiesService.getScriptProperties();
const token = config.getProperty('NOTION_TOKEN');
const pageId = config.getProperty('NOTION_PAGE_ID');
const idPattern = /^(?:[0-9a-f]{32}|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i;
if (!token || !pageId || !idPattern.test(pageId)) {
throw new Error('トークンまたはページIDの設定を確認してください');
}
const current = notionRequest_('get', pageId, token);
const props = current.properties || {};
if (props['集計件数']?.type !== 'number' ||
props['連携確認日時']?.type !== 'date') {
throw new Error('検証用DBの列名と型を確認してください');
}
const count = 12; // 動作確認用。実運用では取得・検証した集計値に置き換える
const observedAt = new Date().toISOString();
notionRequest_('patch', pageId, token, {
properties: {
'集計件数': { number: count },
'連携確認日時': { date: { start: observedAt } }
}
});
const saved = notionRequest_('get', pageId, token);
const savedCount = saved.properties['集計件数']?.number;
const savedTime = saved.properties['連携確認日時']?.date?.start;
if (savedCount !== count ||
Date.parse(savedTime) !== Date.parse(observedAt)) {
throw new Error('書き込み後の値が一致しません。再実行前にページを確認してください');
}
console.log('検証用ページの2項目を更新し、読み戻しを確認しました');
} finally {
lock.releaseLock();
}
}
function notionRequest_(method, pageId, token, body) {
const options = {
method: method,
headers: {
Authorization: 'Bearer ' + token,
'Notion-Version': '2026-03-11'
},
muteHttpExceptions: true
};
if (body !== undefined) {
options.contentType = 'application/json';
options.payload = JSON.stringify(body);
}
const response = UrlFetchApp.fetch(
'https://api.notion.com/v1/pages/' + encodeURIComponent(pageId),
options
);
const status = response.getResponseCode();
if (status < 200 || status >= 300) {
throw new Error('Notion API HTTP ' + status + ':実行を停止しました');
}
return JSON.parse(response.getContentText());
}
updateNotionSample を選んで実行し、Google側の認可を完了します。Notionで集計件数が12になり、連携確認日時が更新され、本文のメモが残っていることを確認してください。
HTTP呼び出しはGoogleのURL Fetchサービス、更新形式はNotionのページ更新APIに基づいています。コードは各社の公式サンプルの転載ではなく、接続確認用に構成した例です。Google公式:UrlFetchApp、Notion API:ページの更新
| 表示・状態 | 主に確認すること |
|---|---|
| 設定を確認してください | プロパティ名、トークンの未設定、ページIDの形式 |
| HTTP 401 | トークンの有効性、別環境の値を入れていないか |
| HTTP 403 | コネクションに必要な操作権限があるか |
| HTTP 404 | 対象IDと、コネクションへのページ共有 |
| HTTP 400 | プロパティ名・型・送信する値の形式 |
| HTTP 429 | 呼び出し頻度を下げ、Retry-After に従う |
| 更新後の値が不一致 | 別処理による上書き、想定と異なるページの参照 |
エラー調査のためにAuthorizationヘッダーやトークンをログへ出す必要はありません。本文の全文出力も避け、対象ページID、HTTPステータス、実行日時など必要な情報だけを記録します。
このサンプルは、自動再試行を入れず失敗時に停止します。書き込み後の応答だけが失われる場合もあるためです。実運用で再試行を追加するときは、現在値の確認とAPIの待機指示を組み合わせます。Notion公式:リクエスト制限
手動更新ができたら、Apps Scriptのトリガー画面から updateNotionSample に時間主導トリガーを1つ設定できます。ただし、そのままでは毎回12を書き込むだけです。実運用に移す前に、集計値の取得処理へ置き換え、対象期間と取得日時も決めてください。
トリガーを複数作ると同じ処理が何度も走ります。引き継ぎ時には、前任者のトリガーと新しいトリガーが重なっていないか確認します。インストール型トリガーが作成者のアカウントで動く点も、運用上の確認事項です。Google公式:インストール型トリガー
GASには実行時間やサービスごとの割り当てがあります。大量データを1回で処理する構成へ広げる前に、分割実行と続きから再開する方法を用意しましょう。Google公式:Apps Scriptの割り当て
まず1ページで、認証、読み取り、更新、読み戻しの4段階を確認する。その後に業務データの取得を追加すれば、「Google側で取れていない」のか「Notion側へ書けていない」のかを切り分けながら進められます。
千葉県出身。10歳の頃からプログラミングを始め、ゲーム、Webサイト、ロボット、スマホアプリなどを制作。大阪大学基礎工学部情報科学科で情報工学と統計学を学び、大学時代はAIを研究。大学在学中にWeb広告代理店でのインターンや人材系Webサービスの立ち上げを経験し、卒業後はフリーランスエンジニアとしてGISシステム、データ基盤構築、Webシステムの開発に従事。10年以上のWebアプリ開発・データ分析経験を基に、2023年9月に株式会社ビットライトを設立し、現場業務の仕組み化からデータ基盤構築、データ活用支援までを一気通貫で支援。