Eleventy
Nunjucks、Liquid、Markdown のテンプレートで Ikiform のフォームを描画する Eleventy のショートコード。フォーム ID はグローバルデータで管理します。
Eleventy は静的な HTML を出力するので、フォームはクライアントの JavaScript なしで送信されます。ショートコードならマークアップを 1 か所にまとめられ、Nunjucks、Liquid、Markdown のどのファイルでも同じように動きます。
セットアップ
ショートコードを追加する
eleventy.config.js const escape = (value) => String(value).replace(/[&<>"']/g, (char) => `&#${char.charCodeAt(0)};`); export default function (eleventyConfig) { eleventyConfig.addShortcode("ikiform", (formId, thanks = "", subject = "") => [ `<form class="ikiform" action="https://ikiform.com/f/${encodeURIComponent(formId)}" method="post">`, '<label>Email <input name="email" type="email" autocomplete="email" required></label>', '<label>Message <textarea name="message" rows="5"></textarea></label>', thanks && `<input type="hidden" name="_redirect" value="${escape(thanks)}">`, subject && `<input type="hidden" name="_subject" value="${escape(subject)}">`, '<input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden>', '<button type="submit">Send</button>', "</form>", ] .filter(Boolean) .join("\n"), ); }- 行は意図的に空行なしでつなげています。Markdown では空行で HTML ブロックが終わり、フォームの残りがテキストとして扱われてしまいます。
- これは ES モジュールの構文を使っています。
package.jsonに"type": "module"がない場合は、ファイル名をeleventy.config.mjsにしてください。
フォーム ID をグローバルデータに置く
_data/ikiform.js export default { formId: process.env.IKIFORM_FORM_ID ?? "frm_xxxxxxxxxxxxxxxx", thanks: "https://example.com/thanks/", };グローバルデータは、すべてのテンプレートで
ikiformとして使えます。Ikiform はそれ以外のリダイレクトを無視するため、サンクスページの URL はhttps:の絶対 URL にする必要があります。使う
contact.md --- title: Contact --- Questions about pricing? Write to us. {% ikiform ikiform.formId, ikiform.thanks, "Pricing question" %}Markdown ファイルはデフォルトで Liquid で処理されるので、タグはそのまま動きます。タグは独立した行に置き、4 つのスペースでインデントしないでください。インデントすると Markdown がコードブロックとして描画します。同じタグは
.njkと.liquidのファイルでも動きます。
_redirect に従うのは、フォームの許可ドメインに自分のサイトが含まれている場合だけです。_redirect のルールを参照してください。
許可ドメイン
本番とそれぞれのプレビューのホストを登録します。Eleventy のサイトは Netlify や Cloudflare Pages にデプロイされることが多く、プレビューの扱いはそれぞれ異なります。
| フォームが動く場所 | 許可ドメインに追加するもの |
|---|---|
npx @11ty/eleventy --serve | localhost。http://localhost:8080 に一致します。Ikiform が比較するのはホスト名だけで、ポートは比較しません。 |
| 自分のドメイン | example.com(www.example.com も含まれます) |
| Netlify | your-site.netlify.app。デプロイプレビュー(deploy-preview-12--your-site.netlify.app)やブランチデプロイ(branch--your-site.netlify.app)はそのサブドメインではないので、テストする間はプレビューの正確なホストを追加してください。 |
| Cloudflare Pages | your-project.pages.dev。abc123.your-project.pages.dev のようなプレビュー URL はそのサブドメインなので、すでに一致します。 |
netlify.appやpages.devだけを追加しないでください。他の人のサイトも含め、そのホスト上のすべてのサイトが一致してしまいます。
テストのチェックリスト
- 開発サーバーを実行し、ページのソースを表示します。フォームは
<pre><code>ブロックの中ではなく、プレーンな HTML になっているはずです。 - 許可ドメインに
localhostを入れてローカルで送信し、送信データが Ikiform に表示されることを確認します。 - プレビューをデプロイし、プレビューのホストからもう一度送信します。
- 本番で送信し、サンクスページに移動することを確認します。
トラブルシューティング
| 症状 | 原因 | 対処 |
|---|---|---|
| フォームがページにコードとして表示される | Markdown ファイルでショートコードが 4 つのスペースでインデントされている | タグを行の先頭に移動します。 |
| フォームの半分が段落として描画される | ショートコードの出力に空行が含まれていて、Markdown の HTML ブロックが終わってしまう | 上の設定のように、空行なしで行をつなげます。 |
Eleventy の起動時に SyntaxError: Unexpected token 'export' が出る | CommonJS のプロジェクトで、設定ファイルが ES モジュールの構文を使っている | ファイル名を eleventy.config.mjs にするか、package.json に "type": "module" を追加します。 |
Nunjucks や Liquid が ikiform タグを見つけられない | Eleventy が設定ファイルを読み込んでいない | ファイルがプロジェクトのルートにあり、名前が eleventy.config.js か .mjs になっているか確認します。 |
送信データが origin_mismatch でスパムフィルターの下に届く | 送信したページが、フォームの許可ドメインに含まれていない | 上の表のホストを追加します。Reject を選んでいる場合、同じ送信には代わりに 403 origin_not_allowed が返ります。 |