【MW WP Form】Google reCAPTCHAからCloudflare Turnstileへ移行!プラグイン不要のスパム対策

WordPressの定番フォームプラグイン「MW WP Form」でスパム対策を行う際、これまで当たり前のように使われてきたのが「Google reCAPTCHA」でした。

しかし、近年Google側の仕様変更が相次ぎ、特にクライアントワーク(受託制作)においてreCAPTCHAを導入するハードルが非常に高くなっています。

この記事では、reCAPTCHAが使いにくくなった背景と、その最適な代替案である「Cloudflare Turnstile」を、追加プラグインなしでMW WP Formに実装する方法をわかりやすく解説します。

コピペで動くコードも記載しているので、ぜひ参考にしてみてね。

目次

なぜGoogle reCAPTCHAは使いにくくなったのか?

長年無料で使えていたGoogle reCAPTCHAですが、以下の2つの大きな仕様変更により、実質的に「手軽に導入できるツール」ではなくなってしまいました。

1. 無料枠の大幅な引き下げ(2024年8月〜)

2024年8月1日より、reCAPTCHA(Enterprise版への統合に伴い)の料金体系が改定されました。これまで月間100万回まで無料だった評価枠が、月間1万回にまで大幅に縮小されました。 一般的なコーポレートサイトであれば月1万回でも十分なケースが多いですが、「いつか上限を超えるかもしれない」という懸念を抱えながら運用することになります。

2. Google Cloudへのクレジットカード登録が必須に

管理画面が従来の専用コンソールから「Google Cloud コンソール」へと完全に移行し、利用にあたって「請求先アカウント(クレジットカード等の支払い情報)」の登録・紐付けが原則必須となりました。

クライアントのサイトに導入する場合、「Googleアカウントを取得し、Google Cloudのプロジェクトを作成し、会社のクレジットカードを登録してください」とお願いするのは、現実的にかなり困難です。

MW WP Formの現在の開発状況について

もう一つ、MW WP Form自体の状況も理解しておく必要があります。

MW WP Formは、2023年9月にオリジナル開発者様による積極的な新規開発が終了しています。 現在は「株式会社Webの相談所」様がプロジェクトを引き継ぎ、脆弱性対応やPHPバージョンへの対応など、最低限のメンテナンス運用を行ってくださっている状態です。

大変ありがたいことですが、新機能の追加が行われない以上、「新しいスパム対策システムへの公式対応は期待できない」という前提で、私たち制作者側が工夫して実装する必要があります。

救世主「Cloudflare Turnstile」とは?

Google reCAPTCHAの代替として現在もっとも選ばれているのが、Cloudflare社が提供する「Turnstile(ターンスタイル)」です。

完全に無料

厳しい回数制限や、クレジットカード登録の催促がありません。制作者のアカウント1つで、複数クライアントのサイトのキーを一括管理できます。

ユーザーに優しい(パズルなし)

「信号機を選んでください」といった面倒な画像パズルが出ず、バックグラウンドでスムーズに人間かボットかを判定してくれます。

プライバシー重視

ユーザーの行動トラッキングを行わないため、企業サイトにも適しています。

MW WP FormへTurnstileを実装する手順(コピペOK)

Contact Form7やWP Formをお使いの場合は、連携用のプラグインをインストールことで比較的かんたんに導入できます。MW WP Formの場合は対応しているプラグインが無いので、今回は追加プラグインなしで、functions.phpの記述のみで完結する方法をご紹介します。

MW WP Formの「確認画面」を挟むタイプのフォームで、重複バリデーションエラー(timeout or duplicate)も回避できる、一元管理用のコードです。

STEP 1: Cloudflareでキーを取得する

  1. Cloudflare Turnstile にログインし、「Add widget(ウィジェットを追加)」をクリック。
  2. 管理名と対象サイトのドメイン(例:example.com)を登録します。
  3. Widget Modeは「Managed (Recommended)」を選択して「Create」。
  4. 発行された 「Site Key」「Secret Key」 を控えておきます。

