Monthly Archives: April 2015

Create a Text-Based / Question-Based “Captcha”

Google’s recaptcha is really good but not always the most optimal tool for stopping spambots. It takes a bit too much space, requires entering app IDs, and sometimes is hard for the visitors to solve.

Question based captcha’s are often easier solution. A simple question that requires textual answer is usually enough to keep most bots away, and is easy to code, requires no graphic libraries or API keys.

Two of our WordPress plugins – WatuPRO and Arigato PRO already implement such captcha features with great success. Here’s how we did it:

The steps

There are two main steps: to generate the captcha, and to verify it. In the case of our plugins we let our users to create their own questions in the admin panel. Here for simplicity we’ll assume the questions are hardcoded in a PHP array.

Generating the captcha

So, let’s assume we have the questions in array called $captcha_questions in such format:

 

$captcha_questions = array("What is the color of the snow? = white",
                          "Is fire hot or cold? = hot"
                          "In which continent is France? = Europe");

 

This code uses one array element for question and answer separated by = sign. You can of course use array of arrays or key => value pairs. But the above example is closer to to the format we let our plugin users input for questions in their admin panel.

So, now we need one random question of these and need to display it on the front-end:

 

shuffle($captcha_questions);
$question = $captcha_questions[0];
list($q, $a) = explode("=", $question);
$q = stripslashes($q);

 

Now let’s echo the question on the screen and display a field to enter the answer. You need also one hidden field. Depending on how you keep your questions in the database you may want to pass question ID. If you use hardcoded array of questions you can pass the question key. Or if you use something else, just pass the question itself – it’s a good idea to use base64_encode to ensure easier matching on the back end.
Do not, of course, include the answer anywhere on the page:

echo trim($q)." <input name="text_captcha_answer" type="text" />\n<input name="text_captcha_question" type="hidden" value="\"".base64_encode(trim($q))."\"" />";

Verify the captcha

I’ll just to ahead with the whole function and then explain:

// this function will actually do the verification
function verify($question, $answer) {
     $answer = stripslashes($answer); // don't forget this or you may get unexpected results
		
     // the $captcha_questions variable needs to be recognized here as well. Use global, constant,  DB entry etc

     $question = base64_decode($question); // decode the hidden field with the question
	
     // go through all questions and compare	
     foreach($captcha_questions as $captcha_question) {
	list($q, $a) = explode("=", $captcha_question);
	$q = trim($q);		
	$q = stripslashes($q);
	$a = stripslashes($a);
				
	if(strcmp($q, $question) == 0 and strcasecmp(trim($a), trim($answer)) == 0) return true;
}		

That’s it. The above function goes through all the questions in the array (note that the code does not show where $captcha_questions variable comes from – don’t use the function as is, you need to declare the variable), explodes question and answer and then compares each of the combinations to the values given to the function. In case of match, returns true.

Pay special attention to using stripslashes() and trim() or you’ll have a lot of headaches to figure out why captcha answers are not correct.

Note also that we use strcasecmp to compare the answer to the question because we don’t want the check to be case sensitive.

And here is how to use it roughly:

// the user has submitted the form. Use different variable name if you wish
if(!empty($_POST['submit'])) {
   // verify the captcha
   if(!verify($_POST['text_captcha_question'], $_POST['text_captcha_answer'])) die("The answer to the verification question was not correct.");
   
   // now process the form
}

The above code isn’t super user-friendly because it will simply die in case of error. I recommend you to implement the check with ajax and stay on the same page until correct answer to the question is given.

Squeeze Page in Arigato PRO Autoresponder

From version 2.4.2 the WordPress autoresponder plugin Arigato PRO supports a very easy method for creating squeeze / landing page. Everyone who have tried to do this with a WordPress blog knows how much pain usually this is and that it often requires installing more plugins or a special squeeze theme.

Well, no more, at least with Arigato PRO. Just go to the “Squeeze page” in the menu and you’ll see a form like this:

squeeze-settings

This form lets you select whether your blog homepage will be the “Squeeze” or a selected published post or page. Then all you need to do is to place the HTML code of a complete landing page in the box, and add the Arigato subscribe form code for the mailing list you want to use.

If you prefer to use the shortcode syntax you need also to add the script code that is displayed under the big box (not shown here).

The HTML code you enter should contain a complete HTML page with header and body tags. The WordPress header will not be added.

If you need samples, you can find many free landing page templates online. We are going to offer some Arigato-specific ones in the near future.

If you want to see a live demo of such page have a look at our demo blog.

How To Use Contact Form 7 in WatuPRO “Final Screen”?

Before answering this, I recommend you to request contact information using this built-in method of WatuPRO. You can also have emails sent with the quiz plugin so in most cases you don’t really need to integrate a contact form in the quiz output.

If you still need to do it, it’s easy. Just switch off “Ajax” for the selected quiz from WatuPRO Settings page, section “AJax in quizzes“. Once you do this, you can include the Contact form 7 shortcode in the “Final page / quiz output” are and it will work.

Contact form 7 will not work in Ajax-loaded page so the above setting is absolutely required.