In-page enforcement
Shield scores every visit and recommends allow, monitor, challenge or block. With in-page enforcement switched on, the SDK acts on that recommendation the moment a risky visitor submits a sign-up, login, checkout, lead or password-reset form — on any install type: JavaScript snippet, npm, Google Tag Manager, WordPress, WooCommerce or Shopify.
Nothing changes in your snippet. The setting travels inside the responses the SDK already receives, so there is no extra request, and the decision itself is made by Shield's servers, never by rules shipped to the browser. Requires SDK 1.2.0 or later; the v1.js CDN URL always serves it.
What it is, and what it is not
Friction against bots and casual abuse — not a security boundary.
This is friction. It stops bots and casual abuse that run your page in a real browser, which is most of it. It does not stop anyone who posts to your endpoints directly, disables JavaScript, or edits the page. For the sign-ups, logins and payments that matter, confirm the session on your server with the verify endpoint, one call from your backend. It returns the same recommendation, and since SDK 1.2.0 also whether the visitor passed a Turnstile challenge.
Switch it on
Protected forms in the Shield dashboard.
Under In the page (SDK) the enforcement pages are Protected forms (which forms Shield protects, and how), Custom rules (your own decisions) and the Enforcement log. Protection is per form: on Protected forms, press Protect a form and answer three questions.
- Which form? Pick one of the forms Shield has seen submitted on your site in the last 30 days (page, form id / name / action, how Shield classified it, how often it fired), or add a form by its page path if Shield has not seen it yet. Leaving the id, name and action blank protects every form on that page.
- What kind of form is it? Sign-up, login, checkout and payment, email and contact, password reset, or other form. Shield's guess is preselected. Your answer is also the form's correction: from then on Shield classifies that form the way you said, on the page (SDK 1.6.0) and on ingest for sites pinned to an older SDK.
- How should Shield respond? An enforcement type: Monitor only, Slow down, Verify (Turnstile), Block, or a custom type of your own.
An enforcement type says what happens in the page for each of Shield's verdicts:
| Shield says | Options |
|---|---|
block (risky visitor) | Stop the submit and show your message · Redirect to a URL · Let it through |
challenge (suspicious visitor) | Turnstile check · Slow down · Stop · Let it through |
monitor (slightly unusual visitor) | Let it through · Slow down |
allow is never touched. The built-in types cover most sites; a custom type sets its own mix, the slow-down delay, a redirect URL and the texts visitors see. Different forms can use different types on SDK 1.7.0 (v1.js always has it); sites pinned to an older SDK apply the type most of their protected forms use to every protected form.
The page then lists your protected forms with their activity, the forms Shield has seen but does not protect yet (protect or ignore each with a click), and your enforcement types. A protected form can be paused, edited or removed; the switch at the top pauses everything at once. Sites that used to protect whole form kinds keep working as before until you choose, on that page, the forms to keep.
The four actions
findip-shield-notice, which you can style. The page's own submit handlers do not run. The texts for all three visible actions are yours to set: the stop message, the challenge message above the Turnstile widget, and the slow-down countdown text, where {seconds} is replaced by the remaining seconds (SDK 1.5.0).block, the visitor is sent to the URL you configure — typically a page that explains the situation and offers a way to contact you. The SDK never redirects from the target page itself, so it cannot loop.Every action is recorded on the event. The Events page shows a badge such as Blocked, Slowed, Challenged or Challenge passed next to the event name, so you can see how often enforcement fires and on which forms.
How forms are matched
SDK 1.3.0+
Paths are matched exactly: lowercase, without query string or fragment. Shield identifies forms by their id, name or action path, as metadata only; field values are never collected. A protected form matches when the page path and every key you gave match. Forms Shield cannot recognise are reported as other forms; protect them like any other form and pick Other form as the kind. Forms you never want classified or protected go on the ignore list (the Ignore button under suggestions). A protected form's name, if you give one, shows next to its kind in Events, the enforcement log and alerts.
The enforcement log
The Enforcement log page lists every submit the SDK stopped, slowed, challenged or redirected: when, who (the visitor's email and user ID when identity reveal is on, otherwise the visitor ID), which form on which page, what happened, Shield's recommendation and reasons, and the network. Each entry offers one-click Block user, Block visitor and Block IP for 24 hours, 7 days or permanently.
Custom rules
Decide for a user, visitor, session, network, country, ASN or submit velocity — regardless of Shield's score.
| Match | You enter | Notes |
|---|---|---|
| User | an email, a user ID, or a SHA-256 hash | Stored as a hash only. Uses the same hashing as identify without a salt; salted installs enter the hash. |
| Visitor | the visitor ID | From the Sessions page or the log. |
| Session | the session ID | |
| IP or network | an address or CIDR | IPv4 and IPv6. |
| Country | an ISO-2 code | |
| ASN | a number | |
| Submit velocity | form kind, max, minutes, per visitor or IP | Matches when a submit would be the N-th of that kind in the window. |
Rules are independent of the in-page switch: with Enforce in the page off, a matching rule still changes the verdict shown in the dashboard, pushed to the dataLayer and returned by the verify endpoint, but nothing is stopped, slowed or challenged in the visitor's browser. The Custom rules page says so prominently while the switch is off.
A rule can also override the site's in-page behaviour when it decides: its own action (stop, slow down, challenge, redirect, or nothing in the page), slow-down delay, stop, challenge and slow-down texts, and redirect URL. Blank fields keep the site setting. Requires SDK 1.4.0 (1.5.0 for the challenge and slow-down texts).
Each rule carries an action — block, challenge, monitor or allow. A matching rule replaces Shield's recommendation for that event and adds rule:<name> to the risk reasons, so the SDK's in-page actions and the verify endpoint both honour it. If several rules match, an allow rule wins, otherwise the strongest action does. Rules can expire, and the page shows how many submits each one enforced (stopped, slowed, challenged or redirected); events that merely matched, such as page views, are not counted.
Turnstile setup
Free, and loaded only when a challenge is needed.
- In your Cloudflare account open Turnstile and create a widget for your domain. The free plan is enough.
- Copy the site key and secret key into Settings › Cloudflare Turnstile in Shield. The site key is shown to visitors; the secret never leaves Shield.
- Give the forms the Verify (Turnstile) enforcement type, or a custom type whose response to
challengeis the Turnstile check.
Shield loads Turnstile only when a challenge is actually needed, so pages that never trigger one do not load it at all. If Cloudflare's verification service cannot be reached, the challenge fails open and the submit goes through; the outcome is recorded as such.
Fail-open rules
The SDK never blocks by accident.
It leaves a submit alone when:
- enforcement is off, or the page has not yet received Shield's response for this visit (for example a submit within the first few hundred milliseconds),
- the recommendation is
allow, or the form is not in scope, - the visitor already passed a challenge in this session,
- a challenge cannot be rendered or verified.
Forms submitted from JavaScript with form.submit() do not fire a submit event and are therefore not intercepted; requestSubmit() and normal button submits are.
Combining it with your server
Turn friction into a decision no client can bypass.
Put the session ID in a hidden field and call the verify endpoint from your backend before creating the account or taking the payment:
{
"verified": true,
"risk_status": "available",
"risk_score": 72,
"recommendation": "challenge",
"challenge_passed": true,
"challenge_passed_at": "2026-09-08T09:12:44.000Z"
}A backend that accepts challenge only when challenge_passed is true, and rejects block, turns the in-page friction into a decision no client can bypass.