STEP 2: フォームの編集(HTMLの追加)

MW WP Formのフォーム編集画面(コードエディタ)を開き、送信ボタン(または確認画面へ進むボタン)の直上に以下のコードを貼り付けます。

[mwform_hidden name="turnstile-check" value="1"]
[mwform_error keys="turnstile-check"]
<div class="cf-turnstile" data-sitekey="★ここにSite Keyを貼り付ける★"></div>

data-sitekey の部分を、STEP1で取得したSite Keyに書き換えてください。

STEP 3: functions.php へのコード追記

テーマの functions.php の末尾に以下のコードを追記します。 (※事前に必ずファイルのバックアップを取ってから作業してください)

  • フォームを設置している固定ページのIDと、フォームのIDを書き換える(フォームが複数の場合には行を追加する)
  • ★ここにSecret Keyを貼り付ける★の部分(14行目)を、STEP1で取得したSecret Keyに書き換える
/**
 * MW WP Form: Cloudflare Turnstile の統合管理(読み込み & 検証処理)
 */

// 1. 設定の統合管理(固定ページID => MW WP FormのフォームID)
// フォームを設置している「固定ページのID」と、MW WP Formの「フォーム識別子(ID)」をペアで記述します。
$turnstile_settings = array(
    100 => 68,   // 例: お問い合わせページの固定ページID => フォームID
    // 101 => 1169, 複数ページある場合
);

// 2. Cloudflare Secret Key の設定
// 取得した Secret Key を記述します。
define( 'MY_TURNSTILE_SECRET_KEY', '★ここにSecret Keyを貼り付ける★' );

// --- 以下、コア処理(基本は変更不要です) ---

/**
 * A. 特定のページでのみ Turnstile スクリプトを動的読み込み
 */
function enqueue_turnstile_on_specific_pages() {
    global $turnstile_settings;
    if ( is_page( array_keys( $turnstile_settings ) ) ) {
        wp_enqueue_script(
            'cloudflare-turnstile',
            'https://challenges.cloudflare.com/turnstile/v0/api.js',
            array(),
            null,
            array( 'strategy' => 'defer', 'in_footer' => false )
        );
    }
}
add_action( 'wp_enqueue_scripts', 'enqueue_turnstile_on_specific_pages' );

/**
 * B. MW WP Form カスタムバリデーション処理(重複エラー回避・警告対策版)
 */
function my_mwform_turnstile_validation( $Validation, $data ) {
    static $is_verified = false;
    if ( $is_verified || empty( $data ) ) {
        return $Validation;
    }

    // --- 【修正】チェックボックス等の配列データを安全にスキップする処理を追加 ---
    $has_target_word = function( $target_words, $form_data ) {
        foreach ( $form_data as $val ) {
            if ( is_array( $val ) ) continue; // 配列(チェックボックス等)はスキップ
            if ( in_array( $val, $target_words, true ) ) return true;
        }
        return false;
    };

    // 「戻る」ボタンでの遷移時は検証スキップ
    $back_words = array( '戻る', 'back', '入力内容を修正する' );
    if ( $has_target_word( $back_words, $data ) || ( isset( $data['submitBack'] ) && $data['submitBack'] === 'back' ) ) {
        return $Validation;
    }

    // 「送信する(完了画面へ)」遷移時は検証スキップ
    $submit_words = array( '送信する', '送信', '予約する', 'send', 'この内容で送信する' );
    if ( $has_target_word( $submit_words, $data ) ) {
        return $Validation;
    }
    // ------------------------------------------------------------------------

    // サニタイズしてトークンを取得(セキュリティ強化)
    $turnstile_token = isset( $_POST['cf-turnstile-response'] ) ? sanitize_text_field( wp_unslash( $_POST['cf-turnstile-response'] ) ) : '';

    if ( empty( $turnstile_token ) ) {
        $Validation->set_rule( 'turnstile-check', 'no_token', array(
            'message' => 'スパム対策のチェックを行ってください。'
        ));
        return $Validation;
    }

    // Cloudflare API で検証
    $response = wp_remote_post( 'https://challenges.cloudflare.com/turnstile/v0/siteverify', array(
        'body' => array(
            'secret'   => MY_TURNSTILE_SECRET_KEY, // 先ほど define で定義した定数
            'response' => $turnstile_token,
            'remoteip' => $_SERVER['REMOTE_ADDR'],
        ),
    ) );

    $response_data = json_decode( wp_remote_retrieve_body( $response ), true );
    $is_verified = true; // 二重検証エラーの防止

    if ( ! $response_data['success'] ) {
        $Validation->set_rule( 'turnstile-check', 'turnstile_failed', array(
            'message' => '迷惑ボットとしてブロックされました。もう一度お試しください。'
        ));
    }

    return $Validation;
}

