David Walsh Blog

How I Stopped WordPress Comment Spam

I love almost every part of being a tech blogger:  learning, preaching, bantering, researching.  The one part about blogging that I absolutely loathe:  dealing with SPAM comments.  For the past two years, my blog has registered 8,000+ SPAM comments per day.  PER DAY.  Bloating my database with that trash slows down my blog in every which way, and recently I decided I was done with it.  I was also tired of moderating comments and seeing loads of SPAM comment notifications in my email inbox.  Done.  And like a boss…I stopped it.  Dead.  Here’s how I did it!

How I Was Getting Spammed

There’s no way to tell, but I suspect bots detected that I had a WordPress blog, knew the form keys for submitting comments, and did so accordingly.  I was getting comments for Viagra, Cialis, Michael Kors, Nike shoes, and more.  Stuff only bots would spend the time on.  It all had to be a detected, automated attack — nothing targeted.

What Wasn’t Working

Everything.  I had used different WordPress plugins and continued to get SPAM.  Akismet is the premier WordPress SPAM protector and it wasn’t able to prevent the problems — and included 100KB+ of JavaScript which slowed down my site.  I never used a CAPTCHA utility because any barrier to commenting on my site should be a problem I deal with, not all of you.  In the end, I was let down by numerous utilities.  I was disappointed but refused to give in.

What Worked

The first step was removing all of the anti-spam plugins, as there was a good chance they were messing with each other and letting the SPAM in.  My solution was allowing the generic anti-spam solution:  adding an INPUT to the form which should remain empty during the submission process.  Empty in value but present via key:  the premise is that bots that read form inputs would populate the form field values with rubbish just to make sure submissions weren’t rejected based on empty values.

How I Implemented Spam Protection

You can’t simply add inputs on the server side — they are output to the page and the bot can read those and populate (or not populate) them.  Creating those fields on the client side eliminates the simple bot / curl readers.  You can add said form fields with JavaScript (via any framework) and that’s your best bet.  Before we do that, however, let’s implement the server-side SPAM block check.

The WordPress PHP

Before accepting a comment on the server side, we need to check for the dynamic key presence.  All we need is an isset check:


// Fuck off spammers
function preprocess_new_comment($commentdata) {
	if(!isset($_POST['is_legit'])) {
		die('You are bullshit');
	}
	return $commentdata;
}
if(function_exists('add_action')) {
	add_action('preprocess_comment', 'preprocess_new_comment');
}

If the check fails, we reject the comment.  Of course this means that users without JavaScript support will have their comments rejected, but the chance of being spammed is probably greater than that of users without JS support so I’m fine with that.  If the key isn’t set, we outright reject the comment all together.  This is a chance, of course, but statistics show it’s worth it.

The JavaScript

The easy answer here is using basic JavaScript to inject the form field, and since every JS framework has its own syntax, I’ll pass on providing code for all of them.  Adding said field upon page load seems a bit suspect to me, as an intelligent bot may be able to detect that.  In the case of my blog, I use MooTools and submit comments via AJAX, so I simply append the secret field within the JavaScript code upon submission:


var form = $('comment-form');

new Request({
    url: form.action,
    method: 'post',
    onRequest: function() {},
    onSuccess: function(content) {},
    onComplete: function() {}
}).send(form.toQueryString() + '&is_legit=1');

Adding that key upon submission has proven safe to this point.

WINNING

After two weeks I’ve received 0 SPAM comments.  Zero.  None.  Nil.  Absolute zip.  I went from over 8,000 per day to none.  Better than Akismet, better than any plugin.  Take WordPress SPAM prevention into your own hands — use client-side magic with a small PHP function to make your life easier!