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;
});
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 containspam
, update the option to log only spam”.Joshua Nelson says
Gravity forms ships with it’s own honeypot, as an option for each form under Form Settings, more info here: https://www.gravityforms.com/rip-captcha/
Cheers!
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.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
Bill Erickson says
Ah, thanks for catching that!
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.
G Pellikaan says
Didn’t work quite as aspected, until I changed my ‘fancy-field’ from text to name field, and also kept the label. Spambots just didn’t fill the hidden textfields, but a name field, O boy!
Echo says
Exactly what I’ve been looking to do myself. Perfect! Thank you!
Stef says
Bill can this be used as well to hook into a checkout form in WooCommerce?
Bill Erickson says
I think the general concept could work, but I’m not familiar with the hooks & filters in WooCommerce so can’t provide an example of the code you would use. You might try asking a developer that specializes in WooCommerce.
Ross says
Thanks for taking the time to share this Bill. I went through the steps you listed but somehow for me the Logs item is not listed on wp-admin under wp forms in comparison to your example.
Bill Erickson says
Make sure you go to WPForms > Tools and enable logs. I think they changed the UI a bit since I last wrote this. You might check with WPForms support if you’re still having issues.