Using Akismet to Prevent Comment Spam in CodeIgniter

Updated 2012-06-03 to reflect changes in the library since the article was originally written.

Have you ever visited a site or blog where the comments are overrun by spambots mercilessly peddling their wares? If you’re going to allow public comments on something you’re working on, you will need to take steps to stop this happening to you.

Comment spam puts off genuine contributions and makes your site look unkempt and unloved. Plus, if spambots keep managing to get links published, that’s all the incentive the spammers need to redouble their efforts. Therefore it is your moral duty to fight back against comment spam! Motivated yet?

The most effective way of stopping comment spam is to hold all comments in moderation and only approve genuine contributions. However this involves a lot of effort on your part - reading and checking the comments could be very time-consuming. Obviously we want to avoid this, so manual approval is out.

This is where Akismet comes to the rescue. A free service from the folks at Automattic, Akismet will take your comment data and run it through a battery of tests to decide how spammy it is. The great thing about Akismet is that it can “learn” from real-word examples of spam and genuine comments (“ham”), so you shouldn’t get left behind in the arms race of spammers coming up with new techniques and everyone else trying to keep up.

Getting Started With Akismet

So, let’s take advantage of this excellent service! Luckily for us, the power of Akismet is ridiculously easy to harness.

The first step is to sign up for a WordPress API key. Once that’s done, we’ll be needing the Akismet CodeIgniter Library. Download the library and copy it to your application’s “libraries” directory.

For the purposes of this article, I’ll assume your blog runs off a controller called “blog”, and that the comments are submitted through a method called “comment” - if you’re not, it should be fairly obvious where to put the code anyway.

To start off, we’ll create a private method in the “blog” controller called “_init_akismet”. This simple method will just set up a connection to the Akismet server, ready for us to pass through comments for checking:

function _init_akismet()
{
	$this->load->library('akismet');

	// quick bit of setup
	$akismet_config = array(
		'blog_url' => 'your_url_here', // e.g. http://www.example.com/ (note trailing '/')
		'api_key' => 'your_api_key_here'
	);

	$this->akismet->initialize($akismet_config);
}

Doing The Actual Work

OK, so we’re about a third of the way there now (yes, really!). The next step is to modify the “comment” method so it passes comments off to Akismet for checking as they come in. We still want to save the comment, regardless of what Akismet says, because in the case of false positives we want to be able to publish them later:

// … do your prep, e.g. processing POST vars etc …

$this->_init_akismet();

// set up your comment data to be passed to Akismet here, e.g:
$akismet_comment_data = array( 
	'author'	=> $comment_data['name'],
	'email'		=> $comment_data['email_address'],
	'website'	=> $comment_data['website'],
	'body'		=> $comment_data['comment']
);

if ($this->akismet->is_spam($akismet_comment_data)) // perform the check
{
	$comment_data['is_spam'] = 1; // flag the comment as spam
}

// … save the comment and carry on as normal …

The above code should be fairly self-explanatory. You may need to add a field to your database table to store the fact that the comment has been marked as spam, but that should be trivial. Once that’s done, you just need to set your comment model to only return rows that aren’t marked as spam.

So, you’re now checking all incoming comments and marking off suspected spam in the database to stop it being displayed publicly. Good work, we’re nearly there now!

The Finishing Touches

Now we’re marking comments as spam, we need to deal with ham that gets marked as spam, and spam comments that somehow sneak through the net. Both cases are thankfully rare, but need dealing with all the same.

First we’ll deal with false positives - ham being marked as spam. The way I do this is to have an admin page that lists all comments that have been marked as spam. Each comment has two buttons next to it. One marks the comment as genuine and publishes it, the other deletes the comment altogether.

To report a comment as ham, we need to update our database record so that the comment is published, and we also need to report the ham to Akismet. This is not only good manners, but helps to improve the service as Akismet learns from its mistakes.

My ham-reporting function looks like this:

function mark_comment_ham()
{
	$id = $this->uri->segment(4); // e.g. /admin/blog/mark_comment_ham/[comment_id]
	$comment = $this->comment->get($id);

	// local ham marking 
	$update_data = array('is_spam' => 0);
	$this->comment->update($id, $update_data); // Using Jamie Rumbelow's MY_Model

	// report ham to akismet
	$this->_init_akismet();
	
	$akismet_comment_data = array(
		'author'	=> $comment->name,
		'email'		=> $comment->email_address,
		'website'	=> $comment->website,
		'body'		=> $comment->comment
	);

	$this->akismet->submit_ham($akismet_comment_data);
	
	redirect('/admin/blog/comments');

}

Likewise, to report spam, we need to mark the comment in our database as such, and report it back to Akismet. The way I handle this is to have a “report spam” button next to each comment when I am logged in as the admin user. This way I can quickly and easily zap any spam that does happen to get through the defences.

The spam-reporting method is basically exactly the same as the ham-reporting method - just change any instance of “ham” to “spam” and set “is_spam” to 1 instead of 0 in the database.

I leave the finer details of actually integrating the above functionality into your site up to you, as there are a lot of ways you could potentially do it, but it should be straightforward enough. Feel free to comment with any questions though!

Wrapping Up

We’ve now harnessed the power of Akismet and turned it to our favour in the war against comment spam. Not only that, we’re even being good soldiers and giving back to the system by reporting spam and ham. You can sleep soundly tonight!

Image: “Spam wall” by freezelight.

Tags: Akismet CodeIgniter PHP Security Spam Tutorial

Found this post useful or interesting? Please share it with your friends!

Feedback

Sorry, feedback is now closed on this post, but please feel free to get in touch if you would like to talk about it!

Or find posts by tag →

Friends & Influences

  1. Aching Brain
  2. Andy Budd
  3. Anthony Killeen
  4. Ben Everard
  5. Cameron Moll
  6. Dan Cederholm
  7. Dan Mall
  8. Dave Shea
  9. Elliot Jay Stocks
  10. Jamie Knight
  11. Jamie Rumbelow
  12. Jason Santa Maria
  13. Jeff Croft
  14. Jeffrey Zeldman
  15. Jeremy Keith
  16. Jon Hicks
  17. Khoi Vinh
  18. Mark Boulton
  19. Matt Croucher
  20. Nocturnal Monkey
  21. Sarah Parmenter
  22. Shaun Inman
  23. Simon Collison
  24. Tim Van Damme
  25. Toby Howarth