A contact form that fills with spam usually has no defense at all, or one defense that a bot walks around. The fix is a few layers, each catching what the last one missed, and the order worth setting them up in runs from the ones a visitor never sees to the ones a visitor has to deal with. I haven’t set up each of these myself, so the steps below come from the Contact Form 7, Cloudflare, Akismet and Gravity Forms documentation linked where it is used. My own sites run on WordPress and Hostinger, which is why the examples lean toward WordPress.

How-to Setup Cloudflare Turnstile integration with Contact Form 7, RankYa on YouTube

Four layers, in the order a visitor would notice them

From invisible to a checkbox

A contact form gets junk from automated scripts that fill in every field they find, so each defense below is a different way of telling a script from a person. A honeypot is a hidden field that a person never sees. A spam filter such as Akismet reads what was submitted and judges it. A score-based check such as Google’s reCAPTCHA v3 grades the visit in the background. A challenge widget such as Cloudflare’s Turnstile makes the browser do a small piece of work and hand back proof.

The first three cost a real visitor nothing. The fourth costs a moment at most. None of them is perfect, and the sources are consistent about that: the Contact Form 7 page on Akismet says filtering is not 100 percent accurate and that false positives and false negatives will occur, and the Gravity Forms page on honeypots points to other anti-spam tools as well, which implies that the honeypot alone is not the whole answer. The reasonable plan is two or three layers with a way to see what they caught.

The honeypot

Hands sorting envelopes into two wooden trays on a desk

A field only a script would fill in

The Gravity Forms page, Fighting Spam with Honeypot, describes a honeypot as a form field hidden from visitors on the front end. Real people never see it or fill it in, so it works as a trap: a bot sees the field, fills it out, and the submission is flagged as spam. In Gravity Forms it is a toggle in the form’s options.

The same page says the option can create an entry marked as spam, so the flagged submissions can be reviewed in the form’s entries instead of vanishing. That matters because the page itself says a legitimate submission could be flagged, and a log is the only way to find out. A plugin that discards a trapped submission silently is making that decision for you.

Whether your form plugin has a honeypot is a settings question. The website builders for a small shop post covers the builders that bundle a form, and the form settings of whichever one you use are the first place to look before adding anything else.

Akismet on Contact Form 7

Filtering by content

Contact Form 7 has a documented Akismet integration. Akismet is bundled with WordPress, so the setup is to activate the Akismet Anti-Spam plugin and get an API key. The page says personal blogs can use it free, while corporate or commercial sites need a paid subscription, so a business site should read the current terms before relying on it. The page is also an affiliate post that promotes a paid Jetpack product, which is worth knowing when weighing its advice.

To make Akismet accurate, the page says to mark the form’s fields with options: akismet:author on the name field, akismet:author_email on the email field and akismet:author_url on a website field. It advises using as many options as possible. When a submission arrives, Contact Form 7 sends all the user’s inputs and environment variables to Akismet, not just the tagged fields, and if Akismet says spam, the email is suspended and the visitor sees an error with an orange border.

The page also gives a way to test it. Typing the magic word viagra-test-123 into the name field, or akismet-guaranteed-spam@example.com into the email field, should produce the orange-bordered error. A form that passes that test is wired up. A form that sends the email anyway is not.

To report mistakes back to Akismet, the page says you need the Flamingo plugin, which stores submissions, and you set a message’s status to Spam or Not Spam there. That is the same log that matters later in this article.

Turnstile on Contact Form 7

Laptop on a shop counter with a blank form page beside a coffee cup and a paper pad

A challenge widget, set up in two steps

Contact Form 7’s own page on Turnstile integration describes Turnstile as Cloudflare’s free CAPTCHA alternative and recommends it over Google reCAPTCHA unless you have a specific reason to use reCAPTCHA. The setup has two steps. First, create a Turnstile widget in Cloudflare following Cloudflare’s documentation, choose the Managed mode widget, and copy the site key and the secret key. Second, in the WordPress dashboard go to Contact, then Integration, select Setup integration in the Turnstile section and paste in both keys.

