Adding recaptcha v3 to wordpress page

in  Building the blog, Wordpress
4 minutes read

As owner of a blog that is around for a while with any traffic, you will find sooner or later annoying amount of spam comments taking your blog by storm. If the akismet is not your cup of tea and you do not want to pay for possible license (commercial use), then I can show you how to easily implement your own recaptcha v3 from google.

Update: After using the version 1 I have received rather a lot of spam comments, 70% of spam was not recognized. I have added another feature that hopefully will make it little bit harder for spam bots to get around my Recaptcha v3. If this does not help will add more checks. If you have any tips please leave comment.

You will need to register your site recaptcha v3 to get two keys one used on frontend (site key) and one at backend (secret key). For more information refer to developer’s guide. For our need we will use the very basic setup that is taken straight from the documentation as it was.

  • Load the JavaScript API.
 <script src="https://www.google.com/recaptcha/api.js"></script>
  • Add a callback function to handle the token.
 <script>   function onSubmit(token) {     document.getElementById("form").submit();   } </script>
  • Add attributes to your html button.
  <button  class="g-recaptcha button" 
        data-sitekey="SITE_KET" 
        data-callback="onSubmit" 
        data-action="submit">

Now that we know what to do we need to change our template files and to do that we can use sftp or navigate to Appearances > Theme editor

Form

First we will change the front end for which we do require recaptcha. Most likely site owners use it on comment or contact us section, basically any publicly accessible form that we do not want to get overtaken by spam. Do the following changes to the function comment_form in the file comments.php located in your active theme. How to add custom layout and styles to your comments please see the post Style WordPress comments in bootstrap

<?php
	comment_form(
		array(
			'logged_in_as'       => null,
			'title_reply'        => esc_html__( 'Leave a comment', 'twentytwentyone' ),
			'title_reply_before' => '<h2 id="reply-title" class="comment-reply-title">',
			'title_reply_after'  => '</h2>',
			'id_submit' => 'submitcomment',
			'class_submit'          => 'g-recaptcha',
			'name_submit'          => 'submitbutton',
			'submit_button'        => '<button name="%1$s" id="%2$s" class="%3$s" data-sitekey="<site_key>" 
			data-callback="onSubmit" data-action="submit">%4$s</button>'
		)
	);
	?>

</div><!-- #comments -->
<script src="https://www.google.com/recaptcha/api.js"></script>
<script>
   function onSubmit(token) {
     document.getElementById("commentform").submit();

   }
</script>

In order to recaptcha submit I had to rename attributes id, name to something else than submit. Also attribute type=”submit” when using input instead the submit button had be removed because the recaptcha will never trigger or trigger incorrectly.

Now with the front end sorted out the last thing we need to take a look at the back end part of comment verification.

We will use WordPress functionality of action hooks and add custom functionality to insert_wp_comment

To add hooks we need to change file functions.php inside your theme.

//custom functionality
add_action('wp_insert_comment','remove_comment_from_default_table', $comment);
function remove_comment_from_default_table( $id ){
	function validateComment() 
	{
		try {

			$url = 'https://www.google.com/recaptcha/api/siteverify';
			$data = [
						'secret'   => '<application_secret>',
						'response' => $_POST['g-recaptcha-response'],
						'remoteip' => $_SERVER['REMOTE_ADDR']
					];
					
			$options = [
				'http' => [
					'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
					'method'  => 'POST',
					'content' => http_build_query($data) 
				]
			];
		
			$context  = stream_context_create($options);
			$result = file_get_contents($url, false, $context);
			$result = json_decode($result);
			return [$result->success, $result->score];
		}catch (Exception $e) {
			return null;
		}
	}
	//get the results from recapcha api validation
    list($isValid, $score) = validateComment();
  	//add score meta to the comment for further analysis
	add_metadata( 'comment', $id, 'spam-score', $score );
  	//trehold by which the comment is considered as spam
  	//I have cerated general option where I can set the number as needed
	$spamTreshold = get_option('mtn_comment_post_spam_score') ? floatval(get_option('mtn_comment_post_spam_score')):0.5;
	if ($score < $spamTreshold || !$isValid)
	    wp_set_comment_status($id, 'spam');// mark it as spam
    	//wp_delete_comment($id, $force_delete = true); // delete right away
}

API Request

API request are made to URL: https://www.google.com/recaptcha/api/siteverify METHOD: POST

POST ParameterDescription
secretRequired. The shared key between your site and reCAPTCHA.
responseRequired. The user response token provided by the reCAPTCHA client-side integration on your site.
remoteipOptional. The user’s IP address.
Parameters for google recaptcha validation API

API response

Response is retrieved as json object and can look something like:

{  
  "success": true|false,  
  "challenge_ts": timestamp,  // timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)  
  "hostname": string,         // the hostname of the site where the reCAPTCHA was solved 
  "error-codes": [...],        // optional
  "score": number             // the score for this request (0.0 - 1.0)
}

If all is correct you should be able to see floating recaptcha thumbnail on the bottom of your page. Next you can watch recaptcha do the work for you by looking at statistics in the admin console.

Recaptcha admin view

Leave a comment

Your email address will not be published.