How to increase interaction on your blog with the right comment configuration (or, useful comment-related Drupal modules)

Up until a month ago, I hadn't had very good experiences managing commenting on Drupal blogs. Even with the hoops that commenters had to go through to write a post (i.e. long and frustratingly ambiguous captchas), tons of spam still got though, and the whole administration process was rather unwieldy. The e-mail notification modules available at the time were a little too in-depth, sending e-mails on new comments as well as new or updated nodes. Also, because of the spam, I'd set comments to only be published on approval, adding additional lag time to the discussion. It was a poor experience, and even I loathed posting comments on my own blog!

In setting up a blog for my Drupal training companyBlue How-To (currently a coming soon page), I decided to get things right. The installation was also going to be core to a multi-site that would include several other sites as well, so I'd be able to leverage the techniques across multiple sites. 

What I wanted in particular was:

I scanned through the Drupal modules matching the phrase comments and found a few gems, did the same in Google, and got started.

The modules you'll need

Spam
Comment Notify
Rules
Ajax Comments
Comments Bonus API (dependency for Ajax Comments)

Dealing with comment spam

The first step was figuring out how to deal with spam. I was using image captchas from the Captcha module. I had given Mollom a try on other sites, and while it will be my fall back if I end up needing captcah, I've gotten a lot of false positives in the mode where they show a captcha only if your content looks spammy (particularly on groups.drupal.org).

In my searching, I came a across a couple of easy-to-apply techniques using hook_form_alter(). The first is to add a text input that is hidden via CSS on forms so your users don't see it, but any bots will. Using a validation function, you check to see if the input is filled out, and if it is you throw an error and don't submit the form. I was familiar with this technique from way back and even used it in my first custom-made CMS, but it had slipped through the mental cracks.

Here's the code I use for this, which is slightly modified from the original. I was having issues on node forms, so I set it to not display there. I would also suggest changing the name of the input so as to not make this too predictable:

$form['#validate'][] = 'common_misc_honeytrap_check';    
if (strpos($form_id, 'node_form') === false) {
  $form['comment_body_two'] = array(
    '#type' => 'textfield',
    '#weight' => 0,
    '#required' => false,
    '#default_value' => '',
    '#attributes' => array('class' => 'honeypot'),
  );
}

We need to add a validation function to do the final check, and here it is:

function common_misc_honeytrap_check(&$form, &$form_state) {
  if (!empty($form_state['values']['comment_body_two'] ) ) {
    watchdog('notice', 'SPAM attempt at '
.$form['form_id']['#value'].' form', NULL, WATCHDOG_NOTICE);
    form_set_error('comment_body_2', 'Oops, you probably didn\'t mean to do that');
  }
}

So, if there's anything in this particular input, it will trigger the error.

The second thing we can do is set a timer on the form. Using this technique, we will add a hidden input with the current time to the form, and in a validation function make sure that it has taken the user more than a few seconds to fill out the form and throw an error if the submission un-humanly quick:

if ($form_id == 'comment_form') {
  $form['timegate'] = array(
    '#type' => 'value',
    '#title' => 'Timegate',
    '#weight' => 5,
    '#required' => false,
    '#default_value' => time(),
  );
}

I added the validation to the validation function above. Note I've set this to 10 seconds, but you can set it lower or higher.

if (time() < ($form_state['values']['timegate'] + 10 ) ) {
  form_set_error('comment_body_two', 'We KNOW you can\'t be THAT fast.');
}

Because I personally submit some forms faster than 10 seconds, I wrapped a check for an administrator role around both validations so that I wouldn't trigger the errors.

Setting up the spam module

These two techniques seem to work really well to stop automated spam. For spam that is produced by spam sweatshop laborers, I installed the Spam module. I enabled all of the included modules, but after a problem with one post triggering the Bayesian filter by beginning with the word "Thanks", I turned that one off. In the Custom filter, I added a regular expression so that I can add spammy words to as I discover them. Notice the <code>\b</code> around a word that could legitimately be part of some other word:

