WordPress に reCAPTCHA v2 をプラグインを使わず導入する方法

Akira

福岡在住の Web デザイナー。Web サイト制作に役立つ情報を紹介しています。AMP が大好き。

FacebookTwitter で記事の更新をお知らせしています。

サイトを運営していて困るのが、スパムコメント。

サイト運営者にとっても、サイト訪問者にとっても、迷惑な存在です。

そこで導入したいのが reCAPTCHA 。

Google が導入を推奨する reCAPTCHA は、スパムコメントやスパムメールからサイトを強力に守ってくれます。

WordPress で運営するこのサイトに reCAPTCHA v2 を導入した際の方法を記事に残しておきます。

reCAPTCHA に登録

reCAPTCHA を使うには、reCAPTCHA への登録が必要です。

Google アカウントにログインした状態で、reCAPTCHA の公式サイトより登録します。

今回登録するのは reCAPTCHA v2 。

発行されるキーの管理名となる Label は、サイト名などご自身が管理しやすい名前にします。

Domains は、サイトドメインを入力します。複数のサイトを登録する場合は、1 行毎に 1 つのドメインを入力。

登録後は「Site key」と「Secret key」が発行されます。この 2 つは、サイトに reCAPTCHA を導入する際に必要です。

スクリプトの読み込み

「Site key」と「Secret key」を入手した後は、サイトに reCAPTCHA を設置していきます。

まずは以下の reCAPTCHA のスクリプトを <head> 内で読み込ませます。

<script src="https://www.google.com/recaptcha/api.js" async defer></script>

WordPress の作法に従うのなら、テーマの functions.php に下記コードを追加し読み込みます。

/** reCAPTCHA スクリプトの読み込み */
add_action( 'wp_enqueue_scripts', function() {
  wp_enqueue_script( 'google-recaptcha', 'https://www.google.com/recaptcha/api.js', array(), false, false );
});

/** reCAPTCHA スクリプトに async と defer を追加し非同期で読み込み */
add_filter( 'script_loader_tag', function( $tag, $handle, $src ) {
  if ( 'google-recaptcha' === $handle ) {
    $tag = '<script src="' . esc_url( $src ) . '" async defer></script>';
  }
  
  return $tag;
}, 10, 3 );

Contact Form 7 の reCAPTCHA 機能を使う場合

このサイトでは、Contact Form 7 でお問い合わせページを作成しています。

Contact Form 7 には reCAPTCHA 機能が備わっているため、お問い合わせページの reCAPTCHA は Contact Form 7 に任せます。

ただ、Contact Form 7 の reCAPTCHA 機能を使うと、Contact Form 7 もお問い合わせページで reCAPTCHA スクリプトを読み込みます。

全てのページの <head> 内で reCAPTCHA スクリプトを読み込むと、お問い合わせページで reCAPTCHA スクリプトが 2 つ読み込まれエラーが出ます。

そこで、このサイトでは投稿ページのみでスクリプトを読み込むことにしました。

<?php if ( is_single() === true ) { ?>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<?php } ?>

これでお問い合わせページでのエラーを回避。

reCAPTCHA を設置

次にコメントフォームに reCAPTCHA を設置します。

設置方法は 2 種類あります。

functions.php で設置

簡単なのは functions.php を使っての設置。

コメントフォームのテンプレートを変更したくない方に適した方法です。

下記のコードをテーマの functions.php に追加します。

add_filter( 'comment_form_default_fields', function( $fields ) {
  $fields['recaptcha'] = '<div class="g-recaptcha" data-sitekey="ここにSite keyを入力"></div>';
  
  return $fields;
});

2 行目のここにSite keyを入力に、発行された「Site key」を入力します。

これでコメント送信ボタンの上に、reCAPTCHA が設置されます。

テンプレートに設置

もう 1つの設置方法が、コメントフォームを呼び出しているテンプレートに直接設置するもの。

すでにコメントフォームのテンプレートを変更されている方に適した方法です。

ほとんどのテーマは、comments.php でコメントフォームを呼び出しているはずです。

例えば、下記のようにコメントフォームを変更します。

