Skip to content

Page Caching ​

How recovery links work with caching plugins, hosts and CDNs, and what to check if a link stops bringing carts back.

A page cache saves a copy of each page and serves that copy to the next visitor instead of building the page again. It makes your store fast, and you should keep it. But a saved copy can't rebuild one particular shopper's cart, so the links in recovery emails have to reach WordPress fresh, every time.

ShapedRecover takes care of its side of that for you. This guide is for store owners who use a caching plugin, a host with built-in caching or a CDN such as Cloudflare. It explains what ShapedRecover already does, the one setting that can still get in the way, and how to check your setup in a couple of minutes.

Check your caching in 4 steps

  1. Know which links matterThe recovery link and the unsubscribe link.
  2. Check your checkout is not cachedUsually already true.
  3. Keep the link parameters intactExclude them in your cache or CDN if needed.
  4. Test a linkA quick header check, then a real click.

Every recovery email carries two personal links. Both are your home page address with a query string, the part after the ?, holding a long random code (a token):

LinkLooks likeWhat WordPress does with it
Recovery linkhttps://yourstore.com/?sprcv_restore=Xk3f…Rebuilds the shopper's cart, notes the click for attribution, then redirects to your checkout (or cart).
Unsubscribe linkhttps://yourstore.com/?sprcv_unsubscribe=…Shows the unsubscribe page; its button sends the request back to the same address.

When either link reaches WordPress, ShapedRecover marks the response as not cacheable, using WordPress's standard no-cache headers and the DONOTCACHEPAGE signal that WordPress caching plugins look for. The recovery link always answers with a fresh redirect, so no cached copy is ever made of it. You don't have to configure anything for that part.

The token is the whole point: without it, WordPress doesn't know whose cart to rebuild. Everything below is about making sure the token gets through. Recovery Link explains what the link does once it arrives.

2. Check your checkout is not cached ​

WooCommerce tells caching plugins never to cache its cart, checkout and My account pages. ShapedRecover captures carts on the checkout, and the recovery link redirects there, so both rely on that.

You normally don't need to do anything. Two cases are worth a look:

  • A custom checkout page. If shoppers check out on a page from a funnel or page builder, rather than the page set as Checkout page in WooCommerce → Settings → Advanced, WooCommerce's protection doesn't cover it. Exclude that page from your cache yourself.
  • "Cache everything" rules. Some CDNs and hosts offer rules that cache every page regardless of what WordPress says. If you use one, make sure it leaves out your cart, checkout and account pages.

What has been tested ​

To be clear about what we know and what we expect:

  • Tested: capture and restore behind WP Super Cache. Storefront pages were cached as normal, the checkout never was, the recovery link answered with a fresh redirect on every click, and the unsubscribe page was never cached.
  • Not yet tested: WP Rocket, LiteSpeed Cache, Cloudflare (including APO), Varnish and hosts' own caching layers. Most caching tools respect the same no-cache signals, but we haven't verified each one, so please run the test below after you set up or change your caching.

3. Keep the link parameters intact ​

The one thing that breaks recovery links is a cache or CDN that ignores or strips query strings. Some do this on purpose to serve more visitors from the cache: they treat yourstore.com/?anything as the same page as yourstore.com/, or remove "unknown" parameters before the request reaches WordPress.

When that happens, the token never arrives. The shopper lands on your home page with an empty cart, and there's no message at all. Unsubscribe links fail the same way: the shopper sees your home page and isn't unsubscribed.

If your cache or CDN has a setting like that, exclude both parameter names:

sprcv_restore
sprcv_unsubscribe

Where to do it depends on your setup, and exact names vary:

  • Caching plugins usually have a list of URLs, or query strings, that should never be cached, often called something like Never cache URLs or Rejected query strings. Add both names. Many plugins already skip any address with a query string unless told otherwise; then there's nothing to do.
  • CDNs (Cloudflare and others) let you add a rule that bypasses the cache when the query string contains a given name. Add one for each parameter, and check that no setting is set to ignore or strip query strings on your home page.
  • Host-level caches (Varnish, Nginx and similar) are often managed by the host. Ask their support to bypass the cache for addresses carrying these two parameters, and send them this page if it helps.

4. Test a link ​

Quick header check ​

You don't need a real cart for this. Any made-up token goes through the same path: WordPress treats it as an expired link and redirects to your cart page. In a terminal, run this twice, with your own address:

bash
curl -s -o /dev/null -D - "https://yourstore.com/?sprcv_restore=test"

What you want to see, both times:

  • A 302 status on the first line.
  • A location: header pointing to your cart page.
  • A cache-control: header that includes no-cache.

If you get a 200 instead, the token didn't reach WordPress: a cached copy of your home page answered, or the query string was removed on the way. Many caches add a header saying whether the answer came from the cache, such as x-cache: HIT or cf-cache-status: HIT (names vary). Fix the exclusions above and run it again.

Do the same for the unsubscribe link:

bash
curl -s -o /dev/null -D - "https://yourstore.com/?sprcv_unsubscribe=test"

Here a 400 status is the good answer: WordPress saw the made-up token and refused it, with the page This unsubscribe link is not valid. A 200 means a cached home page answered instead.

Run these against your public address, the one shoppers use, so the requests go through your CDN.

A real click ​

Then try a real link, ideally on a cart you created yourself:

  1. Create a test cart as a guest, as in Test the Recovery Flow, and open it in Abandoned.
  2. In its Cart Drawer, choose Copy Recovery Link from the ⋯ menu.
  3. Paste the link into a private browser window.

You should land on your checkout with the cart rebuilt, and the token gone from the address bar. The drawer's timeline shows a new Clicked event. Don't do this with a real customer's cart: the click is recorded on their cart.

Troubleshooting ​

What the shopper seesWhat it means
Your home page, cart empty, no messageThe token never reached WordPress. A cache or CDN ignored or stripped the query string. See Keep the link parameters intact.
The cart page with This link has expired.The link reached WordPress fine; caching isn't the problem. The link is older than Link Expires After, or doesn't match a cart. See Expired links.
The checkout with Some items could not be restoredThe link worked; those products are out of stock or no longer for sale. See How the cart is rebuilt.
The checkout showing old or someone else's detailsYour checkout page is being cached. Exclude it, as in step 2.

The drawer's timeline is a good tie-breaker: a working link that reaches WordPress adds a Clicked event to the cart. If a shopper says they clicked a link that hadn't expired and no event appeared, the request never got through.

Where to go next ​