Title: Checkout Bouncer
Author: Mahruf Hussain
Published: <strong>Август 15, 2026-ж.</strong>
Last modified: Сентябрь 21, 2026-ж.

---

Плагиндерди издөө

![](https://ps.w.org/checkout-bouncer/assets/banner-772x250.png?rev=3648800)

![](https://ps.w.org/checkout-bouncer/assets/icon.svg?rev=3648800)

# Checkout Bouncer

 Автору [Mahruf Hussain](https://profiles.wordpress.org/mhussain3209/)

[Жүктөө](https://downloads.wordpress.org/plugin/checkout-bouncer.1.0.2.zip)

 * [Кенен маалымат](https://ky.wordpress.org/plugins/checkout-bouncer/#description)
 * [Сын-пикирлер](https://ky.wordpress.org/plugins/checkout-bouncer/#reviews)
 *  [Орнотуу](https://ky.wordpress.org/plugins/checkout-bouncer/#installation)
 * [Development](https://ky.wordpress.org/plugins/checkout-bouncer/#developers)

 [Колдоо](https://wordpress.org/support/plugin/checkout-bouncer/)

## Сүрөттөө

Your checkout is the one page on your store that anyone on the internet can submit
to, over and over, for free. That is why card-testing bots live there.

They arrive with a list of stolen card numbers, push a cheap product through your
checkout a few hundred times an hour, and use your gateway as a free validity checker.
You are left with the fallout: a wall of failed orders, a pile of authorization 
fees, a falling success rate, and eventually an unhappy email from your payment 
processor.

Most stores reach for a captcha plugin and assume the problem is solved. Then they
switch their checkout page to the WooCommerce Checkout **block**, and any captcha
plugin that only hooks the classic form silently stops working.

The block checkout does not submit a form. It posts JSON to the WooCommerce Store
API, and a plugin that only hooks `woocommerce_checkout_process` never sees that
request at all.

That route stays open even on stores whose visible checkout page still uses the 
classic shortcode. A bot does not need your checkout page. It only needs the route.

Checkout Bouncer is built around that gap. It follows one idea, end to end:

> Detect every way an order can enter this store, protect the ones that can carry
> a token, block the ones that cannot.

#### Detect

Checkout Bouncer ships a real checkout scanner, not a settings page with a checkbox.
It opens your store, works out how your checkout is actually built, and writes you
a plain report:

 * Reads the checkout page WooCommerce is configured to use, and tells you if it
   is missing, unpublished or trashed.
 * Works out which renderer that page uses: the WooCommerce Checkout block, the 
   classic `[woocommerce_checkout]` shortcode, or a page builder. Elementor, Divi,
   WPBakery, Beaver Builder, Bricks and Oxygen are detected by name, and Checkout
   Bouncer looks inside the builder’s own saved layout for the checkout element.
 * Hunts down rogue duplicate checkout pages: the theme-demo import, the staging
   copy, the “checkout-2” a page builder left behind. Every one of them is a second
   address where an order can be started, and most store owners have no idea they
   exist. A page only counts as a duplicate when it really renders a checkout, meaning
   the WooCommerce Checkout block, the `[woocommerce_checkout]` shortcode itself,
   or a page builder layout holding the checkout element. A knowledge-base page 
   that merely writes about the shortcode is not flagged. Duplicate detection needs
   a checkout page configured in WooCommerce to compare against, so it pauses while
   that setting is empty, and nothing is listed or blocked as a duplicate in that
   state.
 * Checks whether the Store API checkout route is registered, and whether anything
   is guarding it.
 * Resolves your pay-for-order and add-payment-method endpoints, which are the two
   surfaces bots use precisely because everyone forgets them.
 * Runs configuration health checks and flags the dangerous combinations: no keys
   saved, master switch off, a block checkout that is neither verified nor blocked,
   a score threshold of 0 that rejects nothing, a threshold so high it will turn
   away real customers, or no WooCommerce checkout page configured at all, which
   is the state that pauses duplicate detection.

Every finding comes with a one-click action, and every action explains what it will
break before you switch it on.

#### Protect

Where a token can be attached, Checkout Bouncer attaches one and scores it with **
reCAPTCHA v3**, the invisible kind. There is no checkbox, no traffic-light puzzle,
and nothing for a genuine customer to do.

 * **Classic checkout.** A hidden token field is added to the order review, refreshed
   while the customer types and minted again every time WooCommerce refreshes the
   review by AJAX. If the token is missing or older than 90 seconds when Place Order
   is pressed, the submit is held for a moment, a fresh token is minted and the 
   form goes on its way by itself, so a customer who left the tab open is not rejected
   for a stale token. The score is checked during checkout validation, which runs
   before WooCommerce creates the order, so a rejected bot normally leaves no order
   row behind at all. If a gateway or a checkout replacement skips that validation
   hook, Checkout Bouncer verifies again the moment the order is created and stops
   it there, before any gateway is engaged, with the order marked failed and annotated.
 * **Block checkout (Store API).** The token rides along as registered Store API
   extension data and is verified on the checkout request itself. Several widely
   installed captcha plugins still do not check this route. WooCommerce patched 
   a number of the larger ones in December 2024, but not all of them, and a plugin
   that only hooks the classic form still sees nothing here.
 * **Pay for order.** The emailed payment link is verified before the gateway is
   called. This is the page bots use to retry stolen cards against an order they
   already created.
 * **Add payment method.** Optional, off by default. Stops a signed-in bot saving
   cards against your gateway without buying anything.

Verification happens before any gateway is asked for money, on every surface.

#### Block

Some surfaces cannot carry a token. An old WooCommerce cannot register Store API
extension data, and neither can a duplicate page nobody maintains. For those, Checkout
Bouncer closes the door instead:

 * **Block the Store API checkout route** with a 404 or 403 of your choosing.
 * **Block duplicate checkout pages** found by the scanner, with the same status
   code. Enforcement reads the small list the scanner saved, so it keeps working
   after a settings save, a page edit or a cache clear. It never blocks your configured
   checkout page, and it blocks nothing at all while WooCommerce has no checkout
   page set.
 * Store staff and allowlisted IP addresses are always let through, so you can still
   inspect a blocked page yourself.

#### A second, different kind of protection

reCAPTCHA answers “is this a browser?”. It cannot answer “is this browser behaving
like a card tester?”, because each individual request looks perfectly human.

So Checkout Bouncer also ships a gateway-agnostic **order-rate throttle** with three
rules, all keyed on a salted hash of the client IP:

 * too many orders in an hour
 * too many failed payments in fifteen minutes, which is the classic card-testing
   signature
 * too many distinct billing email addresses in an hour (one card, many identities)

It covers the classic checkout, the block checkout Store API and pay-for-order alike,
with no gateway-specific code anywhere.

Each surface is enforced on the hook WooCommerce actually lets a rejection travel
through. That is `woocommerce_checkout_order_processed` for the classic form, `woocommerce_store_api_checkout_update_order_from_request`
for the Store API, and `woocommerce_before_pay_action` for pay-for-order, the page
bots use to retry stolen cards. That last one matters, because paying for an order
that already exists never creates one, so a throttle hung on order creation alone
would never see it.

Some deliberate details:

 * Only a real placement is counted. Opening the block checkout creates a draft 
   order behind the scenes. That is a page view, not an order, and it never touches
   your limits.
 * An attempt that was blocked is not counted either, so a rolling window always
   drains and a shared office or mobile-carrier address recovers by itself.
 * A throttled block-checkout placement is refused with HTTP 429 and the draft is
   left alone, and a throttled pay-for-order attempt returns the customer to the
   payment page with a notice and the order still payable. Only the classic checkout
   leaves a failed order behind, because WooCommerce has already created the row
   by the time any hook can stop it.

There is a **monitor mode** that records every trip without blocking anything, so
you can tune the limits against your real traffic before you arm them. The throttle
works even before you have finished setting up your reCAPTCHA keys.

#### Everything else you would expect

 * **Events dashboard.** Seven-day tiles by verdict, the top block reasons, and 
   a paginated log of every pass, fail, skip and block, filterable by verdict, surface,
   reason, date range and free text, with a **CSV export** that downloads exactly
   the selection on screen.
 * **Support tab.** Before it sends you anywhere, it checks this store: whether 
   keys are saved, whether anything is being verified, what the last scan found,
   whether the log is recording, and whether Checkout Bouncer is seeing your shoppers
   or your proxy. That last one is the check nobody thinks to run. It also builds
   a **system report** you can paste into a forum thread, holding no secret key,
   no token and no IP address.
 * **Per-gateway targeting.** Verify all payment methods, only a chosen list, or
   everything except a chosen list. No gateway id is hardcoded anywhere in this 
   plugin.
 * **Staff and IP bypass.** Roles you choose skip verification, plus an IP allowlist
   that accepts IPv4, IPv6 and CIDR ranges for your office or warehouse.
 * **Fail open or fail closed.** Decide for yourself whether an order goes through
   when Google cannot be reached.
 * **HPOS and block compatible.** Compatibility with High-Performance Order Storage
   and with Cart and Checkout Blocks is formally declared, so WooCommerce never 
   flags Checkout Bouncer as incompatible.
 * **Keys in `wp-config.php`.** Define `CHECKOUT_BOUNCER_SITE_KEY` and `CHECKOUT_BOUNCER_SECRET_KEY`
   to keep them out of the database entirely. The settings fields then render read-
   only.
 * **Privacy-first logging.** IP addresses are anonymized before they are stored,
   billing addresses are only ever kept as salted digests, and a daily job purges
   anything older than your retention window.
 * **Invisible to real customers.** No challenge, no puzzle, no extra click, no 
   layout shift.
 * **Built for a store, not a client.** No hardcoded IP addresses, no hardcoded 
   gateway, no assumptions about your theme or your checkout type.
 * Translation-ready, multisite-aware, no bundled frameworks, no CDN assets, no 
   build step, no tracking, and no phone-home of any kind.

#### Scope

Checkout Bouncer protects the WooCommerce **checkout**, and only the checkout, using**
reCAPTCHA v3** only. It does not touch your login form, registration, comments or
contact forms, and it does not offer reCAPTCHA v2, hCaptcha or Turnstile.

### Third-Party Services and Privacy

Checkout Bouncer relies on one external service: **Google reCAPTCHA v3**. reCAPTCHA
is the service doing the scoring, so this is inherent to what the plugin does, and
it cannot be switched off while the plugin is verifying checkouts.

Please read this section before installing, and reflect it in your own privacy policy.

#### What is loaded in your customer’s browser

Checkout Bouncer enqueues the Google reCAPTCHA v3 API script from `https://www.google.
com/recaptcha/api.js`. Loading that script means Google receives your visitor’s 
IP address and standard request headers, and reCAPTCHA collects device, browser 
and interaction signals in order to produce a risk score. Google may set cookies
in your visitor’s browser.

**By default this happens on every front-end page of your shop, not only the checkout.**
That is deliberate. reCAPTCHA v3 scores a visitor on how they behaved across the
whole site, and Google recommends running it in the background of pages rather than
only on the form you are protecting, because a single data point produces unreliable
scores.

If you would rather limit the reach of Google, set the loading scope to “Checkout
screens only” and the script is enqueued on checkout, pay-for-order and add-payment-
method views alone, at the cost of less accurate scoring. Please check which setting
fits your privacy policy, and, if you serve visitors in the EU or another consent
regime, your cookie-consent flow.

#### What is sent from your server

When an order is submitted, Checkout Bouncer sends a single server-to-server `POST`
request to the Google verification endpoint:

    ```
    https://www.google.com/recaptcha/api/siteverify
    ```

That request contains **your secret key**, **the reCAPTCHA token minted in the visitor’s
browser**, and **the visitor’s IP address** (as `remoteip`, which is how the Google
API is designed to be called). Google replies with a success flag, a score between
0.00 and 1.00, the hostname and action the token was minted for, and any error codes.

No order contents, no customer name, no email address and no payment details are
ever sent to Google by Checkout Bouncer.

Your secret key is only ever used server-side. It is never printed into a page, 
never written to a log, and never returned to the browser. The settings screen shows
a fixed mask instead of the stored value, and error messages are scrubbed of it 
before display.

 * Google Privacy Policy: https://policies.google.com/privacy
 * Google Terms of Service: https://policies.google.com/terms
 * reCAPTCHA overview: https://developers.google.com/recaptcha

Sites in regions where `www.google.com` is unreachable can point the browser script
at the Google `www.recaptcha.net` mirror using the `checkout_bouncer_api_script_url`
filter.

#### What Checkout Bouncer stores on your own site

 * An **events table** (`{prefix}checkout_bouncer_events`) holding one row per verification,
   throttle trip or block: timestamp, surface, verdict, reason, score, an anonymized
   IP address, the order id where one exists, the payment gateway id and a short
   note. IPv4 addresses are stored with the final octet zeroed and IPv6 addresses
   with the last 80 bits zeroed. Rows older than your retention window (30 days 
   by default) are deleted by a daily scheduled job, and you can clear the table
   at any time.
 * **Throttle counters** in transients, named using a site-salted, non-reversible
   hash of the IP address. A raw address is never written into a transient name.
   Billing email addresses are stored only as salted digests, never in plaintext,
   because the rule only needs to know whether two addresses differ.
 * **Order notes** recording what Checkout Bouncer decided about each order, its
   score and the threshold in force.
 * Optional lines in the standard WooCommerce logger, which never contain the token,
   the secret key or a full email address.

Uninstalling the plugin removes all of it: the settings, the transients, the scheduled
job and the events table.

#### No other external requests

The Google `api.js` and `siteverify` calls are the only outbound requests this plugin
makes. There is no analytics, no license check, no usage tracking, no remote font
and no CDN asset of any kind.

## Скриншоттор

[⌊Dashboard. Status cards showing whether protection is live, whether your keys 
are saved and which checkout surfaces are covered, plus seven-day tiles broken down
by verdict, the top reasons orders were blocked, and quick links into the scanner
and the log.⌉⌊Dashboard. Status cards showing whether protection is live, whether
your keys are saved and which checkout surfaces are covered, plus seven-day tiles
broken down by verdict, the top reasons orders were blocked, and quick links into
the scanner and the log.⌉[

**Dashboard.** Status cards showing whether protection is live, whether your keys
are saved and which checkout surfaces are covered, plus seven-day tiles broken down
by verdict, the top reasons orders were blocked, and quick links into the scanner
and the log.

[⌊Checkout scanner. One row per surface Checkout Bouncer found: the checkout page
and how it is rendered, the Store API route, pay-for-order, add-payment-method and
every rogue duplicate checkout page on the site, each with a plain explanation of
what was found, a severity, and one-click Protect or Block actions.⌉⌊Checkout scanner.
One row per surface Checkout Bouncer found: the checkout page and how it is rendered,
the Store API route, pay-for-order, add-payment-method and every rogue duplicate
checkout page on the site, each with a plain explanation of what was found, a severity,
and one-click Protect or Block actions.⌉[

**Checkout scanner.** One row per surface Checkout Bouncer found: the checkout page
and how it is rendered, the Store API route, pay-for-order, add-payment-method and
every rogue duplicate checkout page on the site, each with a plain explanation of
what was found, a severity, and one-click Protect or Block actions.

[⌊Settings. reCAPTCHA keys with a "Test keys" button that validates your secret 
against Google, score threshold and fail-open behavior, per-surface protection switches,
per-gateway targeting, blocking options, the order-rate rules with monitor mode,
staff roles and the IP allowlist.⌉⌊Settings. reCAPTCHA keys with a "Test keys" button
that validates your secret against Google, score threshold and fail-open behavior,
per-surface protection switches, per-gateway targeting, blocking options, the order-
rate rules with monitor mode, staff roles and the IP allowlist.⌉[

**Settings.** reCAPTCHA keys with a “Test keys” button that validates your secret
against Google, score threshold and fail-open behavior, per-surface protection switches,
per-gateway targeting, blocking options, the order-rate rules with monitor mode,
staff roles and the IP allowlist.

[⌊Logs. Every verification, throttle trip and block, newest first, with verdict,
surface, reason, score, anonymized IP, gateway and linked order where one exists.
Filter by verdict, surface, reason, date range or free text, then export exactly
that selection to CSV.⌉⌊Logs. Every verification, throttle trip and block, newest
first, with verdict, surface, reason, score, anonymized IP, gateway and linked order
where one exists. Filter by verdict, surface, reason, date range or free text, then
export exactly that selection to CSV.⌉[

**Logs.** Every verification, throttle trip and block, newest first, with verdict,
surface, reason, score, anonymized IP, gateway and linked order where one exists.
Filter by verdict, surface, reason, date range or free text, then export exactly
that selection to CSV.

[⌊Front-end checkout. What your customers see: nothing. No checkbox, no puzzle, 
no extra click. Just the reCAPTCHA badge, or the required attribution sentence under
the place-order button if you have chosen to hide it.⌉⌊Front-end checkout. What 
your customers see: nothing. No checkbox, no puzzle, no extra click. Just the reCAPTCHA
badge, or the required attribution sentence under the place-order button if you 
have chosen to hide it.⌉[

**Front-end checkout.** What your customers see: nothing. No checkbox, no puzzle,
no extra click. Just the reCAPTCHA badge, or the required attribution sentence under
the place-order button if you have chosen to hide it.

## Орнотуу

#### Requirements

 * WordPress 6.2 or newer
 * WooCommerce 7.0 or newer
 * PHP 7.4 or newer

#### Install

 1. Upload the `checkout-bouncer` folder to `/wp-content/plugins/`, or install the 
    ZIP through **Plugins > Add New > Upload Plugin**.
 2. Activate Checkout Bouncer through the **Plugins** screen.
 3. Go to **WooCommerce > Checkout Bouncer**.

#### Get your reCAPTCHA keys

 1. Open the Google reCAPTCHA admin console at https://www.google.com/recaptcha/admin.
 2. Register a new site and choose **reCAPTCHA v3**, not v2, and not reCAPTCHA Enterprise.
 3. Add your store domain. Add `localhost` too if you are testing locally.
 4. Copy the **site key** and the **secret key**. They are two different values, and
    pasting the same one into both fields is the most common setup mistake.
 5. Paste them into **WooCommerce > Checkout Bouncer > Settings**, save, and press **
    Test these keys**. Checkout Bouncer asks Google to validate the secret without 
    needing a real browser token and tells you exactly what Google said.

Prefer to keep keys out of the database? Define them in `wp-config.php` instead 
and the fields become read-only:

    ```
    define( 'CHECKOUT_BOUNCER_SITE_KEY', 'your site key' );
    define( 'CHECKOUT_BOUNCER_SECRET_KEY', 'your secret key' );
    ```

#### Then run the scanner

Open the **Checkout scan** tab and press **Re-scan now**. It takes a second and 
tells you how your checkout is built, which surfaces are protected, which are not,
and what to do about each one.

Work down the list until nothing is highlighted. Then place a test order yourself
and confirm a `pass` row appears on the **Logs** tab.

If your store is behind Cloudflare, a load balancer or any other reverse proxy, 
read the proxy answer in the FAQ before you arm the rate limits or fill in the IP
allowlist. One filter has to be set, or Checkout Bouncer only ever sees your proxy
address.

## FAQ.KG

### Which checkout types are supported?

All of them.

 * The classic `[woocommerce_checkout]` shortcode checkout.
 * The **WooCommerce Checkout block**, verified through the Store API. This is the
   surface several widely installed captcha plugins still miss.
 * The **pay for order** page, used by emailed payment links.
 * The **add payment method** page, where signed-in customers save a card (optional,
   off by default).

A checkout page built with Elementor, Divi, WPBakery, Beaver Builder, Bricks or 
Oxygen is recognized too. The scanner looks inside the builder’s own saved layout
to find the checkout element and reports which builder it found.

### Does it work with the block checkout?

Yes, and this is the reason Checkout Bouncer exists. The block checkout does not
submit an HTML form. It posts JSON to the WooCommerce Store API.

Checkout Bouncer registers proper Store API extension data so the reCAPTCHA token
travels with the order, then verifies it on the checkout request. A failed check
is turned into a clean error in the block interface, and no charge is attempted.

If your WooCommerce is too old to register Store API extension data, Checkout Bouncer
cannot attach a token. It tells you that plainly and offers to block the route instead,
which is the honest answer rather than a checkbox that does nothing.

### Can it block the Store API?

Yes. If your customers check out through the classic form, the Store API checkout
route is an open door you are not using, and Checkout Bouncer can return a 404 or
a 403 for every request to it. Store staff and allowlisted IP addresses are always
let through.

Be careful with this one. **Blocking the route disables the block checkout, the 
WooCommerce mobile app and any headless front end.** The scanner spells that out
before you switch it on, and if you block the route while your own checkout page
uses the block, Checkout Bouncer raises a critical warning with a one-click undo.

### What happens if Google is down or unreachable?

You decide, with the **fail open** setting.

 * **Fail open (default).** If Google cannot be reached, times out, or answers with
   something unreadable, the order is allowed through and the event is logged as
   a soft failure. Your store keeps taking money during a Google outage.
 * **Fail closed.** The order is rejected instead. Safer, but a Google outage becomes
   your outage.

Problems at your end, such as a malformed request or a bad secret key, are always
treated as soft failures rather than punishing the shopper for your configuration.

### Why do I have to keep the reCAPTCHA badge, or show the attribution text?

The Google terms require that visitors are told reCAPTCHA is in use. You can satisfy
that in one of two ways, and Checkout Bouncer supports both:

 * Leave the floating reCAPTCHA badge visible (the default). Nothing else is needed.
 * Switch on **Hide badge**, and Checkout Bouncer automatically prints the required
   sentence near your place-order button: “This site is protected by reCAPTCHA and
   the Google Privacy Policy and Terms of Service apply.” It carries both links,
   and it is wired in five different places so a theme that drops the WooCommerce
   hooks cannot make it disappear.

**Hiding the badge without that sentence breaks the Google terms.** Checkout Bouncer
will not let that happen, and you do not need to add the sentence yourself. If you
do, you will end up with two.

### What score threshold should I use?

Start at **0.5**, which is the Google recommendation and the Checkout Bouncer default,
and leave it there for a week while you watch the Logs tab.

 * Scores run from 0.00 (almost certainly a bot) to 1.00 (almost certainly a human).
 * **0** verifies nothing, so every visitor passes. Tokens are still checked and
   scores are still recorded, which makes it a legitimate way to gather data before
   arming the plugin, but it rejects nobody. The scanner will warn you it is on.
 * **0.9 and above will reject real customers.** Genuine shoppers on phones, on 
   VPNs, or behind a corporate network routinely score below that. The scanner warns
   about this too.

Raise it slowly, one notch at a time, and watch your `low-score` rows for orders
that look human.

### Will it block real customers?

That is the failure mode to watch, and Checkout Bouncer is built to make it visible
rather than silent.

Every decision is logged with its score and the threshold in force, every order 
gets a note explaining what happened, and the scanner warns you when your threshold
is set high enough to cause trouble. If in doubt, set fail open, keep the threshold
at 0.5, and read the logs for a week.

### Does it work with caching, or behind Cloudflare?

Yes, with two things worth knowing.

**Caching.** reCAPTCHA v3 tokens are minted in the browser and expire after 120 
seconds, so a cached checkout page is not a correctness problem. The token is generated
fresh on page load and refreshed on a timer (100 seconds by default).

The one real failure case is a page cache so aggressive that it serves a checkout
page whose scripts were never enqueued, and the default **Script loading scope**
of every page already covers it. The Google API script loads on every front-end 
page, which survives any cache configuration. If you narrow the scope to checkout
screens only and you run an aggressive cache or CDN, switch it back.

**Cloudflare and other proxies.** Out of the box Checkout Bouncer takes the client
address from `REMOTE_ADDR`, the address your web server actually saw on the socket,
and from nothing else.

It does **not** trust `X-Forwarded-For`, `X-Real-IP` or `CF-Connecting-IP`, and 
it does not ask the WooCommerce geolocation helper either, because those headers
are set by whoever sends the request. Trusting one would let any visitor walk onto
your IP allowlist, hand themselves a fresh throttle bucket on every request, and
spend a real customer quota by sending that customer address.

**If your site sits behind Cloudflare, a CDN, a load balancer or any reverse proxy,
you have to opt in. Until you do, `REMOTE_ADDR` is the proxy, not the shopper.**
In that state your IP allowlist entries can never match, every shopper shares one
throttle bucket behind the proxy address (so the rate limits become far more aggressive
than you intended), and the address on the Logs tab is your proxy address.

Opt in with one filter, naming the single header your proxy is guaranteed to overwrite
on every request:

    ```
    add_filter( 'checkout_bouncer_trusted_proxy_header', function () { return 'HTTP_CF_CONNECTING_IP'; } );
    ```

Set it only when visitors cannot reach your origin server directly. If they can,
that header is spoofable again and you are back to the hole above. Checkout Bouncer
reads that one header, validates the address it finds, and falls back to `REMOTE_ADDR`
when it holds nothing usable.

That filter is the only thing that changes how an address is resolved. Checkout 
Bouncer does not read your WooCommerce or Cloudflare proxy configuration, so on 
a proxied site without it the address Checkout Bouncer uses can differ from the 
one WooCommerce records on the order.

The quickest check is the **Settings** tab, which prints the address Checkout Bouncer
itself sees. If that is not your own address, you need the filter.

### Will it slow my site down?

No, in any way a customer would notice.

The Google script is loaded in the footer and only on the pages that need it, so
it never blocks rendering. Server-side, exactly one HTTP request is made to Google
per checkout attempt, and only for a surface you have switched on.

A token is never verified twice in one request. v3 tokens are single-use at Google,
so the result is held for the rest of the request.

The scanner is the only expensive piece of work in the plugin, and it runs at most
once every twelve hours, only in the admin or on cron, never on a front-end page
load. Duplicate-page blocking reads a single autoloaded option, not a database query.

### Does it store personal data?

As little as it can, and nothing in plaintext that it does not need.

IP addresses are **anonymized before they are stored**, with the last octet of an
IPv4 address and the last 80 bits of an IPv6 address zeroed. Throttle counters use
a site-salted, non-reversible hash of the IP, so a raw address never appears even
in a transient name. Billing email addresses are stored only as salted digests.

Log lines never contain the reCAPTCHA token, the secret key or a full email address.
Your retention window is configurable and enforced by a daily job, and uninstalling
the plugin drops the events table outright.

Please still disclose Google reCAPTCHA in your own privacy policy. See the Third-
Party Services section above.

### How do I stop Checkout Bouncer checking my own office?

Two ways, and you can use both:

 * **Roles.** Staff bypass is on by default for administrators and shop managers,
   and you can choose which roles count as staff.
 * **IP allowlist.** Paste your office or warehouse addresses, one per line, into
   the allowlist. IPv4, IPv6 and CIDR ranges are all accepted, so `203.0.113.7`,`
   203.0.113.0/24` and `2001:db8::/32` are all valid. Invalid lines are dropped 
   when you save, so a typo can never widen your allowlist by accident.

Allowlisted addresses and staff are also exempt from the throttle and from route
blocking, so you can always reach a blocked page to inspect it.

One caveat if you are behind a proxy. The allowlist is matched against the address
Checkout Bouncer sees, which is `REMOTE_ADDR` until you set the `checkout_bouncer_trusted_proxy_header`
filter described above. On a proxied site without that filter your office address
never appears, so an allowlist entry for it will simply never match. Check the address
printed on the Settings tab before you rely on the allowlist.

### How do I test that it is actually working?

 1. Place a real test order in a normal browser window. A `pass` row appears on the**
    Logs** tab within seconds, with the score Google gave you, and the order gets a
    note recording the same thing.
 2. Open the same order and check the note reads as expected. Surface, score, threshold
    and reason are all there.
 3. To see a rejection without needing a bot, temporarily raise the score threshold
    to 0.9, place another test order, and watch it fail with `low-score`. **Put the
    threshold back to 0.5 afterwards.**
 4. Press **Test keys** on the Settings tab at any time. Checkout Bouncer validates
    your secret against Google without needing a browser token and reports exactly 
    what Google said.

### My logs are full of “missing-token”, what does that mean?

It means the browser never produced a token. In practice that is one of four things:

 * A **bot** that does not run JavaScript. This is Checkout Bouncer working exactly
   as intended, and it is by far the most common cause.
 * An **ad-blocker or privacy extension** stopping the Google script from loading.
   Checkout Bouncer gives up quietly after about ten seconds rather than throwing
   errors in the console, so the customer sees a checkout error rather than a broken
   page. If you serve a lot of privacy-conscious traffic, turn **strict browser 
   error** off so a blocked script is treated as a soft failure instead.
 * An **aggressive page cache** serving a checkout page whose scripts were never
   enqueued. The default sitewide loading scope already covers this, so check it
   has not been narrowed to checkout-only.
 * A **JavaScript error from another plugin or theme** halting the page before the
   Checkout Bouncer script runs. Check your browser console on the checkout page.

### What is the difference between reCAPTCHA and the order rate limits?

They catch different attacks, which is why the plugin ships both.

reCAPTCHA scores a **single request**, asking whether there is a real browser and
a plausible human behind this submission.

The rate limits look at a **pattern over time**, counting how many orders, how many
failed payments and how many different billing email addresses have come from one
address inside a window you choose. The defaults are 8 orders an hour, 4 failed 
payments in fifteen minutes and 6 distinct billing emails an hour.

A patient attacker driving a real browser can pass reCAPTCHA every single time and
still be obviously card-testing the moment you look at the shape of the traffic.

The limits are applied on the classic checkout, the block checkout and pay-for-order,
and they are keyed on the address Checkout Bouncer resolves. Read the proxy answer
above first if your site is behind Cloudflare or a load balancer, because otherwise
every shopper counts against a single bucket.

Run the throttle in **monitor mode** first. It records every trip without blocking
anything, so you can see what your real traffic looks like before you arm it.

### Does it work with my payment gateway?

Yes, any of them. Checkout Bouncer contains no gateway-specific code at all. It 
hooks the WooCommerce checkout, validation and order hooks, so Stripe, PayPal, Square,
Authorize.Net, NMI, a bank plugin or an offline method all behave the same way.

You can also target verification per gateway: verify **all** payment methods, **
only** a chosen list, or **everything except** a chosen list. That is useful when
one gateway runs its own risk engine and you would rather not double up, or when
a manual bank transfer method genuinely does not need scoring.

### Does it support HPOS and modern WooCommerce?

Yes. Checkout Bouncer formally declares compatibility with High-Performance Order
Storage (custom order tables) and with Cart and Checkout Blocks, so WooCommerce 
never lists it as incompatible. It works identically on legacy post-based order 
storage and on HPOS.

### What about reCAPTCHA v2, hCaptcha or Turnstile?

Not supported, on purpose. Checkout Bouncer is a reCAPTCHA v3 plugin.

v3 is invisible and scores every request, which is what a checkout needs. A v2 checkbox
on a checkout costs you real conversions to catch bots that a score would have caught
anyway.

### Does it protect my login or registration form?

No, also on purpose. Checkout Bouncer protects the WooCommerce checkout and nothing
else.

Its whole design, meaning the scanner, the surface model, the order-rate rules and
the order notes, is built around orders. If you need login protection, use a plugin
built for that job.

### Does it work on multisite?

Yes. Activation, the events table, the scheduled purge and uninstall are all network-
aware, and a site created while the plugin is network-active is set up automatically.
Each site keeps its own settings, its own keys and its own event log.

### Where do I get help?

Start on the **Support** tab, at **WooCommerce > Checkout Bouncer > Support**. It
checks this store first and names what it finds: whether keys are saved, whether
anything is actually being verified, what the last checkout scan raised, whether
the event log is recording, and whether Checkout Bouncer is resolving your shopper
addresses or your proxy address. Most questions are answered right there, immediately.

If they are not, the same tab builds a **system report** covering configuration,
last scan, seven days of totals, and the WordPress, PHP, WooCommerce, theme and 
plugin details anyone helping you would otherwise have to ask for. Copy it into 
a thread on the WordPress.org support forum for this plugin and say what you expected
to happen instead.

The report is written in English whatever language your store runs in, so whoever
answers can read it. It contains no secret key, no reCAPTCHA token and no IP address,
only whether the address your request arrived from was public or private.

## Сын-пикирлер

There are no reviews for this plugin.

## Contributors & Developers

“Checkout Bouncer” is open source software. The following people have contributed
to this plugin.

Мүчөлөрү

 *   [ Mahruf Hussain ](https://profiles.wordpress.org/mhussain3209/)

[Translate “Checkout Bouncer” into your language.](https://translate.wordpress.org/projects/wp-plugins/checkout-bouncer)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/checkout-bouncer/),
check out the [SVN repository](https://plugins.svn.wordpress.org/checkout-bouncer/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/checkout-bouncer/)
by [RSS](https://plugins.trac.wordpress.org/log/checkout-bouncer/?limit=100&mode=stop_on_copy&format=rss).

## Өзгөртүүлөр

#### 1.0.2

_Release date: 22 September 2026_

 * Rewrote the readme description and the whole FAQ in plain American English, and
   applied the same pass to every admin screen string. No behavior changed and no
   setting moved.
 * Removed em dashes and en dashes from all user-facing text, in the readme and 
   in the plugin.
 * Switched British spellings to American throughout: anonymized, recognized, behavior,
   license.

#### 1.0.1

_Release date: 17 August 2026_

 * New **Support** tab under WooCommerce > Checkout Bouncer. It opens with five 
   live checks against this store: reCAPTCHA keys, whether anything is being verified,
   what the last checkout scan found, whether the event log is recording, and whether
   client addresses are being resolved through a proxy. The commonest questions 
   are answered without waiting for a reply.
 * The support tab also carries the four problems behind most support threads, links
   to the support forum and the documentation, and a copyable **system report** 
   holding the full Checkout Bouncer configuration, the last scan, seven days of
   event totals, and the WordPress, PHP, WooCommerce, theme and active-plugin details
   anyone answering a question has to ask for anyway.
 * The system report never contains your secret key, a reCAPTCHA token or an IP 
   address, only whether the address the request arrived from was public or private,
   which is the part a proxy diagnosis actually turns on.
 * Opening the support tab never triggers a checkout scan. It reads the cached report
   and reports an unscanned store as unscanned, so a screen you reached because 
   something is wrong cannot cost you a full store scan.

#### 1.0.0

_Release date: 12 August 2026_

Initial release.

 * reCAPTCHA v3 verification on the classic checkout, the WooCommerce Checkout block
   via the Store API, the pay-for-order page and the add-payment-method page.
 * Checkout scanner: detects the configured checkout page and its renderer (checkout
   block, classic shortcode, or Elementor, Divi, WPBakery, Beaver Builder, Bricks
   or Oxygen), finds rogue duplicate checkout pages, resolves the Store API route
   and the order-pay and add-payment-method endpoints, and runs configuration health
   checks, each with one-click protect and block actions.
 * Blocking: return 404 or 403 for the Store API checkout route and for scanner-
   flagged duplicate checkout pages, with staff and allowlisted addresses always
   let through.
 * Gateway-agnostic order-rate throttle on the classic checkout, the Store API and
   pay-for-order: orders per hour, failed payments per fifteen minutes, and distinct
   billing emails per hour, with a monitor mode that records without blocking.
 * Client addresses are resolved from `REMOTE_ADDR` only. A forwarded header such
   as `CF-Connecting-IP` is read solely when the `checkout_bouncer_trusted_proxy_header`
   filter opts in, so an allowlist entry cannot be reached with a spoofed header.
 * Events dashboard with seven-day statistics, top block reasons, a filterable log
   and CSV export.
 * Per-gateway targeting, staff-role bypass, and an IPv4, IPv6 and CIDR allowlist.
 * Fail-open handling for Google outages, configurable score threshold, and a “Test
   keys” button that validates your secret without needing a browser token.
 * Badge attribution handled automatically when the reCAPTCHA badge is hidden.
 * Privacy-first logging: anonymized IP addresses, hashed throttle buckets, salted
   email digests and a daily retention purge.
 * HPOS and Cart and Checkout Blocks compatibility declared, multisite-aware activation
   and uninstall, and full translation support.

## Мета

 *  Нуска **1.0.2**
 *  Акыркы жаңыртуу **5 күн мурун**
 *  Активдүү орнотуулар **Fewer than 10**
 *  WordPress нускасы ** 6.2 же андан жогору **
 *  Tested up to **7.0.6**
 *  PHP нускасы ** 7.4 же андан жогору **
 *  Тил
 * [English (US)](https://wordpress.org/plugins/checkout-bouncer/)
 * Тег:
 * [bot protection](https://ky.wordpress.org/plugins/tags/bot-protection/)[captcha](https://ky.wordpress.org/plugins/tags/captcha/)
   [recaptcha](https://ky.wordpress.org/plugins/tags/recaptcha/)[spam protection](https://ky.wordpress.org/plugins/tags/spam-protection/)
   [woocommerce](https://ky.wordpress.org/plugins/tags/woocommerce/)
 *  [Advanced View](https://ky.wordpress.org/plugins/checkout-bouncer/advanced/)

## Рейтинг

Азырынча эч кандай сын-пикир жок.

[Your review](https://wordpress.org/support/plugin/checkout-bouncer/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/checkout-bouncer/reviews/)

## Мүчөлөрү

 *   [ Mahruf Hussain ](https://profiles.wordpress.org/mhussain3209/)

## Колдоо

Комментарийлер барбы? Жардам керекпи?

 [Колдоо форумун көрүү](https://wordpress.org/support/plugin/checkout-bouncer/)