(bad_word|another_bad_word|\bword_that_could_be_in_some_other_word_but_is_still_bad\b)

So far, I've just had a couple of spam comments that could have been caught with the custom filter. It's a huge improvement, and there's no captcha to get in the way for real users.

Integrating simple notifications 

In a previous iteration of this blog, I used the watcher module, which had some nice features. I did some heavy CSS styling on it to match up the look, but I always kind of felt like there might be a better way.

I started by installing the Notifications module and attempting to chisel down it's many features to particular one I was looking for, which was customizable comment notifications. Ultimately I got the feeling that there had to be something more suited to this particular need. 

I finally landed on the Comment Notify module, which is what I'm using now to provide the nice "Notify me when comments are posted" feature:

The default e-mail that goes out for notifications is pretty heavy, so I trimmed the text a bit. You can find this setting at /admin/settings/comment_notify:

Hi !name,

!commname has commented on: "!node_title"

You can view the comment here: !comment_url

Below is the text of the comment:
!commtext

You can stop receiving emails when someone replies to this post,
by going to !link1

You can set up auto-following feature for all future posts
by creating your own user with a few clicks here !uri/user/register

Thanks!
Chris

So far, I've had a lot more repeat participation on my blog.

A special e-mail notice to administrators with some additional information 

Comment Notify is good, but it would require an administrator to manually sign up for each post. In addition, spam that got added but not published wouldn't send out any notification. As an administrator, I also wanted more information about the user that posted the comment, so I used the Rules module to set up an e-mail that got sent out whenever a comment was created.

In the first step, I set up my rule to be triggered when a new comment was saved:

Next, I set up a condition to check that the user doesn't have the administrator role, to make sure I don't get alerts for my own comments. Then, I added an action to send an e-mail to an arbitrary address:

Below is the text of the e-mail I'm sending out to myself:

Node title: <?php echo $node->title;?>


URL to comment: <?php echo url( 'node/'. $node->nid, array('fragment' => 'comment-'. 
   $comment->cid, 'absolute' => true));?>


User info: <?php echo $comment->name . '  '. $comment->mail . '  '. $comment->homepage;?>


<?php echo $comment->comment; ?>

Improving the usability of comments 

The main tool I found for really making the commenting process a more pleasant experience was the AJAX Comments module. With it, you get a ton of really nice ajax-y features:

  • When a user posts a comment, it loads it into the body via AJAX
  • You can administer comments via AJAX (to change the author, mark it as spam, etc)
  • Delete a comment via AJAX, with a key combination that will allow you to bypass the javascript approval dialog if you need to delete a bunch of comments.

It's really nice, and makes commenting and administering comments very fast. Working with comments is actually a pleasure now instead of a chore due chiefly to this module.

There's a couple of caveats, though:

  • AJAX Comments doesn't integrate well with Captcha or Mollum. The initial Captcha will show, but after that, no dice.
  • The comment Preview feature doesn't work
  • If the comment triggers the spam module, the user will get a not-so-helpful error dialog box instead of a useful inline error.
Comment: Notify me when new comments are posted All comments Replies to my comment CTA II: ..crnrnms MY -Rule settings Label: New comment Choose an appropriate label for this rule. Event: After saving new comment /aluate this rule luate LAC .ijn. '-Rule elements ON event After saving new comment IF NOT User has rolefs) Add condition DO Send mail to an arbitrary mail address Add an action NOT has rol to address add. to Add


Comments

Cool post. The anti-spam ideas are especially useful. Those could also be used in combination with a captcha module for added protection. I'm also using ajax comments with captcha on some sites and have noticed the issues you mention there. Maybe it's time to replace it :)

I'm not sure why people keep doing this but it's "Mollom", not "Mollum" :) Also, Comment Notify comes with Drupal 7 core!

Ah, thanks Wim, the spelling fix should be imminent! Also, good to hear about the core addition!

