Skip to main content
Oxygen does not cache full pages unless a route opts in to its full-page cache. If none of your routes opts in, you need nothing from this page.

Keep tested routes private

A route a test can change can hold one visitor’s test price, offer, or free-shipping bar, or leave them out for a visitor the test excludes, so a route that opts in must not share it. Call keepPrivateWhenTested on that route’s response headers, after the loader’s reads:
Server (loader)
It turns a public Cache-Control or Oxygen-Cache-Control header into private when a test can change the route: the loader read a tested product’s price, or offers or shipping rates while such a test runs, a price test prices a product the URL shows, a URL redirect test covers it, or the response sets a cookie. It also makes the route private when the server could not load your tests, for example when the first load times out on a cold start, since without them it cannot tell which routes a test changes. A route no test can change stays cached while your tests run. Both Hydrogen entries export it. While a price test runs, every product, collection, search, and home page counts as one it can change, because any of them can show a tested price. If your product pages show only their own product’s price, pass onlyOwnProductPrices: true to createABConvert, and only the tested products’ pages turn private. We trade the full-page cache on those routes, while you test, for the right price and offer for every visitor.

Keep the visitor out of the page

Reading getClientState() in a loader also makes the route private: it holds the visitor. Return getPageState() instead. It carries the tests the request rendered, as the visitor saw them, and nothing about the visitor, so a cached route can carry it. The browser reads the visitor from the cookies. On Hydrogen 2026.10 and later, read the cart attributes in the browser, as Step 4 of the Hydrogen guide does, not in a loader. The attributes describe the visitor.

A feature test on a cached route

A feature test renders a version per test group, so a route that renders one must not be shared either. Call keepPrivateWhenTested on it as above.