// 登録されたフォームIDに対して動的にフックを追加
foreach ( array_values( $turnstile_settings ) as $form_id ) {
    add_filter( 'mwform_validation_mw-wp-form-' . $form_id, 'my_mwform_turnstile_validation', 10, 2 );
}

重複バリデーションエラーの回避について

MW WP Formは、画面遷移の判定を$_POSTで送信される「ボタンのvalue」に依存しています。

STEP

確認画面へ進む時

$_POST['confirm'] には "確認画面へ" が入るため、上のスキップ処理には引っかからず、TurnstileのAPI検証が実行されます

STEP

完了画面へ進む(送信する)時

$_POST['confirm'] には "送信する"(または "この内容で送信する")が入るため、$submit_words に一致し、TurnstileのAPI検証がスキップされます

このように設定することで、「最初の1回(確認画面へ行く時)だけ人間チェックを行い、その後の遷移ではチェックをパスさせる」という動きが完璧に成立します。

補足:ボタンの文言(value)を変更している場合の注意点

実案件では、フォームのボタン名をデフォルトから変更することがよくありますよね。 例えば、以下のようにショートコードを設定している場合です。

[mwform_backButton value="入力内容を修正する"]
[mwform_submitButton name="confirm" confirm_value="確認画面へ" submit_value="この内容で送信する"]

今回の仕組みは、「押されたボタンのテキスト(value)を見て、どの画面への遷移かを判定し、Turnstileの重複検証をスキップする」というロジックになっています。

そのため、もしボタンのテキストを変更した場合は、functions.phpに記述したコードの該当箇所(配列)にも、そのテキストを追加しておく必要があります。

// 修正前
$back_words = array( '戻る', 'back' );
$submit_words = array( '送信する', '送信', '予約する', 'send' );

// 修正後(実際のボタンの value を追加する)
$back_words = array( '戻る', 'back', '入力内容を修正する' );
$submit_words = array( '送信する', '送信', '予約する', 'send', 'この内容で送信する' );

これで実装は完了です!実際にフォームを開き、送信テストを行ってみてください。

おわりに

Google reCAPTCHAの仕様変更により、クライアントワークでのフォーム制作は少し面倒になりました。しかし、Cloudflare Turnstileを活用することで、クライアントに負担をかけることなく、以前よりもユーザビリティの高いスパム対策が可能になります。

MW WP Formは今後アップデートが見込めないため、ゆくゆくは他のフォームプラグインへの乗り換えも検討していく時期ですが、現在稼働しているサイトの延命・改善策として、このTurnstile実装コードが参考になれば幸いです。

  • URLをコピーしました!
  • URLをコピーしました!

WHO WROTE

Shinpei Okadaのアバター Shinpei Okada COO / AIエンジニア

地方テレビ局、歯科コンサル、中堅SIerを経て独立。ダイヤルアップ接続の時代にHTMLに魅せられ、なんだかんだ10年以上WEB制作に関わり続けている。近年はNotionとn8nを軸にしたワークフロー構築に注力。生活しているだけでユーザーの哲学や日々の情報を抽出・蓄積し、AIによるデータ活用が可能になるシステム「MIMIR」の開発に取り組んでいます。

目次