$commenter = wp_get_current_commenter();
$req       = get_option( 'require_name_email' );
$aria_req  = ( $req ? " aria-required='true'" : '' );
$fields    = array(
  'author'    => '<p class="comment-form-author"><label for="author">' . __( 'Name' ) . '</label> ' . ( $req ? '<span class="required">*</span>' : '' ) .
    '<input id="author" name="author" type="text" value="' . esc_attr( $commenter['comment_author'] ) . '" size="30"' . $aria_req . ' /></p>',
  'email'     => '<p class="comment-form-email"><label for="email">' . __( 'Email' ) . '</label> ' . ( $req ? '<span class="required">*</span>' : '' ) .
    '<input id="email" name="email" type="text" value="' . esc_attr(  $commenter['comment_author_email'] ) . '" size="30"' . $aria_req . ' /></p>',
  'url'       => '<p class="comment-form-url"><label for="url">' . __( 'Website' ) . '</label>' .
    '<input id="url" name="url" type="text" value="' . esc_attr( $commenter['comment_author_url'] ) . '" size="30" /></p>',
  'recaptcha' => '<div class="g-recaptcha" data-sitekey="ここにSite keyを入力"></div>',
);

$args = array(
  'fields' => apply_filters( 'comment_form_default_fields', $fields ),
);

comment_form( $args );

11 行目に、発行された「Site key」を入力します。

コメントフォーム変更の詳細は関数リファレンス/ comment form をご参考ください。

reCAPTCHA 認証を動かす

あとは reCAPTCHA の認証を動かせば終わりです。

下記のコードを functions.php に追加します。

add_action( 'pre_comment_on_post', function( $parameter = true ) {
  if ( isset( $_POST['g-recaptcha-response'] ) ) {
    $response = json_decode( wp_remote_retrieve_body( wp_remote_get( 'https://www.google.com/recaptcha/api/siteverify?secret=ここにSecret keyを入力&response=' . $_POST['g-recaptcha-response'] ) ), true );
    if ( $response['success'] ) {
      return $parameter;
    } else {
      wp_die( '<h1>認証に失敗しました</h1><p>「私はロボットではありません」にチェックを入れてください。</p>', '', array( 'back_link' => true ) );
    }
  } elseif ( ! isset( $_POST['g-recaptcha-response'] ) && ! is_user_logged_in() ) {
    wp_die( '<h1>ロボットと判定されました</h1><p>あなたがロボットでなければ、ブラウザの JavaScript を有効にしてください。</p>', '', array( 'response' => 403, 'back_link' => true ) );
  }
});

3 行目のここにSecret keyを入力に、発行された「Secret key」を入力します。

コードは Using Googles NoCaptcha ReCaptcha In WordPress を参考にしており、2 つの処理を追加しています。

reCAPTCHA のチェックが入っていない時には、「認証に失敗しました「私はロボットではありません」にチェックを入れてください。」と記載したエラーページに移動します。

「戻る」をクリックすると元のコメントフォームに戻る上に、フォームに入力した内容は消えずに維持されます。

また、ブラウザの JavaScript が無効になっており、reCAPTCHA が表示されていない状態でコメントを送信すると「ロボットと判定されました あなたがロボットでなければ、ブラウザの JavaScript を有効にしてください。」とのエラーページに移動します。

ただし、ログインユーザーは、エラーページに移動しません。

これでコメントフォームに reCAPTCHA を設置するカスタマイズは終了です。

ログイン画面にも設置

コードを参考にした Using Googles NoCaptcha ReCaptcha In WordPress に記載のとおり、WordPress のログインページにも自前で reCAPTCHA を設置できます。

一部正常に動作しない箇所があったので、変更しまとめます。

設置するには、下記のコードをテーマの functions.php に追加します。

add_action( 'login_enqueue_scripts', function() {
  wp_enqueue_script( 'recaptcha', 'https://www.google.com/recaptcha/api.js' );
});

add_action( 'login_form', function() {
  echo '<div class="g-recaptcha" data-sitekey="ここにSite keyを入力"></div>';
});

add_action( 'wp_authenticate', function( $parameter = true ) {
  if ( isset( $_POST['g-recaptcha-response'] ) ) {
    $response = json_decode( wp_remote_retrieve_body( wp_remote_get( 'https://www.google.com/recaptcha/api/siteverify?secret=ここにSecret keyを入力&response=' . $_POST['g-recaptcha-response'] ) ), true );
    if ( $response['success'] ) {
      return $parameter;
    } else {
      wp_die( '<h1>認証に失敗しました</h1><p>「私はロボットではありません」にチェックを入れてください。</p>', '', array( 'back_link' => true ) );
    }
  }
  
  return false;
});

6 行目のここにSite keyを入力に「Site key」を、11 行目のここにSecret keyを入力に「Secret key」を入力します。

送信に失敗しました

ボットと判定された可能性があります。

大変お手数をおかけしますが、以下の内容をご確認の上、再度のコメントの送信をお願い申し上げます。