WPForms Spam Filtering Using the Comment Blacklist Field

WordPress Comment Blacklist Field

Update – 1 March 2024

I have now addressed the issues with this code that occurred in September 2023, when WPForms removed the honeypot filter. Now, the code steps through the fields and checks them against the comment blacklist values, and if it matches a term, the entry is not saved and no emails are sent. The submitter sees the same message as everyone else, as I haven’t implemented any code yet to modify the confirmation message on the way past, and I possibly won’t, as I don’t want to give the spammers a heads up that I’ve filtered them out.

WPForms have a added a “keyword filter” option under Settings > Spam Protection and Security, but I have to update this for EVERY form on my site, which drives me nuts. This solution allows me to have a central “banned terms” list that all of my forms use to drop spam entries.

Update – 27 Sep 2023

It appears that WPForms have removed the ‘wpforms_process_honeypot’ filter from the plugin, so the below code no longer works. You can get it working again relatively easily by using the ‘wpforms_entry_save’ filter instead and setting ‘$save_entry’ to false, and disabling the notification emails with the ‘wpforms_disable_all_emails’ filter, if the entry contains spammy terms. I’ll update the code examples soon.

I’ve recently begun getting spam messages through my contact forms that are submitted by humans, not bots, so they don’t get stopped by the standard honeypot setting in WPForms, my form plugin of choice.

If you’ve ever used Contact Form 7, you might know that it uses the values that you enter into your Comment Blacklist field to stop spam messages being successfully submitted by people.

I wanted to create something similar for WPForms, that was easy to maintain, and add new terms to, and used the existing comment blacklist. I also didn’t want the overhead of another plugin just to do this, so I created a solution in PHP.

I came across an excellent solution from Bill Erickson, that blocks specific email addresses from submitting spam, but I needed a few extra features.

Firstly, I wanted to look at more than just the email address. I wanted to be able to scan the contents of the name, email and message fields for spammy terms.

Secondly, I wanted to be able to search for partial matches, not exact matches, because of course spam is always evolving, and the terms might change slightly.

And thirdly, I wanted an easy way to add terms to my list, instead of having to edit my function each time a new term popped up. I considered using Advanced Custom Fields to do this, but then realised it made a lot more sense to use the existing Comment Blacklist field, in the same way that Contact Form 7 does.

My WPForms Spam Blacklist Solution using a Custom Function

I blended the code from Bill’s WPForms Email Blacklist function and the code from the WP Core function wp_blacklist_check to create the function below.

When you add this code to your site, the form submission is not added to your WPForm entries, no emails are sent to you, and the user just sees a blank response, so they have no indication that their submission has not been successful.

If you have logging enabled, the honeypot value should show up in your WPForms Log.

Step 1. Add this code to your theme’s functions.php file

This code has been written to suit my contact form, which has a first name field, and email field and a message (textarea) field.

If your forms have other fields that you want to check for spam terms, you’ll need to assign these values to variables and add these variables to the pattern matching section.

To find out which fields your form is using, you can add a

print_r($fields);

line, and do a test form submission to see the full array of terms that your specific form includes. Or you can inspect the source code of your form and look for the “type” value for each field.

1 March 2024 – Code updated, now fully functional again.
Link to gist with code

/**  Filter out spam messages on WPForms forms **/
// Stop form entry being saved, and don't send emails, if it contains spam terms
// @link https://measurewhatworks.com/article/stop-wpforms-spam-using-comment-blacklist-field/
function nhs_stop_spam_entry_saving( $save_entry, $fields, $entry, $form_data ){
    
    $contains_spam = nhs_check_blacklisted_terms( $fields, $entry, $form_data );
    
    /* If entry is spammy, don't save it or send any email notifications */
    if( $contains_spam ){
        $save_entry = false;
        add_filter( 'wpforms_disable_all_emails', function(){ return true; } );
    }
    
    return $save_entry;
}
add_filter('wpforms_entry_save', 'nhs_stop_spam_entry_saving', 9, 4);

