WordPress Consent and Caching: Why Your Banner Shows the Wrong State
A visitor declines tracking, comes back the next day, and the banner asks them again. Or worse: they declined, and the cached page shows them a banner that says they accepted. The consent plugin is working. The cache is undoing it.
The cache does not know about consent
WordPress caching serves a stored copy of the page instead of building it fresh. That is the whole point: speed. But the stored copy was built for one visitor, at one moment, with one consent state, and it is served to every visitor after that. If the cached page was built when the banner was showing, every visitor sees the banner. If it was built after someone accepted, every visitor sees a page that behaves as though they accepted.
The failure is silent. The consent plugin records the visitor's choice correctly. The banner plugin renders correctly. The cache serves the wrong version of both, and nothing in the admin dashboard flags it, because each part is working as designed. The visitor's choice is recorded in one place and ignored in another, which is the worst kind of consent failure: the record says the site did the right thing, and the visitor experienced the opposite.
The mechanism is the cookie. Consent plugins set a cookie when the visitor answers the banner: Jetpack's Cookie Consent Block, for example, sets a cookie named eucookielaw when the visitor accepts. The cache has to vary on that cookie, which means serving different cached versions depending on whether the cookie is present and what it says. If the cache does not vary on the consent cookie, every visitor gets the same cached page regardless of their choice.
Where the fix lives
The fix depends on the cache. In LiteSpeed Cache, the setting is Vary Cookies, and the consent cookie name goes in the list. Once it is there, LiteSpeed serves a separate cached version for visitors with the cookie and visitors without it. In other caches the setting has a different name, but the idea is the same: tell the cache that the page depends on the consent cookie, so it stores and serves the right version for each state.
There is a second place the fix has to land: the server-side check. A page that checks consent in PHP, on the server, before rendering, gets the right answer, because PHP runs fresh on every request that is not served from cache. A page that checks consent in JavaScript, after the cached HTML has already loaded, is checking too late: the cached page may already contain the tracking scripts, and the JavaScript can only remove them after they have run. The reliable pattern is a server-side check against the consent cookie, with the cache varying on that cookie.
And test it the way a visitor experiences it. Open the site in a private window, decline tracking, close the window, open a new private window, and see what the banner does. Then accept, close, reopen, and see what it does. The block editor consent block has the same dependency: the block renders correctly, and the cache decides who sees it. The consent API enqueue order matters for the same reason: scripts that load before the consent check runs are scripts that run before consent.
The audit to run this week
List every cookie your consent setup uses, then check whether your cache varies on each one. If the cache plugin has a Vary Cookies or equivalent setting and the consent cookie is not in it, that is the bug. Add it, purge the cache, and retest with fresh private windows in both states.
Then check the embeds, because they have the same problem in a different form. The WP Consent API at WooCommerce checkout is the highest-stakes version: a checkout page that serves a cached consent state is a checkout that may be tracking a purchase the shopper never consented to. Fix the cache first, then the consent record means something.
Frequently asked questions
Why does my consent banner show the wrong state?
Because the page is served from cache, and the cache does not vary on the consent cookie. The cached page was built for one consent state and is served to every visitor regardless of their choice. Tell the cache to vary on the consent cookie, and purge the cache after.
What is a Vary Cookie?
A setting in the cache plugin that tells it to store separate cached versions of a page depending on whether a named cookie is present. In LiteSpeed Cache it is called Vary Cookies. Add the consent cookie name, and the cache serves the right version for each consent state.
Should the consent check run on the server or in JavaScript?
On the server, against the consent cookie, before the page renders. A JavaScript check runs after the cached HTML has already loaded, which can be too late: the tracking scripts in the cached page may already have run. Server-side is the reliable pattern.
Does the Jetpack Cookie Consent Block set a cookie I can vary on?
Yes. It sets a cookie named eucookielaw when the visitor accepts. Add that name to your cache plugin's vary list, purge the cache, and test with fresh private windows in both the accepted and declined states.