After that, nothing needs to be embedded by hand. The page says that once the keys are saved Contact Form 7 adds the widget to all your forms by default, at the top of each form. To move it, you add a [turnstile] form-tag to the form template, and the tag accepts options for action, appearance, language, size, tabindex and theme, with the page’s example being a compact size and the English language.

Cloudflare’s own page, Get started with Turnstile, explains what is going on. A JavaScript widget runs a challenge in the visitor’s browser and produces a token. Your server then sends that token to Cloudflare to confirm it is valid. The widget gives you a public site key for your page and a private secret key for the server, and the three steps are create the widget, embed it and validate the token.

The server check is the part that does the work

Why a widget on the page is not enough

Cloudflare’s documentation states that server-side validation is mandatory. A widget that shows up on the page but whose token is never checked on the server protects nothing, because a script can skip the page and post straight to the form’s address. The Cloudflare page adds that tokens expire after 300 seconds and can be used only once, and that without the Siteverify call the configuration is incomplete and the validation numbers in Turnstile’s analytics show zeros.

The Contact Form 7 page describes only the keys and the widget, and says nothing more about the server step, so the practical test is the one Cloudflare’s note implies. Submit the form yourself and confirm it goes through. Then look at Turnstile’s analytics in the Cloudflare dashboard and confirm validations are being counted. A dashboard full of zeros after a day of real submissions is the sign, by Cloudflare’s own description, that the second half is not running.

Not every form plugin is documented the same way, and the documentation of whichever plugin you use should say whether it makes the server call.

reCAPTCHA v3, and what it asks of you

The score-based option

Contact Form 7’s page on reCAPTCHA says version 5.1 and later uses the reCAPTCHA v3 API, which runs in the background so visitors don’t solve puzzles or tick a box. The form uses reCAPTCHA’s score to estimate whether a submission came from a person or a bot. Setup follows the same pattern: register the site in the reCAPTCHA Admin Console choosing v3, copy the two keys, and paste them under Contact, then Integration, in WordPress.

The page lists caveats. Keys for v2 don’t work with the v3 API, so an older site has to register again. The plugin ignores [recaptcha] form-tags in version 5.1 and later, since v3 needs no widget. And the page says Google plans to move all reCAPTCHA users to reCAPTCHA Enterprise, which it says will raise costs for many of them. That note is part of why the same plugin’s documentation recommends Turnstile first.

Contact Form 7’s post on why a message is marked spam gives an example of how the score works: a submission scored 0.30 against a threshold of 0.50 gets flagged. It does not give a way to change the threshold, so the score is something to watch in the log, not tune.

Keep a log, and read it once a week

Fine-mesh strainer held over a bowl on a kitchen counter catching solids as liquid passes through

False positives and the disallowed list

The Contact Form 7 post on spam marking lists the filters that can flag a message: Akismet, reCAPTCHA and a disallowed list that blocks submissions containing terms on a list. Flamingo is not a filter. It is the plugin whose Inbound Message section shows the spam log, and the log reports the reason a message is in the Spam tray. The post says this feature needs Contact Form 7 5.1.2 or higher and Flamingo 2.0 or higher.

A log solves the other half of the problem. Every layer in this article will sometimes block a real inquiry, and a business that never looks at the spam folder will never learn that a customer asking for a quote was trapped with the rest. A weekly read of the spam tray takes minutes. A one-page website for a small business is the kind of site where the contact form is the main way a customer reaches you, which makes that folder the one place a lost lead can sit.

One honest turn against the whole plan: a form with no protection and an inbox you read every day is sometimes less trouble than three layers and a dashboard to check. The layers pay off once the junk volume is high enough to bury real messages.

For informational purposes only. This article is based on plugin and service documentation that may change, so check the current instructions for the versions you run.

Sources