/** Check form entry against spam terms in discussion blacklist field **/
function nhs_check_blacklisted_terms( $fields, $entry, $form_data ){

	$contains_spam = false;	
	
	// Get comment blacklist values
	$mod_keys = trim( get_option( 'blacklist_keys' ) );
	if ( '' == $mod_keys ) {
	}
	else{
		$words = explode( "\n", $mod_keys );
		
		// Assign field content to variables
		foreach( $fields as $id => $field ) {
			if( 'email' == $field['type'] ){
				$email = $field['value'];
			}
			if( 'name [first]' == $field['type'] ){
				$first_name = $field['value'];
			}
			if( 'text' == $field['type'] ){
				$text = $field['value'];
			}			
			if( 'textarea' == $field['type'] ){
				$message = $field['value'];
				$message_without_html = wp_strip_all_tags( $message );
			}
		}

		// Step through spam terms in turn
		foreach ( (array) $words as $word ) {
			$word = trim( $word );

			// Skip empty lines
			if ( empty( $word ) ) {
			continue; }

			// Escape terms so that '#' chars in the spam words don't break things
			$word = preg_quote( $word, '#' );

			// Match form fields to spam terms
			$pattern = "#$word#i";
			if ( preg_match( $pattern, $name )
				|| preg_match( $pattern, $email )
				|| preg_match( $pattern, $text )
				|| preg_match( $pattern, $message )
				|| preg_match( $pattern, $message_without_html )
				) {
				$honeypot = '[Blacklist] ' . $name . ', ' . $email . ', ' . $message;
				$contains_spam = true;
			}
		}
	}

	return $contains_spam;
}

Step 2. Add spammy terms to your comment blacklist

Go to Settings > Discussion and scroll to your Comment Blacklist.

Add any terms that match the kinds of spam you’ve been getting in here. Keep in mind two things:

  1. These terms will be unique to your site and the spam you’re getting
  2. Make sure that your terms don’t filter out legitimate messages, based on your site’s audience and content

WordPress Comment Blacklist Field

I’m really pleased with this solution, because finally I can stop getting all that rubbish in my inbox and my database, and it’s easy for me to update in the future.

Good luck and happy spam blocking!

Please share this content

About the author 

I’ve had a love affair with systems, technology and data for as long as I can remember. I’ve been building websites for over 20 years, running online businesses for more than 15, and teaching myself how to use gazillions of software programs since the very first moment I got my hands on a computer. I’m a geek and proud of it!

  • Thank you so much for sharing this information. I’ve been getting tons of emails written in Russian. Do you know how to block those?

    • Hi Peggy,

      I’ve been getting some of those myself. One thing I’ve done is add “.ru” to my honeypot terms to eliminate Russian email addresses, although mostly this won’t make much difference because that’s not the address that’s used.

      The other thing I’ve done is use Google Translate to translate the email message, and then identify which words are the spammiest in Russian and add these to my list as well, in Russian!

      Hopefully this helps you reduce those annoying Russian messages a little!

  • This is an excellent function, many thanks for developing it.

    May I suggest two slight modifications as follows:

    1) There is no need to have an empty ‘if’ clause and have the code in the else clause, this is generally considered to be bad form. A better way would be to use if ( ” !== $mod_keys ), move the code to the if clause and dispense with the else clause entirely.

    2) Since you are not using this function as a spam word counter, once you have determined that the text is spam, that is after the first match, you can break out of the loop. So under the line that stars with “$honeypot = ‘[Blacklist] ‘ add a break;

    Thanks.

    • Hi Mark,

      You’re most welcome and thanks for the great feedback.

      I wrote the code with the empty ‘if’ clause simply because it made more sense to me that way, and I like self-evident code that’s easy to understand when I come back to it in five years’ time.

      But you’re right that it’s less efficient to do it that way, and your suggestion would work even better. I haven’t tested it, so I won’t update my code just yet, but it’s definitely a great idea, especially to improve speed.

      And again, adding the break in the loop would definitely make the code faster. If you don’t put it in, you’d see all of the terms that were considered spam, but one really is enough!

      I appreciate you taking the time to make these suggestions and heartily agree with both of them.

  • Hi Nikki,

    Thank you for sharing this tip with us.

    I was trying to implement it on functions.php on child theme, however it's not showing up after implement the code.

    Do you have any clue what could be blocking it from showing it up?

    Many thanks in advance.

    BR,
    Ed.

    • Hi Ed,

      There’s many reasons why it might not be working for you, but I’m not able to figure that out for you.

      The code won’t change the appearance of your form, it just silently drops any entries that contain words in your blacklist, so you’ll have to do lots of test submissions while changing things to get it working.

  • Hello Nikki !

    Thank you for this great tip. It's a live-saver.
    I thought I had to get rid of WP-Forms, but your snippet made my life easy again.

  • {"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}
    >