Since lately the FormIt driven contact form in our website footer got bombed with hundreds of spam messages each day. So I decided to change the spam protection to a more robust one. Since using this method we did receive a grand total of zero messages created by spam bots! You can read how I achieved this in the following tutorial.

FormIt is a very popular Add-On - a dynamic form processing Snippet - for MODX Revolution which already has built in all the features we need for our tutorial.

The next thing which will come to our mind is, to protect the form with a so called Captcha - Completely Automated Public Turing test to tell Computers and Humans Apart. On Zurb Blog you can read why you should avoid Captchas:

Between the spam and the abuse, web forms just aren't secure, and it felt like the only way to combat it was with those nasty captchas. Captchas have always felt like a cop-out. As a business, you're passing your own business problem onto users. Moreover, the way in which the problem is passed onto users is half-assed and can cause loads of confusion.

But what can we do to avoid Captchas?

In my opinion the best solution has been using what's called a "honeypot". A honeypot is a form field which is hidden to humans but visible to typical spam bots. Since spam bots tends to fill in any available form field, we can use this behavior to protect our form.

Below you will find our full featured FormIt driven Contact form protected by a honeypot:

[[!FormIt?
    &hooks=`spam,email`  
    &emailTpl=`ContactFormMailTpl`
    &errTpl=`[[+error]]`
    &emailTo=`n a m e @ d o m a i n . c o m`
    &emailCC=`[[+email]]`
    &emailSubject=`Contacting via web-form: y o u r s i t e n a m e`
    &successMessage=`Thank you for your message! We will immediately contact you.`
    &store=`1`
    &emailHtml=`0`
    &validate=`name:required,
               email:email:required,
               message:stripTags:required,
               confirmemail:blank`
    &name.vTextRequired=` <span class="required error">Please enter your name.</span>`
    &email.vTextRequired=` <span class="required error">Please enter your email address.</span>`
    &email.vTextEmailInvalid=` <span class="required error">Please enter a valid email address.</span>`
    &message.vTextRequired=` <span class="required error">Please enter your message.</span>`
]]

<form id="contactform" action="[[~[[*id]]]]#contactform" method="post">
    <fieldset>
	    <legend>Contactform</legend>
        [[+fi.successMessage:notempty=`
	    <p class="successMsg">[[+fi.successMessage]]</p>
	    `]]
	    <p class="fieldbg">
	        <label for="name">Name
	            [[!+fi.error.name:notempty=`[[!+fi.error.name]]`]]
	        </label>
	        <input type="text" name="name" id="name" value="[[+fi.name]]" required>
        </p>
	    <p class="fieldbg">
	        <label for="email">Email
	            [[!+fi.error.email:notempty=`[[!+fi.error.email]]`]]
	        </label>
	        <input type="email" name="email" id="email" value="[[+fi.email]]" required>
	        <input type="email" name="confirmemail" value="[[+fi.confirmemail]]" class="confirmemail" autocomplete="off" placeholder="P l e a s e  l e a v e  e m p t y!">
        </p>
	    <p class="fieldbg">
	        <label for="message">Message
	            [[!+fi.error.message:notempty=`[[!+fi.error.message]]`]]
	        </label>
	        <textarea name="message" id="message" rows="6" required>[[+fi.message]]</textarea>
        </p>
	    <p>
	        <button type="submit" class="button green rounded submitbutton" role="button">Submit message</button>
        </p>
    </fieldset>
</form>

The magic lies in line 38 of the above source in combination with the confirmemail:blank value (line 14) of the &validate Snippet parameter! We provide a second email input form field, which will be hidden to humans but visible to spam bots. A spam bot will fill in this special field and the form validation fails 'cause we told the FormIt Snippet this field needs to be empty.
To make this field invisible, we need to assign a special CSS class for example called confirmemail.

Please note: Most spam bots have learnt to ignore input type="hidden" form fields. So simply using an input type="hidden" won't protect your form!

The following definition of the confirmemail CSS class is needed to make our special form element invisible. You need to add this to the style sheet of your website. To prevent rendering issues when using the confirmemail class (e.g. horizontal scroll bars), you should use style position: relative on the parent element of this field.

There are many other methods to visually hide a HTML element. Personally I prefer the method from the well know HTML5 Boilerplate framework.

/*
 * Hide visually, but have it available for spam-bots
 * Use fake class name: confirmemail to prevent detection of keyword "hidden"
 */
.confirmemail {
    border: 0;
    clip: rect(0 0 0 0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    width: 1px;
}

Now create a new chunk and name it ContactFormMailTpl. This will be the template used for the body of the mails you will receive when sent through the above form.

[[+name]] ([[+email]]) contacting via web-form:

[[+message]]

As a further protection, we additionally use the spam hook (line 2 of the FormIt Chunk above). This hook is a built in feature of the FormIt Snippet. Your can read more about this hook in the FormIt documentation.

That's it! Your web-form is now protected from most spam bots. Let's see how long it last until bots will learn how to avoid this "problem" ... :-) And if you have any questions please leave a comment.