Eliminate spam with a custom honeypot

A custom honeypot is a simple and effective way to eliminate spam. If a hidden field in your form is filled in, you can be fairly confident the submission is spam.

WPForms does include a built-in honeypot, but now that the plugin is used on millions of sites, most spam bots have been updated to identify and skip the WPForms field with a name of hp.

Your custom honeypot is different. It’s unique to your form and looks like any other field to a bot. I have pretty much eliminated spam on my contact form with a custom honeypot.


First, come up with a unique CSS class name you’ll use to identify your honeypot field. Make it something unique to your site (ie: not honeypot). If your class is my-fancy-field, add this to your theme’s stylesheet to hide that field.

.wpforms-container .my-fancy-field {
	display: none;
}

Create a field in your form and add your custom class to it.

Add the following code to your theme’s functions.php file or a Core Functionality plugin. If this field is ever filled in, the submission will be marked as spam and have a honeypot message of “[Custom honeypot]”.

Make sure you update the $honeypot_class variable at the top to use your custom class name.

/**
* WPForms Custom Honeypot
*
* @author Bill Erickson
* @link http://www.billerickson.net/eliminate-spam-with-a-custom-honeypot/
*
* @param string $honeypot, empty if not spam, honeypot text is used in WPForms Log
* @param array $fields
* @param array $entry
* @param array $form_data
*/
function be_wpforms_custom_honeypot( $honeypot, $fields, $entry, $form_data ) {
	$honeypot_class = 'my-fancy-field';

	$honey_field = false;
	foreach( $form_data['fields'] as $form_field ) {
		if( false !== strpos( $form_field['css'], $honeypot_class ) ) {
			$honey_field = absint( $form_field['id'] );
		}
	}

	if( !empty( $entry['fields'][$honey_field] ) ) {
		$honeypot = 'Custom honeypot';
	}

	return $honeypot;

}
add_filter( 'wpforms_process_honeypot', 'be_wpforms_custom_honeypot', 10, 4 );

Logging

You can also enable logging so you can see if the honeypot is working. Every time a spam entry is submitted, this will create a post in the wpforms_log post type with the honeypot message and the full submission.

I recommend only logging this data temporarily because you don’t want to fill up your database with a bunch of unimportant spam messages.

First, update the wpforms_logging option to log spam:

/**
 * Enable logging of spam
 *
 */
add_action( 'init', function() {
	$debug = get_option( 'wpforms_logging' );
	if( empty( $debug ) || ! in_array( 'spam', $debug ) )
		update_option( 'wpforms_logging', [ 'spam' ] );
});

Use this code to make the WPForms Log post type visible. You can then access it in WPForms > Logs.

/**
 * Make log visible
 *
 */
add_filter( 'wpforms_log_cpt', function( $args ) {
	$args['show_ui'] = true;
	unset( $args['capability_type'] );
	return $args;
});

Bill Erickson

Bill Erickson is a freelance WordPress developer and a contributing developer to the Genesis framework. For the past 14 years he has worked with attorneys, publishers, corporations, and non-profits, building custom websites tailored to their needs and goals.

Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments

  1. Hans Schuijff says

    Hi Bill,

    Thanks for this useful tip. I use Gravity Forms at the moment, but could probably add something like this there too.

    There seems a small error in the second snippet, since it now checks for an empty array that also not contains “spam”, so perhaps you meant !empty( $debug ) in the first part?

    Cheers,
    Hans

    • Bill Erickson says

      You’re right, there is an error in the last snippet. That should be an OR statement, not an AND statement.

      The code should say “if the wpforms_logging option is empty, or if doesn’t contain spam, update the option to log only spam”.

  2. Chris Wathen says

    Hey Bill,

    I just found a typo in your second snippet. When you call out the variable in line 17, you have $honeypost_class instead of $honeypot_class.

    Take care,
    Chris

  3. David says

    Hi Bill,

    I used a custom form in my word press site, but wanted to know how could I use this code in a custom form, not a WP plug in.

    • Bill Erickson says

      You could use the general concept – hide a field with CSS, and if it is filled in, reject that message as spam. But the actual code above will only work with WPForms.

Leave A Reply