I've been struggling with form spam recently, and found a solution that I like and thought would be worth posting about. I tried the "honeypot" technique described in this post, but I found that some of the bots attacking my forms were sophisticated enough to detect that the honeypot field is hidden, even if I used CSS or JavaScript to hide the field. So I tried a modified version of this technique which seems to be working well.
Step 1: create a "honeypot" field
- Create a new text field in your form (not a hidden field, we'll hide it with JS later).
- The field label should be a question with an answer that would be obvious to any human, such as "what color is the sky?" If you're not confident that it's obvious enough, you can put something in the field instructions that says "just say blue." This is necessary so that the form will work with JavaScript disabled.
- Set up your form processing steps to run conditionally only if the value of this field is "blue" or whatever the correct answer is. That way submissions with the wrong answer will not be added to the database.
- You might want to add a form processing step to send you a notification email if the form is filled out with the wrong answer so that you can monitor the spam submissions and make sure it's working well. You can always turn that off later.
Step 2: hide the field using JavaScript
- Don't use CSS to hide the field, because you want it to be visible if JavaScript is disabled so that the submitter can correctly answer the question.
- Use JavaScript to set the "display" property of the field (or preferably, one of its parent elements) to "none." See sample jQuery code below.
- If you're using the default Eloqua 10 form layout, the easiest way to do this is to hide the div with id "formElementX" where X is the number of the order that the field appears on the form, starting from 0.
Step 3: populate the hidden field using a JavaScript event
- The idea here is to use JavaScript to fill in the correct answer to the hidden field when the user takes an action that any human would have to take in order to fill out the form.
- I settled on using the "focus" event on all form elements because even if the user is using their browser to auto-fill the fields, they will still have to place focus on some form element in order to submit the form.
- If you use some other event, make sure that it's an event that any human user must trigger in order to submit the form, but not one that is automatically triggered when the page loads (such as window load) because some bots may be smart enough to execute it.
Example Code
This example uses jQuery, so you'll need to make sure you're loading the jQuery library on the page. If you're using an externally hosted landing page and you're already using a different version of jQuery, remove the first line in the code. You can replace the first line with whatever version of jQuery you prefer to use. This code also assumes you are using the default Eloqua 10 form code, but it could easily be adapted to whatever form layout you're using.
Insert this code into the <head> section of your document if you're using an external form, or into the JS field in the Tools bar if you're using an Eloqua 10 landing page.
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script><script type="text/javascript"> $(document).ready(function(){ $('#formElement7').hide(); $('input').focus(function(){ $('input[name="sky"]').val('blue'); }); });</script>
Be sure to replace "formElement7" with the id of your honeypot field's parent div (remember the fields are labeled starting from 0). Replace "sky" with the HTML name of your honeypot field, and "blue" with the correct answer to your obvious question.
So far this is working well for me - I'll post updates if I find that there are problems or if I want to recommend modifications to the technique.