2026.10.21

独自テンプレートの問い合わせページでCloudflare Turnstileが動かない原因と解決(Contact Form 7)

独自テンプレートの問い合わせページでCloudflare Turnstileが動かない原因と解決(Contact Form 7)

Contact Form 7(CF7)にCloudflare Turnstileを連携したのに動かないときは、テーマがwp_footerを通しておらず、Turnstile本体のスクリプト(api.js)が出力されていない可能性があります。CF7はフォームにウィジェット用の要素を挿入してくれますが、api.jsがなければトークンは作られません。この記事では、独自テンプレートの問い合わせページで実際に起きたこの問題と、連携が有効なときだけ読み込む条件つきの解決方法を紹介します。

背景: 公開にあわせてスパム対策を入れた

当社サイトの一般公開にあわせて、問い合わせフォームのスパム対策にCloudflare Turnstileを導入しました。設定は次のとおりです。

CF7にはTurnstileとの連携機能が標準で入っているので、通常のテーマであればこれだけで動きます。

症状: ウィジェット要素はあるのに、トークンが作られない

ところが当社の問い合わせページでは、連携後にフォームのHTMLを確認すると、CF7が.cf-turnstileの要素を挿入しているのに、Turnstile本体のスクリプト(api.js)がページのどこにも出力されていませんでした。

原因はテンプレートの作りです。当社の問い合わせページは独自テンプレートで、wp_footerを通さず、CF7が必要とするJavaScriptを手動で読み込んでいます。そのため、通常ならwp_footer経由で出力されるTurnstileのスクリプトが、このページでは出てきませんでした。

この状態では検証用のトークンが作られないので、スパムだけでなく正当な問い合わせまで弾かれるおそれがありました。見た目には何も変わらない(Invisibleモードは元々何も表示しない)ため、気づきにくい不具合です。

実装: 連携が有効なときだけ、手動で読み込む

テンプレートの末尾、CF7本体のスクリプトを読み込んだ直後に、CF7が行うのと同じ読み込みを追加しました。

<?php if ( class_exists('WPCF7_Turnstile') && WPCF7_Turnstile::get_instance()->is_active() ): // Cloudflare Turnstile(CF7標準連携)。このテンプレートは wp_footer を通さないため、CF7本体と同じ読み込みを手動で行う ?>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async></script>
<script>document.addEventListener('wpcf7submit', function(){ if (window.turnstile) turnstile.reset(); });</script>
<?php endif; ?>

ポイントは2つです。

検証: 自動テストでは最後まで確認できない

反映後に確認したのは次の点です。

ハマりポイント

自動操作のブラウザではトークンが発行されない

確認に使った自動操作のブラウザでは、Turnstileのトークンが発行されませんでした。ボットを弾く仕組みなので当然ですが、これは「最後の送信テストは自動化できない」ことを意味します。実際の送信は人が実ブラウザで行い、完了メッセージの表示、通知メールの受信、受信履歴(Flamingo)への記録までを確認して、稼働と判断しました。

Invisibleモードにはプライバシーポリシーの記載が必要

Invisibleモードは画面に何も表示しないぶん、利用条件として、プライバシーポリシーでTurnstileの利用とTurnstile Privacy Addendumに触れる必要があります。当社では「不正利用防止ツールについて」という節を新設して対応しました。スクリプトが動いたところで終わりにせず、ここまでを導入作業に含めておくと漏れません。

まとめ

スパム対策のバッジや読み込みを必要なページだけに絞る考え方は、reCAPTCHA v3のバッジを問い合わせページ以外で消す方法でも紹介しています。

Webサイトの構築や、こうした設計のご相談は、SERVICESからお気軽にどうぞ。

← TECH-BLOG一覧へ