How did you get this cool looking reply to posts look? I mean, I like the dark blue box & the inclusion of your pic. Really makes it stand out & would be cool to hear how it was accomplished.

I'll have to write a post on this, but the technique is that I do a comment pre-processing function to check if the user who created the comment has the 'comment admin' role, and I add a class to the comment box if they do. On my site, I'm the only admin, but I'm also using this technique for other sites where there's more than one admin. I'll try to remember to comment here when I post that.

Cheers!

Nice write up! I will take a look to ajax comments.
One doubt I was having while reading your post, wouldn't be some of these advices incompatible with accesibility rules? I mean, some browsers doesn't "use css or js" so maybe this is a problem to disabled people, what do you think?

With the technique for adding an extra honeypot field to forms you just need to put something in the field description like:
"This field is used to catch spamers, please leave it blank."
or the like.

AJAX comments will degrade if the browser has no-JS.

I think that covers all the accessibility issues.

Thanks.

Although captchas can be a pain for visitors if they're not designed well, they do serve a purpose. They're a good layer of defense against spam bots in comments (used in conjunction with Mollom or other techniques already mentioned here). They also work well in the new account registration process to stop bots from creating fraudulent accounts (in forums or free webmail services, for example) and they are good to use on web forms as well.

If you're going to use a captcha, it helps to pick one that isn't completely irritating for your visitors. There are alternatives to those ugly, hard to read captchas displaying distorted text. For example, this clickable picture captcha works well at stopping bots but is pretty easy for most people: http://drupal.org/project/confident_captcha

Hey, that confident captcha is a pretty neat idea, I'll have to give it a run one of these days.

Captcha definitely has its purpose, but if it's to stop automated posting, then the honeypot idea seems like a more usable replacement. I'm still getting some spamming from what I think are real spam sweatshop folks manually filling in the form, but the amount has gone way, way down.

Thanks for the comment, cheers!

confident_captcha seems cool. how well does it play with ajax_comments? Anyone know or tried it out yet?

Hey! Thanks for the links. I'm very happy you found good use for my ideas on SPAM.

Best regards.

I'm happy, too! Thanks for the great ideas!

Cheers!

So in conclusion, the list of modules you're using for this site (for example), Chris, are:
-Spam
-Comment Notify
-Rules
-Ajax Comments
-Comments Bonus API (which Ajax Comments now says it depends on)

Is that right or did i miss something? Great post! Really like the setup you have here & have been wanting to implement something similar (easier/better UX for readers of my blog).

That sounds about right. I went ahead and added this list in the post.

Awesome that the post was useful, let me know if you end up adding any improvements.

Great am new web server and web designing, Thanks a lot for sharing and helped ..i have already made a twitter of this

I would have never thought of using a time based captcha.
AJAX comments is awesome too!

I'm the only admin, but I'm also using this technique for other sites where there's more than one admin. I'm still getting some spamming from what I think are real spam sweatshop folks manually filling in the form

This feels like a lot of working parts. Do you worry it might be hard to maintain over time?

Good point, there are quite a few pieces. Once the 'honeytrap' stuff gets into a module, though, it will simply be a matter of installing and configuring a few modules and the maintenance should be simply updating the modules. It might be nice to put together a feature module with all this stuff in it, too, so the entire collection can be maintained like a module.

Thanks for pointing me to ajax_comments. And I want to remind you to write that post about using comment pre_processing. Sounds interesting and your tutorials are pretty awesome. Looking forward to it.

may i know how to add image with blog comment on Drupal modules? is it possible?

Alas, Ajax Comments are not yet ported to D7. This module adds so much usability to Drupal comments, that's true.

Hello,

The main problem with ANY captcha from CAPTCHA module is that pages with a captcha are not CACHED, as incredible as it seems, it has been confirmed by the captcha coder.

And Mollom module doesn't work wwell if you really check...

So what to do ?

Thanks for help !