1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Cloudflare Workers×NotionでGitHub Pagesからのフォーム入力を安全に保管する

1
Last updated at Posted at 2025-12-15

image.png

はじめに

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を呼び出してデータベースにレコードを追加する

image.png

実装手順

Cloudflare Workers,Notionの設定手順と、フロントエンド/バックエンドのソースコードについて紹介します。

Notionの設定

Notionでデータベースを作成し、APIでデータベースを操作するためのIntegrationの設定を行います。

  • 自分のワークスペースにアクセスし、左上のアイコンで「Database」をクリック

image.png

  • データベースのプロパティについて以下のように設定(必要に応じて変更してください)

image.png

データベースのプロパティ

名前 type 備考
Name タイトル 必須のため削除不可
Email Email フォームで入力されるメールアドレス
UserName テキスト フォームで入力される名前
Source テキスト 送信元URL(フォームのURLを取得)
Status セレクト Unconfirmed/Confirmed
(最初はUnconfirmedで登録)
CreatedAt 日付 登録日時

ここまでで、一旦データベースの設定は完了です。 次は、 Notionの Integration 管理画面 から、データベースをAPIで操作するための設定を行います。

  • 「New Integration」をクリック

image.png

  • 任意の名前を入力し、「Associated workspace」でDBを作成したワークスペースを選択。Typeは「Internal」を選択したら「Save」をクリック

image.png

  • Integrationが作成されたら「Internal Integration Secret」の「Show」をクリックして値をメモする(これがAPIキーです)

image.png

  • 「Access」タブ >「Edit access」から作成したデータベースを選択

image.png

  • データベースの画面に戻り、右上の「・・・」アイコン > 「Connections」に先ほど作成したIntegrationの名前が表示されていることを確認する

image.png

ここまでで、Notionの設定は完了です。自分のワークスペースとIntegration管理画面の2つで操作が必要な点にご注意ください。

Cloudflare Workersの設定

Workersではエンドポイントの作成・コードのデプロイと、コードから呼び出す環境変数の設定を行います。

image.png

  • 「Start with Hello World!」をクリック

image.png

  • 任意の名前を入力し、以下のソースコードを貼り付けて「Deploy」をクリック

image.png

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」ボタンをクリックして、表のとおり環境変数を追加

image.png

image.png

環境変数の設定

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つ追加できたら完了です。

image.png

認証情報はコードに直接記述せず、環境変数で管理する

動作確認

ここまでの設定で、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のデータベースにデータが追加されます。

image.png

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フォームに内容を入力する(入力項目が他にもありますが、今回はまずメールアドレスのみ確認します)

image.png

  • Notionのデータベースを確認する

image.png

上記のとおり、データベースにフォームの入力内容が追加されていればOKです。SourceにはWebフォームのURLが入力されているはずです。

Webフォームの送信が失敗する場合
Workersへのリクエスト送信 は成功しているのに、Webフォームからの送信が失敗する場合はCORSの設定不備の可能性が高いです。
WorkersにデプロイしたコードでWebフォームのドメインを許可しているか確認してください。

まとめ

Cloudflare WorkersとNotionを組み合わせることで、GitHub Pagesなどの静的サイトでも安全にデータを管理できます。
小規模なサイト・簡易的な問い合わせ管理であれば、この構成は実装・運用の面で扱いやすいと思いますので紹介した手順を参考にしてみてください。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?