What the check looks at
C2 requests the cart, checkout and My account pages that are set in WooCommerce, each with a unique query parameter and without cookies, so the test shopper has an empty cart. Each page counts only once it is confirmed to be the real WooCommerce page: the cart and account pages by the body class WooCommerce prints, and the checkout either by its body class or by the 302 redirect to the cart that WooCommerce sends when the cart is empty.
For every confirmed page the plugin reads the cf-cache-status header. The worst page decides the result.
The addresses come from WooCommerce. A page WooCommerce gives on another host is not requested, and the result names it in a note. When all three are on another host, the check does not apply.
Like every request Edge Doctor sends, these go only to the hosts of your Site Address and WordPress Address (home_url() and site_url()). An address WordPress gives on another host, such as a single sign on page, is never requested.
Results and what they mean
The plugin sorts the cf-cache-status header Cloudflare returns into classes. HIT, MISS, EXPIRED, STALE, REVALIDATED and UPDATING all mean the response was eligible for the cache, so they count as cacheable; a MISS is a copy that is being stored now. BYPASS means a rule made the request eligible, but the origin response was not cacheable. DYNAMIC means Cloudflare decided at request time that the response is not eligible, which is the normal state for private pages. (Cloudflare: cache responses.)
| Result | What it means |
|---|---|
| PassedConfidence: High | Your shop pages are not cached Cloudflare treats the cart, checkout and account pages as dynamic ( DYNAMIC). |
| WarningConfidence: High | A cache rule reaches your shop pages A rule makes the pages eligible for the cache, and only the headers WooCommerce sends keep them out for now ( BYPASS). |
| FailedConfidence: High | Cloudflare is caching your shop pages Cloudflare answered for a shop page from its cache, or stored it. When the stored answer is the checkout redirect, a shopper with a full cart is sent back to the cart and cannot pay. |
| Could not checkConfidence: High | This check could not be completed The cache key ignores the query string, so the plugin did not request any private page ( qs_ignored). |
| Could not checkConfidence: Medium | This check could not be completed No page could be confirmed: they did not answer as WooCommerce prints them, or the shop is in Coming soon mode. |
| Could not checkConfidence: Low | This check could not be completed Cloudflare did not say what it did (no usable cf-cache-status), or the requests did not get through. |
| Not applicable | WooCommerce is not active Reason plugin_inactive. |
| Not applicable | No cart, checkout or account page is set up Reason no_records. |
| Not applicable | The shop pages are on another host Reason out_of_scope. The plugin sends requests only to your own site. |
| Not applicable | Cloudflare is not in front of this site Check A1 did not detect Cloudflare, so this check sent no request. Reason not_behind_cloudflare. |
When the result names a reason
qs_ignored: Your cache key ignores the query string, so the plugin cannot test a page without risking a cached copy of it. Before it asks for any private address, the plugin requests your home page twice with a different unique query string. If either answer is aHIT, your cache key ignores the query string, and a test request could store a private page under an address visitors use. So the plugin stops and sends nothing.shop_pages_not_found: The cart, checkout and account pages did not answer as WooCommerce prints them, so they could not be checked. A theme or plugin may send them somewhere else. Pages that were not confirmed are listed as not seen and never count as passed.maintenance: The site is in maintenance mode or behind a coming soon page, so the pages read were not the real ones. On C2 this means every page that answered was the WooCommerce Coming soon page.worker: A Cloudflare Worker sits in front of this site, so cache headers do not say what the cache did.loopback_failed: Your server could not reach its own site, so this check had nothing to read. The plugin links this result to its own guide: Your server could not reach its own site.blocked_by_config: WordPress itself refused the requests from your site to itself, so none was sent. WP_HTTP_BLOCK_EXTERNAL is on, and your own address is not let through. The plugin links this result to its own guide: WordPress blocks requests to your own site.plugin_inactive: The plugin this check looks at is not active.no_records: There are no DNS records of the kind this check reads.out_of_scope: This check does not apply to a site set up like yours. On C2 it means WooCommerce gives all three shop pages on another host.not_behind_cloudflare: This site is not behind Cloudflare.
Symptoms you may notice
- A shopper sees another shopper’s cart, or the cart shows items they never added.
- The checkout keeps sending people back to the cart, because the stored answer is the redirect WooCommerce sends for an empty cart.
- Payments fail with security errors: a stored checkout page can carry a payment nonce that belongs to somebody else.
- My account can show the wrong page to a customer, such as the login form after they have logged in.
Why it happens
Cloudflare does not cache HTML by default (Cloudflare: default cache behavior). Shop pages get cached when a Cache Rule makes all HTML Eligible for cache and does not exclude them.
The Edge TTL setting of that rule decides how far it goes. With Ignore cache-control header and use this TTL, the headers WooCommerce sends to keep these pages private are ignored: on a test site on 2026-10-25 the cart and account pages, which WooCommerce marks private, were stored (MISS). With Use cache control-header if present, bypass cache if not the same pages came back as BYPASS, which is the Warning: still reached by the rule, but kept out by the headers.
Confirm it by hand
Request the cart twice with the same query string, without cookies, and read the cache headers. Use the address of your cart page:
curl -sI "https://example.com/cart/?cachetest=1" | grep -iE "cf-cache-status|cache-control|age"
curl -sI "https://example.com/cart/?cachetest=1" | grep -iE "cf-cache-status|cache-control|age"HIT on the second request means the page is stored. DYNAMIC is what you want. In a browser: open a private window, open DevTools, Network, tick Disable cache, load the cart and read cf-cache-status in the response headers.
How to fix it
1. Find the rule. Look for the Cache Rule whose expression covers your HTML and whose cache eligibility is Eligible for cache.
2. Keep shop pages out of it. Edit that rule so its expression excludes the shop pages and the WooCommerce cookies, or add a rule with Bypass cache for them. With the default page addresses, an expression for the excluded traffic looks like this (adjust the paths to yours):
(http.request.uri.path contains "/cart/") or (http.request.uri.path contains "/checkout/") or (http.request.uri.path contains "/my-account/") or (http.cookie contains "woocommerce_items_in_cart") or (http.cookie contains "wp_woocommerce_session_")3. Let the origin headers count. If the rule uses Ignore cache-control header and use this TTL, consider Use cache control-header if present, bypass cache if not, so the private headers WooCommerce sends keep pages out of the cache.
4. Clear what is already stored. Purge the cart, checkout and account addresses, or everything if you are not sure.
In WordPress: the pages that count as cart, checkout and My account are set under WooCommerce, Settings, Advanced, Page setup; their addresses are the ones to exclude. Check C5 tells you whether something on the site removes the headers WordPress sends.
Limitations
The test shopper has an empty cart and no cookies. A rule that caches only for visitors with a session cookie is not seen here; check C5 sends cookies.
Only the three pages set in WooCommerce are tested, not order confirmation pages or pages a theme adds.
The plugin sees the cache of the Cloudflare data center its own requests pass through. The rule is the same everywhere, but a stored copy in another data center is out of reach.
Related checks
- C5 Login cookies and private responses: whether the cache steps aside for login and cart cookies.
- C1 wp-admin and the login page in the cache: the same test for wp-admin and the login page.
- C3 Logged-in pages in the public cache: signed in pages served to everybody.
- C6 Cached pages older than their nonces: stored pages with expired nonces.
Sources
- Cloudflare: default cache behavior
- Cloudflare: cache responses
- Cloudflare: create a Cache Rule
- Cloudflare: Cache Rules settings
- Cloudflare: http.cookie field
- Cloudflare: purge everything
Run this check on your own site with Edge Doctor for Cloudflare®, free on WordPress.org.
Edge Doctor for Cloudflare® is not affiliated with or endorsed by Cloudflare, Inc. Cloudflare is a registered trademark of Cloudflare, Inc.