はじめに
GitHub Pagesを使ってとあるフォームを公開しています。そのフォームへの入力(メールアドレス)をNotionに送信・管理させる構成を実装したので手順をご紹介します。
Webサイトはホスティング済みの前提です。
想定読者
- GitHub Pagesで静的Webサイトを公開していてDBと連携させたい方
- Notionを簡易的な管理DBとして使いたい方
- Cloudflare Workers を使った軽量なバックエンド構成に興味がある方
※本記事で使用している画像は生成AIによって生成された画像です
全体構成
タイトルの通り、今回の実装には3つのサービスを利用しています。(いずれも無料)
構成は以下の通りです。
システム構成
- フロントエンド:GitHub Pages(HTML + JavaScript)
- バックエンド:Cloudflare Workers
- データ保存先:Notion Database
フロントエンドではフォーム送信のみを行って、バックエンドでNotion APIを実行する構成です。フロントエンドから直接Notion APIをcallすることも可能ですが、APIキーがWeb上で見えてしまうためセキュリティの観点で危険です。
構成のポイント
認証情報(NotionのAPIキー)をバックエンド(Workers)で隠蔽する
データ送信処理
フロントエンドとバックエンドのコードでは、それぞれ以下の処理を実装しています。実際のソースコードは後述します。
- フロントエンド:GitHub Pages
- Webフォームの送信ボタンがクリックされると、Cloudflare Workersのエンドポイントに対してPOSTリクエストを送信する
- バックエンド:Cloudflare Workers
- リクエストを受信したら、Notion APIを呼び出してデータベースにレコードを追加する
実装手順
Cloudflare Workers,Notionの設定手順と、フロントエンド/バックエンドのソースコードについて紹介します。
Notionの設定
Notionでデータベースを作成し、APIでデータベースを操作するためのIntegrationの設定を行います。
- 自分のワークスペースにアクセスし、左上のアイコンで「Database」をクリック
- データベースのプロパティについて以下のように設定(必要に応じて変更してください)
データベースのプロパティ
| 名前 | type | 備考 |
|---|---|---|
| Name | タイトル | 必須のため削除不可 |
| フォームで入力されるメールアドレス | ||
| UserName | テキスト | フォームで入力される名前 |
| Source | テキスト | 送信元URL(フォームのURLを取得) |
| Status | セレクト |
Unconfirmed/Confirmed (最初は Unconfirmedで登録) |
| CreatedAt | 日付 | 登録日時 |
ここまでで、一旦データベースの設定は完了です。 次は、 Notionの Integration 管理画面 から、データベースをAPIで操作するための設定を行います。
- 「New Integration」をクリック
- 任意の名前を入力し、「Associated workspace」でDBを作成したワークスペースを選択。Typeは「Internal」を選択したら「Save」をクリック
- Integrationが作成されたら「Internal Integration Secret」の「Show」をクリックして値をメモする(これがAPIキーです)
- 「Access」タブ >「Edit access」から作成したデータベースを選択
- データベースの画面に戻り、右上の「・・・」アイコン > 「Connections」に先ほど作成したIntegrationの名前が表示されていることを確認する
ここまでで、Notionの設定は完了です。自分のワークスペースとIntegration管理画面の2つで操作が必要な点にご注意ください。
Cloudflare Workersの設定
Workersではエンドポイントの作成・コードのデプロイと、コードから呼び出す環境変数の設定を行います。
- Cloudflare Dashboard>「Workers&Pages」で「Create application」をクリック
- 「Start with Hello World!」をクリック
- 任意の名前を入力し、以下のソースコードを貼り付けて「Deploy」をクリック
Workersのソースコード(JavaScript)
export default {
async fetch(req, env) {
const url = new URL(req.url);
const origin = req.headers.get("Origin") || "";
// 環境に合わせて変更
const ALLOWED_ORIGINS = [
"Webサイトのドメイン"
];
const corsHeaders = {
"Access-Control-Allow-Methods": "POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Max-Age": "86400",
};
if (ALLOWED_ORIGINS.includes(origin)) {
corsHeaders["Access-Control-Allow-Origin"] = origin;
}
if (req.method === "OPTIONS") {
return new Response(null, { status: 204, headers: corsHeaders });
}
if (req.method !== "POST" || url.pathname !== "/subscribe") {
return new Response("Not Found", { status: 404, headers: corsHeaders });
}
const body = await req.json();
const email = (body.email || "").trim();
const name = (body.name || "").trim();
const source = (body.source || "").trim();
if (!email) {
return new Response("Invalid email", { status: 400, headers: corsHeaders });
}
await fetch("https://api.notion.com/v1/pages", {
method: "POST",
headers: {
Authorization: `Bearer ${env.NOTION_TOKEN}`,
"Notion-Version": "2022-06-28",
"Content-Type": "application/json",
},
body: JSON.stringify({
// 環境変数を読み込んで、Notionのデータベースを特定
parent: { database_id: env.NOTION_DB_ID },
// データベースに追加する内容
properties: {
Name: { title: [{ text: { content: email } }] },
Email: { email },
UserName: name ? { rich_text: [{ text: { content: name } }] } : undefined,
Source: { rich_text: [{ text: { content: source } }] },
Status: { select: { name: "unconfirmed" } },
CreatedAt: { date: { start: new Date().toISOString() } }
}
}),
});
return new Response(
JSON.stringify({ ok: true }),
{ status: 200, headers: { ...corsHeaders, "Content-Type": "application/json" } }
);
},
};
実装のポイント
- CORSを設定し、指定したオリジンのみを許可
-
/subscribeパスへのリクエストを受け付け、フォームから送信されたデータを処理 - リクエストを受信すると、Notion APIを呼び出してデータベースにレコードを追加
ここまでで、Workersにコードがデプロイされました。コードが安全にAPIキーを読み込むために環境変数を設定します。
- Worker管理画面で「Settings」タブ > 「Variables and Secrets」で「Add」ボタンをクリックして、表のとおり環境変数を追加
環境変数の設定
| Variable name | Type | Value | 確認方法 |
|---|---|---|---|
NOTION_TOKEN |
Secret | NotionのAPIキー | NotionのIntegration 管理画面で 「Internal Integration Sercret」を確認 |
NOTION_DB_ID |
Secret | データベースのID | NotionのデータベースURLの xxxxxxxの部分https://www.notion.so/xxxxxxx?v=yyyyyy
|
以下のように2つ追加できたら完了です。
認証情報はコードに直接記述せず、環境変数で管理する
動作確認
ここまでの設定で、WorkersからNotionのデータベースの操作が可能になっています。curlやPowerSellでWorkersのエンドポイントにリクエストを送信して動作確認してみます。
curlコマンドが実行できる場合は以下のコマンドで確認できます。<WorkersのURL>は適宜、環境に合わせて変更してください。
curl -X POST <WorkersのURL>/subscribe \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","source":"manual-test"}'
今回は開発環境がWindowsだったので、以下のPowerShellコマンドを使用しました。
$body = @{
email = "test@example.co.jp"
source = "powershell"
} | ConvertTo-Json
Invoke-RestMethod `
-Uri "<WorkersのURL>/subscribe" `
-Method POST `
-ContentType "application/json" `
-Body $body
上記のコマンドでWorkersにPOSTリクエストを送信しているため、Notion APIが実行されてNotionのデータベースにデータが追加されます。
Webフォームのソースコード
最後に、ホスティング済みのWebフォームにコードを追加します。以下のコードを追加することで、WebフォームからWorkersのエンドポイントにリクエストを送信するようになります。
WorkersへのPOST(JavaScript)
<script>
// htmlで設定している<form>のidに合わせて変更
const form = document.getElementById("leadForm");
form.addEventListener("submit", async (e) => {
e.preventDefault();
await fetch(
//環境に合わせて変更
"WorkersのURL/subscribe",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: form.name.value,
email: form.email.value,
source: location.href
})
}
);
alert("送信しました");
form.reset();
});
</script>
これで設定は全て完了です!
フォーム入力がデータベースに反映されているか確認
それでは、Webフォーム→Workers→Notionの流れでデータが登録されるか確認してみましょう。
- ホスティング済みのWebフォームに内容を入力する(入力項目が他にもありますが、今回はまずメールアドレスのみ確認します)
- Notionのデータベースを確認する
上記のとおり、データベースにフォームの入力内容が追加されていればOKです。SourceにはWebフォームのURLが入力されているはずです。
Webフォームの送信が失敗する場合
Workersへのリクエスト送信 は成功しているのに、Webフォームからの送信が失敗する場合はCORSの設定不備の可能性が高いです。
WorkersにデプロイしたコードでWebフォームのドメインを許可しているか確認してください。
まとめ
Cloudflare WorkersとNotionを組み合わせることで、GitHub Pagesなどの静的サイトでも安全にデータを管理できます。
小規模なサイト・簡易的な問い合わせ管理であれば、この構成は実装・運用の面で扱いやすいと思いますので紹介した手順を参考にしてみてください。

















