静的サイトのお問い合わせフォーム2 分で読めます
GitHub Pages のサイトにお問い合わせフォームを追加する
GitHub Pages ではサーバーコードが動かず、フォームの POST は 405 Not Allowed になります。フォームバックエンドに送信し、プロジェクトサイトのリダイレクトを正しく設定しましょう。
GitHub Pages は静的ファイルしか配信しないので、自分のサイトに送信するフォームは 405 Not Allowed になり、メッセージは失われます。フォームの action を Ikiform のエンドポイントにし、username.github.io と独自ドメインを Allowed domains に追加して、プロジェクトサイトのパスを含むサンクスページにリダイレクトします。リポジトリも Pages の設定も変わらず、公開リポジトリにシークレットが入ることもありません。
GitHub Pages ならではの違い
GitHub Pages が公開するのは、リポジトリか Actions のワークフローがビルドしたものだけです。Jekyll を使うならビルド時に動き、その結果はファイルになります。リクエストを処理する仕組みがないので、何をコミットしても PHP の mail()、Node のスクリプト、Python の CGI フォームは動きません。
失敗はターミナルで確認できます。Pages のサイトのどのページに POST しても、次の結果になります:
curl -i -X POST -d "message=hello" https://ada.github.io/notebook/contact.htmlHTTP/2 405
server: Varnish
content-length: 131
<html>
<head><title>405 Not Allowed</title></head>Pages には他の静的ホストと違う点がさらに 4 つあり、どれもお問い合わせフォームに関わります:
| Pages の特徴 | フォームへの影響 |
|---|---|
プロジェクトサイトは username.github.io/repo/ のようにパスの下に置かれる | /thanks.html というサンクスページの URL は、プロジェクトではなくユーザーサイトを指す。どの URL にも /repo/ の部分が必要 |
| カスタムのレスポンスヘッダーを設定できない | Content-Security-Policy は、ページ内の <meta> タグでしか指定できない |
| リポジトリは公開されていることが多い | 中身はすべて公開される。フォーム ID なら問題ないが、シークレット API キーやメールのパスワードは絶対に置かない |
| GitHub は、パスワードやクレジットカード番号の送信など機密性の高い取引に Pages サイトを使うべきではないとしている | お問い合わせフォームはお問い合わせ専用にする。カード情報やアカウントのパスワードを集めない |
- Pages の公開元のブランチに push します。
- Jekyll か Actions のワークフローがサイトを 1 回ビルドします。
- Pages はその結果を、github.io か独自ドメインで静的ファイルとして配信します。
- 訪問者がお問い合わせフォームを送信します。action が自分のサイトを指していると、Pages は 405 Not Allowed を返します。
- action を Ikiform のエンドポイントにすれば、Ikiform がメッセージを保存してメールで通知します。
- Ikiform はブラウザーをサンクスページにリダイレクトし、Pages はそれを他のファイルと同じように配信します。
フォーム
手書きのサイトなら、index.html の隣に contact.html を追加します。この例は ada.github.io/notebook のプロジェクトサイト用なので、リダイレクト先に /notebook/ が含まれます:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; form-action 'self' https://ikiform.com; connect-src 'self' https://ikiform.com"
/>
<title>Contact</title>
</head>
<body>
<h1>Get in touch</h1>
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
<label for="name">Name</label>
<input id="name" name="name" autocomplete="name" required />
<label for="email">Email</label>
<input id="email" name="email" type="email" autocomplete="email" required />
<label for="about">What is it about?</label>
<select id="about" name="about">
<option value="question">A question about the project</option>
<option value="hire">Work together</option>
<option value="other">Something else</option>
</select>
<label for="message">Message</label>
<textarea id="message" name="message" rows="6" minlength="10" required></textarea>
<input type="hidden" name="page" value="docs-home" />
<input type="hidden" name="_redirect" value="https://ada.github.io/notebook/thanks.html" />
<input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
<button type="submit">Send</button>
</form>
</body>
</html><meta>の Content-Security-Policy は任意です。すでにあるなら残し、form-actionとconnect-srcにhttps://ikiform.comが含まれていることを確認してください。Pages は代わりにヘッダーを送れません。aboutのセレクトボックスで、メッセージを開く前に問い合わせの理由がわかります。選択肢は、実際に届く問い合わせの内容に合わせて変えてください。- hidden の
page入力欄は、フォームが置かれていたページを記録します。同じフォームを複数のドキュメントページに置くときに便利です。 - フィールド名は
emailのままにしてください。通知メールはこれを reply-to アドレスとして使います。
同じ HTML を複数のパスにデプロイする場合や、最終的なパスがわからない場合は、ページ自身のアドレスからブラウザーでリダイレクト先を組み立てます。フォームの後にこれを置きます:
<script>
document.querySelectorAll('input[name="_redirect"]').forEach((input) => {
input.value = new URL("thanks.html", document.baseURI).href;
});
</script>Jekyll を使っていますか?それなら URL をハードコードする必要はありません。Jekyll ガイドに、absolute_url で URL を組み立てる include があり、プロジェクトサイトでは baseurl を付けてくれます。Astro、Vite、Hugo を Actions のワークフローでビルドしているなら、フォームのアセットが読み込まれるようにフレームワークのベースパスを /repo/ に設定し、フォーム自体は Hugo や各フレームワークのガイドに従ってください。
github.io での許可ドメイン
自分のユーザー名で ada.github.io を追加します。プロジェクトサイトは同じホストを共有するので、これでユーザーサイトとすべてのプロジェクトサイトをカバーできます。独自ドメインを使っているならそれも追加します。example.com は www.example.com もカバーします。
github.io だけを追加してはいけません。他人のサイトにあるあなたのフォームのコピーも含め、すべての Pages サイトが一致してしまいます。許可ドメインを設定していれば https://ada.github.io/notebook/thanks.html への _redirect に従いますが、設定していなければ Ikiform はそれを無視し、自身がホストするサンクスページを表示します。
https: で始まる _redirect の値だけで、証明書がまだない独自ドメインは http: でページを配信します。mailto: リンクを置き換える
多くの Pages サイトは、フッターの mailto: リンクから始まります。これをフォームに置き換えれば、新たなスクレイパーにページからアドレスを読み取られなくなり、メールアプリを設定していない訪問者も連絡できるようになります。削除する前に知っておくべきことが 2 つあります:
- アドレスはリポジトリの履歴や、古いページのフォークやアーカイブに残ります。フォームが役立つのはこれからの分で、何年も公開されていたアドレスが非公開に戻るわけではありません。
- 返信は自分の受信トレイから行います。通知メールは送信者を reply-to アドレスに設定するので、Reply を押せば、
mailto:リンクと同じことを逆側から行えます。
Ikiform は訪問者にメールを送らないので、いつごろ返事が届くかをサンクスページに書いておきましょう。メールで返しきれないほどメッセージが届くなら、Webhook で 1 件ずつ Slack や Discord に送ることもできます。
動作を確認する
これは公開中の github.io のアドレスで実行してください。Pages にはプレビューのデプロイがないので、まずローカルサーバーでテストします。
- Allowed domains に
localhostとusername.github.io、独自ドメインがあればそれも追加します。 contact.htmlとthanks.htmlをコミットし、リポジトリの Actions タブで Pages のデプロイが終わるのを待ってから、公開中のページを開きます。- フォームを送信します。アドレスバーにプロジェクトのパスが入った、自分の
thanks.htmlに移動するはずです。 - ダッシュボードで Submissions を開きます。送ったすべてのフィールドを含む新しい送信データがあります。
- 通知の受信者それぞれの受信トレイを確認します。各自にフィールド入りのメールが届き、フォームに
emailフィールドがあれば Reply の宛先は送信者になります。 - 何も届かない場合は、ダッシュボードのステータスフィルターを Spam に切り替えてください。スパムにも本物の送信と同じ成功の応答が返ります。
ハマりどころ
| 問題 | 対処 |
|---|---|
送信を押すと 405 Not Allowed になる | デプロイされたフォームがまだ自分のサイトに送信しています。github.io でページのソースを表示して action を確認してください。古いキャッシュのビルドが数分間残っていることもあります。 |
| 自分のページではなく Ikiform のサンクスページが表示される | _redirect の値にリポジトリのパスがない、http: になっている、またはフォームに許可ドメインがありません。username.github.io を追加し、完全な https: の URL を使ってください。 |
403 origin_not_allowed が返るか、すべての送信がスパムになる | ページのドメインがフォームの Allowed domains にありません。ドメインと、ローカルのテスト用に localhost を追加してください。登録済みドメインのサブドメインは許可されます。 |
| ローカルでは送信できるのに、github.io ではコンソールに CSP エラーが出る | レイアウトの <meta> の Content-Security-Policy で、form-action か connect-src に https://ikiform.com がありません。 |
よくある質問
できません。GitHub Pages は静的ファイルを配信するだけで、訪問者がフォームを送信してもコードは実行されないため、Pages の URL への POST は 405 Not Allowed になります。代わりにフォームの action をフォームバックエンドに向けてください。
はい。フォーム ID はどのみち公開される HTML に含まれます。許可ドメインとスパムチェックでフォームを守り、シークレット API キーは絶対にコミットしないでください。静的サイトにはそれを安全に保管する場所がありません。
/thanks.html のようなパスは、プロジェクトではなく username.github.io のルートを指します。リポジトリのパスを含む完全な URL を使うか、ブラウザーで document.baseURI から組み立ててください。
はい。ページをどのドメインで配信しても、フォームは Ikiform に送信されます。Allowed domains に username.github.io と並べて独自ドメインを追加し、HTTPS を強制したら _redirect の値も独自ドメインに更新してください。
いいえ、無料プランはありません。テストは無料で、支払いの前に localhost から月 50 件のテスト送信ができます。本番運用するには、月 $6 で 500 件からの Pro を選ぶか、1 回払いで 10,000 件 $49 または 50,000 件 $149 を購入できます。クレジットに有効期限はありません。
手順で詰まったときや、あなたの状況に合うガイドがほしいときはメールでどうぞ: hello@ikiform.com