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”.

      • Bill Erickson says

        WPForms also has its own honeypot built-in. The problem is that Gravity Forms and WPForms are used on so many websites that spam bots have been programmed to identify their honeypots and not fill them in.

        The approach outlined above lets you create a honeypot that spam bots aren’t already aware of. It’s unique to your site, so you don’t have to worry about them identifying the class or ID of the field and skipping it.

        This general approach could easily be applied to Gravity Forms using their gform_entry_is_spam filter.

  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