Published on
Anti-Spam checks can be really useful in reducing spam submissions to your forms - but they also get in the way of genuine users. Most users will tolerate them once, but if you ask them to re-submit a captcha in the same session they may get upset and go. Here is one way to avoid a repeat spam check.
Anti-Spam checks like Capthca, ReCaptcha, Security Question and Honeypot traps all work in a similar way. They set up some kind of 'code' when the form is loaded and check the 'code' setting when the form is submitted. This FAQ shows you a way to record when the check has been passed by a user so that you can ignore it if the form is re-submitted. This approach was first posted in reply to a user who wanted to avoid checks on the Confirmation Page but it can equally be used for other form re-submissions.
Note: if you have a multi-page or multi-step form then the Anti-Spam check should always be on the first page. That is the point at which to block unwanted submissions. (And spam-bots are unlikely to find their way through a multi-page form!).
To add a 'by-pass' to your Anti-Spam check add an Event Switcher [GH] action at the beginning of the On Submit event of your form - it should be the first action. Drag the Check action into the Event A box of the Event Switcher [GH] action and drag an Event Loop action into the pink On Fail event of the Check action.
Drag a Custom Code action into the On Submit event and put it after the Event Switcher [GH] action. Open the Custom Code action and add code like this:
<?php $form->data['captcha'] == 'passed'; ?>
This just makes a note in the $form->data array that this user has passed the Captcha check.
Now open the Event Switcher [GH] action and add this code to it:
<?php
if ( !isset($form->data['captcha']) || $form->data['captcha'] != 'passed' ) {
return 'event_a';
}
?>
This looks for the note in the $form->data array and skips the Captcha check if it has already been passed.
That is all you need to set up a basic version of this checker.
Hiding the Captcha input
An obvious next step is to hide the Captcha element in the form if it has already been passed. You can so this by putting the Captcha element inside a Container element of type Custom and adding code like this to the Start Code box:
<?php
if ( !isset($form->data['captcha']) || $form->data['captcha'] != 'passed' ) {
?>
and the End code box:
<?php
}
?>
This will hide the Capthca input element if the user has already passed the text on this form submission.
Hiding the Captcha for some users
If you have a form that is used by both registered and non-registered users then you can add a check in a Custom Code action in the On Load event to hide the Captcha from logged-in users:
<?php $user =& JFactory::getUser(); form->data['captcha'] = ''; if ( $user->id > 0 ) { $form->data['captcha'] = 'passed'; } ?>
Combined with the data to Hide the Captcha and by-pass the Captcha check this will hide the Captcha from logged in users.
Hiding the Captcha across several forms
If you have several publis forms on your site that may be completed in the same session and that all have Captchas you can require the Captcha only once by saving the passed value in the User Session. Change the code in the Custom Code action in the On Submit event to be like this:
<?php $form->data['captcha'] == 'passed'; $session =& JFactory::getSession(); $session->set('cf_captcha', 'passed'); ?>
and the code in the Custom Code action in the On Load event to be like this:
<?php $user =& JFactory::getUser(); form->data['captcha'] = ''; if ( $user->id > 0 ) { $form->data['captcha'] = 'passed'; } else { $session =& JFactory::getSession(); $captcha = $session->get('cf_captcha', ''); $form->data['captcha'] = $captcha; } ?>
Used with the code above to hide the Captha element and skip the Captcha check this will mean that the user only has to submit a Captcha on their first form submission in a session. They will have to resubmit again once their session has expired (by default this is after 15 minutes of inactivity).