How To Stop Wordpress Comments Spam

28 Nov 2012

Below is a simple solution to stupid, yet annoying spam problem. I never actually realised how bad it can get until I started this blog. Not that I get a lot of visitors and genuine commentators, but for some reason I used to get approximately 10 spammy comments per day - that's across all blog posts.

TL;DR

The idea for this spam block is very simple: apparently spam bots rely on the presence of certain fields in your HTML comment form. If you change names of those fields on the server, that will confuse hell out of those poor spambots that try to help some shady SEO dudes to make their living. It doesn't have to be a big change - just adding an extra "1" or "a" in front of every value for "name" attribute on ‹input › tags.

We do need to make sure that genuine posters are still able to use the comments form though. So we need to make those changes transparent to them. One thing that distinguishes genuine users from spambots is the presence of, well, browser. So we can use a simple piece of Javascript to revert the changes made on server.

Drawbacks/Disclaimer

This method requires editing of your comments.php file. Since this file is a part of the Wordpress installation, it can be overwritten whenever you happen to upgrade your Wordpress or theme next time, thus removing your superior, tailor-made spam protection. So please consider this drawback and whether that's a showstopper for you at all.

Step by Step Guide

  1. Open comments.php file. Most likely you'll be using some sort of a theme, so this file is usually located under wp-content/themes/[theme-name]/comments.php
  2. Find line that contains call to comments_form() function. It looks something like this:
    comment_form(array(
        'fields' => array(
            'author' => sprintf('<input name="author" type="text" placeholder="%s" value="' . esc_attr( $commenter['comment_author'] ) . '" />', __(Name', 'origami')),
            'email' => sprintf('<input name="email" type="text" placeholder="%s" value="' . esc_attr( $commenter['comment_author_email'] ) . '" />', __('Email', 'origami')),
            'url' => sprintf('<input name="url" type="text" placeholder="%s" value="' . esc_attr( $commenter['comment_author_url'] ) . '" />', __('Website', 'origami')),
  3. For every combination of name="..." add an arbitrary character, say "z" in front of the value, so it looks like this:

    comment_form(array(
        'fields' => array(
            'author' => sprintf('<input name="zauthor" type="text" placeholder="%s" value="' . esc_attr( $commenter['comment_author'] ) . '" />', __(Name', 'origami')),
            'email' => sprintf('<input name="zemail" type="text" placeholder="%s" value="' . esc_attr( $commenter['comment_author_email'] ) . '" />', __('Email', 'origami')),
            'url' => sprintf('<input name="zurl" type="text" placeholder="%s" value="' . esc_attr( $commenter['comment_author_url'] ) . '" />', __('Website', 'origami')),
        ),
  4. Now you need to add a piece of Javascript that reverts your changes when page is loaded. After the PHP closing tag (it looks like "?>") add the following:

    (function($) {
        $(document).ready(function() {
            $('#commentform').children('[name^="z"]').each(
                function(i, e) {
                    $(e).attr('name', $(e).attr('name').substring(1))
                })
        })
    })(jQuery)

    Notice how we specifically select only elements with name that starts with the arbitrary character (in this case "z") in our $('#commentform').children('[name^="z"]') statement? So if you were to use some other character instead, make sure you modify the script accordingly

Results

Since adding this simple change rate of spam comments on my blog dropped to virtually zero. You can ramp up the protection by renaming the comments form's target wp-comments-post.php handler file and using similar Javascript to "fix" the form target on the client. This way your Wordpress installation will be better protected from those "drive-by" spambots. It won't help you to defeat a spammer who is dedicated enough to actually reverse-engineer your code. But boy that's a good problem to have - a possible indication that you are some sort of internet celebrity.

Hope you find this helpful. Let me know of any comments, concerns or questions.