How to use honey pots in Zen Cart Forms.

Some ideas on coding spam traps in Zen Cart forms.

I get that not everyone is able to code or come up with something that works with your site layout. We can only help so far and then it becomes a job… If you can not figure something out, don’t be afraid to ask how much or hire someone.

This is for folks that want to learn or do it them self and not a drop and run set of code.

I’ll concentrate on the ‘Contact Us’ form, but this can and should be used on any from. The words ‘CHANGE_THIS’ means just that! Change the word to something that makes sense to the form its in. The idea of a good honey pot is that theres no noticeable difference between it and the rest of the form.

The three type of honey pots I’ll use are:

1) hidden input, radio, and textarea form field traps.
2) visible questions.
3) confirmation of information.

1) hidden input, radio, and textarea form field traps.

Step 1. Setup the ZC template pages.
The contact us page has four parts,
1) the template page YOUR_TEMPLATE/template/tpl_contact_us_default.php,
2) the header page modules/pages/contact_us/header_php.php,
3) the language page languages/english/YOUR_TEMPLATE/contact_us.php,
4) the css page YOUR_TEMPLATE/css/contact_us.css.

Two things that affects all ZC, the template override pages and the non-override pages. The three pages here, template, language, and css should be in your template override folder and only affect your template. The header page does not have a override and will affect all templates!

I use a common css file for all my css for the template I’m using and not the contact_us one.

Step 2. Using the hidden field.
No matter what you do, you can’t prevent users from having full access to every bit of data on your website. Additionally, there’s no way to disable the ability of any user to simply “view source” or “view page info” for your site. You CAN make it super-confusing to read it… Simple input fields are easy to understand, complex checkbox or radio fields can confuse anyone. Input or textarea fields are normally empty, but what if that wasn’t true! Check boxes can be checked or not, 50% chance of getting that right.. Two radio’s connected, click one or the other, but both can be unselected or false at startup!! Text areas, what system wouldn’t pass up a chance to advertise in that! Option fields, pick any one and your wrong! In short, any form field can be used to trap a bot hidden or not!

This is a normal email field for my site:

<div class="js-float-label-wrapper">
<label for="email-address"><?php echo ENTRY_EMAIL; ?></label>
<?php echo zen_draw_input_field('email', ($email_address), ' id="email" spellcheck="false" title="Please enter a E-Mail address (" pattern="^(([-\w\d]+)(\.[-\w\d]+)*@([-\w\d]+)(\.[-\w\d]+)*(\.([a-zA-Z]{2,5}|[\d]{1,3})){1,2})$" required="required" aria-required="true"', 'email'); ?>

This would be my spam catch:

<div class="js-float-label-wrapper email-pot">
<label for="email-us"></label>
<?php echo zen_draw_input_field('CHANGE_THIS', '', ' id="email-us" title="do not fill in!" placeholder="do not fill in!" autocomplete="off"', ‘email’); ?>

Do you see the difference? I use a script to float labels, if I used a label for this field, the default would not be empty, but the label! So testing for the label would be correct and not empty. Basically, the reverse of normal honey pots. Normal behavior is that this field would be empty. To test, one would comment out the css hide and fill in the line during form submit.

Based on the hidden idea, the radio field would be like this:

<div class="js-float-label-wrapper email-pot">
<p>To prevent Spam we ask if you are a human or a computer. If for some reassign you are reading this line.<b>Do not Answer!</b></p>
<?php echo zen_draw_radio_field('user', 'H1', false, 'id="user-1"') . '<span class="input-group-addon"><i class="fa fa-male fa-2x"></i></span>' . zen_draw_radio_field('user', 'C2', false, 'id="user-2"') . '<span class="input-group-addon"><i class="fa fa-laptop fa-2x"></i></span>'; ?>

Both are set to false, if ether is set during submit, then its a bot.

Step 3. Hide the field.
Using contact_us.css or stylesheet.css add the email-pot class.

.email-pot {position:absolute; visibility:hidden; display:none;}

Step 4. Test for bot answers.
In this test we want the bot to think it succeeded in submitting and leave. So we need to use the success page and not an error message which is why adding comments for humans not to fill out if for some reason the css fails is just as impotent.

