Gravity Forms Spam Protection Without a Captcha
Gravity Forms spam protection without a captcha means the site checks that a real browser rendered and submitted the form, instead of asking the visitor to prove it. ReportedIP Hive does exactly that for Gravity Forms: a bot’s submission is refused as a validation error above the form, no entry is written, and a genuine sender never sees a puzzle, an image or an extra step.
The Gravity Forms adapter is part of the Business plan and switches on with one toggle on the Protection page under Form Protection. It arrived with Hive 2.1.63 and is tested against Gravity Forms 3.1.
Why a captcha is the wrong tool for a contact form
A captcha asks the wrong person to do the work. The sender, who wants to reach you, has to read distorted letters or click on traffic lights; the script that floods the form was never going to solve it and simply moves on to a site with a weaker one. Every failed attempt costs you a message, and you never learn how many gave up.
Bots fall into two groups, and a form has to handle both. The first fills in every field it finds, including the one it should skip. The second never loads the page at all: it posts straight at the endpoint with a payload copied from one real submission. Gravity Forms ships its own honeypot field for the first group. The second walks past a honeypot, because it never renders the markup that carries it.
How the execution proof judges a Gravity Forms submission
Hive plants one invisible anchor field in every Gravity Forms form on the page, excluded from the tab order and from screen readers. A small script then adds a second field whose name is different on every installation, so a payload recorded on one site fits no other. On submission the server reads both fields back and sorts the request into one of four verdicts:
| Verdict | What the submission carried | What happens |
|---|---|---|
proved | Anchor empty, proof field present | A browser rendered the form and ran its script. The entry is saved. |
tripped | The anchor field, filled in | Refused. A filled invisible field is automation with no innocent explanation, and the address moves up the block ladder. |
failed | Anchor empty, proof field missing, the site knows it renders the field | Refused. The page was fetched, the script never ran. |
absent | Neither field present | Lenient. Hive has not yet seen itself render the field on this site, so nothing is judged. |
Nothing request-specific reaches the HTML. The anchor is the same on every page load, the randomised name lives in the script, so a page cache can keep serving the form for as long as it likes without a single visitor being locked out.
Gravity Forms submits its forms itself
Most form plugins submit through the browser’s normal submit event, which is where Hive’s script fills the proof field. Gravity Forms does not: it collects and sends the form on its own and fires no submit event doing so. It does publish a JavaScript filter for exactly this moment, gform/submission/pre_submission, the same one its own invisible captcha uses. Hive hooks that filter, fills the proof field, and hands the form back.
On the server the anchor goes in through gform_form_tag, so it sits inside the form element without searching the markup for a closing tag, and the verdict is delivered on gform_validation, the hook Gravity Forms runs on every submission before it writes an entry.
Multi-page forms are judged once, on the last page
A form with several pages sends each page as a request of its own. Only the final page is a submission, so only that one is judged. Judging every step would spend a computed answer and a community lookup for nothing. Forms sent in the background, the AJAX mode most sites use, are covered the same way as a form sent with a page reload, and the refusal is shown above the form on both paths.
A form that arrives late is taken in again
A Gravity Forms form rendered a second time, after a failed validation or inside a popup, arrives after the script’s first pass. Hive listens for the plugin’s own render event and takes the form in again: it reads the challenge, restarts the clock and binds the submission filter. Before 2.1.63 such a form found no computed answer waiting and was refused as unproven; that is fixed.
Why a refused submission is a validation error and not a spam-folder entry
Gravity Forms offers a spam folder, and the adapter could have filed refused submissions there. It does not, on purpose. An entry in the spam folder is a message the sender was thanked for and the operator never reads. If the verdict was wrong, the person who wrote to you believes their message arrived and waits for an answer that never comes.
A refusal from Hive is a form-level validation error instead, the same mechanism Gravity Forms uses for its own “at least one field must be filled out”. The sender sees the message above the form, can read why, and can try again. No entry is written, no notification goes out, and no confirmation page is shown. This plugin never loses a message without at least telling the sender so.
What a bot sees and what a visitor sees
| Genuine visitor | Script posting at the endpoint | Bot filling every field | |
|---|---|---|---|
| Loads the page | Yes | No | Yes |
| Runs the script | Yes | No | Usually not |
| Proof field | Present | Missing | Missing or wrong |
| Anchor field | Empty | Empty or missing | Filled |
| Extra step for the human | None | ||
| Result | Entry saved | Refused above the form | Refused, address counted |
What the check cannot do is tell a person from a botnet driving a real browser. It tells a browser from a script. For the address behind the browser, Hive runs a second, independent check: the community threat check refuses a submission from an address the site would refuse a sign-in to, at the protection level the sign-in page enforces, and the sender is told why. That check needs Community Network mode; the execution proof works in Local Shield mode as well, with nothing leaving the site.
Submissions made through the Gravity Forms API are never judged
An import, a Zapier feed or a REST call through the Gravity Forms API carries no anchor and no proof field, and without a rule for that, every one of them would read as a client that failed the check. Hive asks the validation hook whether the submission came from a browser and stands aside for everything else. Since Gravity Forms 2.6.4 the hook says so itself; on an older plugin Hive asks the way the plugin’s own honeypot asks.
Switching it on in four steps
- Update to Hive 2.1.63 or later on a Business plan. On a lower plan the Gravity Forms switch stays visible and locked, with the plan it needs written next to it.
- Turn on the Gravity Forms switch on the Protection page under Form Protection. Switching it on clears the common page caches, and for 24 hours a submission that never carried the proof is still accepted, so a page cached without the field cannot lock anybody out. The
reportedip_hive_form_adapters_gracefilter buys more room on a site whose cache outlives a day. - Run the self-test under Tools → Diagnostics. The card lists what is switched on and then runs three passes with the browser you are sitting in front of: like a visitor, like the same visitor twice, and like a bot. No real form is submitted, no mail goes out and no entry is stored. An invisible protection is otherwise hard to tell apart from no protection at all.
- Optionally start in report-only mode, which logs every verdict and refuses nothing. A week of logs shows what would have been refused before anything is.
The computation check, included from Professional and therefore on Business, closes the one shortcut the plain proof field leaves open: reading the field name out of the page and posting it back. The browser works out a small sum in the background, each answer is accepted once, and the sender still notices nothing. It needs HTTPS; without it the plain proof field keeps deciding.
Which form plugins get the same protection
| Form | Plan | Tested against |
|---|---|---|
| Comment, sign-up and lost-password forms | Free | WordPress core, WooCommerce, Multisite |
| Your own forms, through the form API | Free | Three calls: field, check, passes |
| Contact Form 7 | Every plan | The version published on wordpress.org |
| Gravity Forms | Business | 3.1, including multi-page and background forms |
| Formidable Forms and Formidable Forms PRO | Business | 6.35 |
| Elementor Forms | Business | Elementor PRO 3.34, the form widget exists only there |
| Ultimate Member | Business | 2.13, sign-in, sign-up and password forms |
Each plugin has its own switch. The whole layer, the master switch, a second switch that leaves sign-up and password reset out, and report-only mode sit together on the Protection page. REPORTEDIP_HIVE_DISABLE_FORM_PROOF in wp-config.php switches the layer off for the case where a visitor cannot submit and you need the site working before you debug.
Frequently asked
Does Gravity Forms still need a captcha with Hive switched on?
Not against scripts and bots. The execution proof catches a submission that never rendered the form and a bot that fills the invisible field, and the community threat check refuses an address the network already knows. A captcha adds nothing to that except a step the sender has to take. What no field can do is tell a person from a botnet driving a real browser, and a captcha cannot do that either.
Does it work next to Akismet or the Gravity Forms honeypot?
Yes. Hive judges the submission on the validation hook, before an entry exists. A refused submission never reaches the entries list, the spam folder or any other anti-spam plugin. Everything that passes goes on to the checks you already run.
What happens to a visitor with JavaScript switched off?
On the form plugins a submission without the proof is refused with a message that says why, because on a contact form there is no moderation queue to fall back on. On the comment form the same case only costs a moderation step. A site with many such visitors can run the layer in report-only mode, or leave the Gravity Forms switch off and keep the free forms covered.
Does the check slow the form down or break page caching?
No. The anchor is identical on every page load and nothing request-specific reaches the HTML, so a cached page stays valid. The script fills one field at submission time and measures how long the form was on screen; the starting point comes from the browser, never from the markup, so a cached page cannot carry a stale one.
Is it GDPR compliant?
The proof collects nothing about the visitor beyond whether two hidden fields were present on submission and how many seconds the form was on screen. No fingerprinting, no third-party request, no image served from another domain. In Local Shield mode nothing leaves the site at all. The WordPress plugin documentation carries the full data-handling summary.
Related reading
- Form honeypot and execution proof, the four verdicts and how the comment form scores them
- Decoy paths, a different trap that reports a scanner on its first probe
- Audit event trail, the other Business capability that landed one release earlier
See the WordPress plugin documentation for the full settings reference and the plan comparison for what Business includes. Explore ReportedIP Hive →