Google reCAPTCHA
Protect XPAC Forms with Google reCAPTCHA v3 scores, server-side verification, and fail-closed configuration checks.
Google reCAPTCHA adds score-based bot protection to Forms. It supports reCAPTCHA v3 only. A protected form asks Google for a token in the browser, and the server verifies that token before accepting the submission.
Forms is required
This add-on does not register its settings, editor controls, or verification check unless XPAC Forms is active.
Set up reCAPTCHA
Create a reCAPTCHA v3 site in the Google reCAPTCHA admin console. Add every production and staging hostname that will serve a protected form.
Open XPAC → Integrations → reCAPTCHA, enter the site and secret keys, and save.
Set a score threshold. Start with the default of 0.5, then tune it using
real traffic.
Edit a form, open Anti-spam protection, enable Google reCAPTCHA, and update the form.
The supported site-wide settings are:
| Setting | Default | Behaviour |
|---|---|---|
| Site Key | empty | Public v3 key sent to the browser. |
| Secret Key | empty | Private key used only for server verification. |
| Score Threshold | 0.5 | Scores less than or equal to this value are refused. Values are constrained to 0.1–1.0. |
| Disable Google reCAPTCHA Badge | off | Hides Google's floating badge and prints the required privacy/terms attribution below each protected form. |
The secret uses a masked password control. Existing option names and stored values are unchanged; masking the field does not encrypt the WordPress option at rest.
Enabled protection fails closed when keys are missing
The per-form toggle remains available when credentials are absent. If an enabled form has a missing site or secret key, the editor shows a non-dismissible warning with a settings link, and the server refuses submissions instead of silently disabling protection.
Do not use v2 checkbox, v2 invisible, or Enterprise keys. They are not compatible with this integration.
What happens on submit
The browser requests a token for the fixed action submit. Browser-side execution
has a 30-second guard: loading, execution, or token errors return the form to an
actionable error state so the visitor can retry instead of leaving the button busy
indefinitely.
The server then sends the token and visitor IP to Google's siteverify endpoint.
It accepts the submission only when all of these are true:
- the provider reports success;
- the returned action is exactly
submit; - the returned hostname matches the site's WordPress home or site hostname;
- the response contains a numeric score; and
- the score is strictly greater than the configured threshold.
The server request defaults to a five-second timeout and is clamped to 1–10 seconds. It is not retried because reCAPTCHA tokens are single-use. A timeout, malformed response, provider error, action/hostname mismatch, missing token, or low score is a refusal—not a bypass.
Only pages that render an enabled form with configured credentials enqueue Google's front-end script. This avoids a reCAPTCHA request on unrelated pages.
Refused submissions and monitoring
A refused submission does not run notification emails or integration deliveries. Forms marks it with the detector and reason. With the default Keep submissions marked as spam setting enabled, it is quarantined in the Spam view so an administrator can review and restore a false positive. If that Forms setting is disabled, the refusal is not retained.
Accepted entries store the numeric reCAPTCHA score for review. The raw token is not
stored. Operator-side failures such as missing or invalid credentials, transport
errors, malformed verdicts, and action/hostname mismatches are also written to the
WordPress/PHP error log with an XPAC google-recaptcha prefix.
A CAPTCHA reduces abuse; it does not guarantee it
Monitor the Spam view and real scores after launch. Raising the threshold blocks more automation but can also quarantine real visitors. Keep another control such as Honeypot enabled where appropriate, and test from every hostname used in production.
Privacy and availability
A protected submission contacts Google from the visitor's browser and from your server. Account for that third-party processing in your privacy and consent setup. If Google's script or verification service is blocked or unavailable, the form fails closed and asks the visitor to retry.
If you hide the badge, the add-on automatically prints Google's Privacy Policy and Terms of Service notice below each protected form. See Google's reCAPTCHA v3 guide, server verification guide, and badge guidance.
Developer reference
Site-wide values are stored in the xpac option:
| Option key | Meaning |
|---|---|
recaptcha_v3_site_key | Site key |
recaptcha_v3_secret_key | Secret key |
recaptcha_v3_score_threshold | Threshold, normalized to 0.1–1.0 |
recaptcha_v3_disable_badge | Badge visibility |
Per-form state is stored under googleRecaptcha in the form's form_settings meta:
{
"googleRecaptcha": {
"enable": true
}
}xpac_google_recaptcha_request_timeout filters the server timeout before the
1–10-second clamp. xpac_forms_enable_verification can skip a provider for a
special submission flow; the provider slug is google-recaptcha. Returning false
deliberately bypasses this protection and should be narrowly scoped. Forms Auto
Submit uses that path because a signed server-driven submission has no browser from
which to obtain a CAPTCHA token.