In modules/pages/contact_us/header_php.php when the form is submitted, it starts an action called SEND so we need to look for the beginning of the submit action then under it add our post lines.

if (isset($_GET['action']) && ($_GET['action'] == 'send')) {

$antiSpam = isset($_POST['CHANGE_THIS']) ? zen_db_prepare_input($_POST['CHANGE_THIS']) : '';
  $userspam = zen_db_prepare_input($_POST['user']);

You can omit which ever one your not using or do both.
The test can be after all others or before:

if (($antiSpam != '') || ($userspam != '')) {
zen_redirect(zen_href_link(FILENAME_CONTACT_US, 'action=success', 'SSL')); 

If ether are not empty, stop sending and get to the success page to fake out the bot.

2) visible questions.

CAPTCHA is basically a visible question a human would answer. The issues with any is how the user can interact with the question! CAPTCHA code can be internal (Your code on site) or external (third party code off site). With ZC plugins, you have both options. Personally, I would keep my customers on site and not allow for off site tracking or down servers. If captcha is done so the bots can not read the answer, then nether can humans and even worse if sight in-pared! Which is one reason for 508 complacency.

If not CAPTCHA then what? Well, build a better question and answer system! We have one hidden that use radio buttons, unhidden and test for the correct answer!!

The bot has a 50% chance of guessing right with radios and checkboxes!

Input field, 2+2= type the number 4! How about some other question like yellow+blue= type the word green!

What about sliders? The variables are grate, the answer can be any number, lets see the bots guess right here…

The harder one to code is the slider so I’ll cover it.

Step 1. Add the code for the slider at the bottom of the form.

<div class="slidecontainer">
<p>Are you Human? Slide to Human..</p>
  <?php echo zen_draw_input_field('iqTest', '', ' min="0" max="50" value="0" class="slider" id="id1"', 'range'); ?>
<br /><br />
<span>Value:</span> <span id="f" style="font-weight:bold;color:red"></span>

Step 2. Add css to format the slider.

/******** slider ********/
.slidecontainer {
    width: 100%; /* Width of the outside container */

/* The slider itself */
.slider {
    -webkit-appearance: none;
    width: 100%;
    height: 1px;
    border-radius: 5px;  
    background: #d3d3d3;  
    outline: none;
    opacity: 0.7;
    -webkit-transition: .2s;
    transition: opacity .2s;

.slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 25px;
    height: 25px;
    border-radius: 50%; 
    background: #cc0000;
    cursor: pointer;   

.slider::-moz-range-thumb {
    width: 25px;
    height: 25px;
    border-radius: 50%;
    background: #4CAF50;
    cursor: pointer;

Step 3. Add script to modules/pages/contact_us/jscript_main.php
The code is used to display feed-back to the user so they know when to stop or the question was answered. Some day the browsers will support this without script, a html5 issue!

Enter within the script tags are create another set.

$(document).ready(function () {
var slideCol = document.getElementById("id1");
var y = document.getElementById("f");
y.innerHTML = slideCol.value; // Display the default slider value

// Update the current slider value (each time you drag the slider handle)
 slideCol.oninput = function() {
    y.innerHTML = this.value;
    if (this.value >= 50) {
      y.innerHTML = 'Human';

Step 4. Set the trap. modules/pages/contact_us/header_php.php
Set the field get and check under the other spam tests.

  $humanTest = zen_db_prepare_input($_POST['iqTest']);
     if ($humanTest != '50') {
     $messageStack->add('contact', 'You don\'t seem to be Human yet!', 'error');
     $error = true; 

We don’t want to reload the page and delete all the user inputs here, they need to fix there answer and resubmit the form.

You can use any number, script can change any number to a word, the possibilities are limitless.

3) confirmation of information.

Simply, the user fills out the form. The submit button verifies the form and takes the user back to the page with all fields full. The page asks the user to verify the information before sending. Basically two clicks to send the page. Most bots will see the first send as finished and leave. The second click would be a human and final send.

Users normally don’t have a problem with verifying what they entered before sending.. Its like previewing before submitting to a forum!

In closing,  I see no reason to eye test customers with an off site CAPTCHA that may not work or be available to use.

One Reply to “How to use honey pots in Zen Cart Forms.”

Leave a Reply