<aside> 🟢
+10% Revenue Per Visitor in 90 days. Or we refund the engagement.
</aside>
This is how you build and ship A/B test variants on Shopify with Claude as the orchestration layer. Theme and Liquid changes, client-side variant code, and checkout extensions. What the platform lets you ship, and what it quietly forbids.
Most CRO tests are CSS and JS injected at page load. They never become permanent theme code unless they win. That single fact is why one person plus Claude can run a build cadence that used to need a dev queue.
The mistake operators make is treating every test like a code deploy. Duplicate the theme, edit the Liquid, push it live, hope nothing breaks, then unwind it all when the test loses. That is slow, and it is how you end up with eleven orphaned theme copies in your admin.
A variant lives in one of four places, depending on what it changes:
| Where the change lives | What it is good for | Permanent? |
|---|---|---|
| Convert variant code (client-side JS/CSS injected at page load) | Copy swaps, layout reorders, hero swaps, CTA changes, social-proof adds, sticky bars, badge/urgency tests | No. Only promoted to theme if it wins |
| Theme + Liquid + sections (server-rendered) | Anything SEO-critical, structured data, metafield-driven content, or a winner you are rolling out permanently | Yes |
| Checkout UI Extensions (Shopify CLI) | Adding content/blocks to native checkout: trust badges, banners, upsells, progress bars, custom fields | Yes (deployed extension) |
| Shopify Functions (WASM/JS) | Checkout logic: cart transforms, validations, discount / delivery / payment customizations | Yes (deployed function) |
The default for testing is the first row. You inject the variant client-side, run the test, and only when it wins do you spend developer time making it server-rendered theme code. The other three rows are where winners go to live permanently, and where checkout-specific tests have to live from the start, because the checkout does not accept injected JS.
<aside> 🟢
Steal this: Tomorrow, count the duplicate themes sitting in your Shopify admin. Every one of them is a test that should have shipped as injected code. Delete the dead copies and commit to one rule: the live theme stays untouched until a winner earns its way in.
</aside>
You touch the theme in exactly two situations.
Rolling out a winner permanently. The test won, it is stable across segments, and you want it server-rendered instead of injected on every page load. Client-side injection adds a flash and a tiny latency cost. A permanent winner belongs in the theme.
The test itself needs server-rendered HTML. If the variant requires markup Shopify must render server-side (dynamic product metafields, structured data, SEO-critical content, JSON-LD), client-side injection is the wrong tool. Those run as redirect/split-URL tests against a real second page, covered later.
For everything else, the variant is JS/CSS and never enters the theme during the test.
The first thing Claude needs is the real, rendered DOM, so it can target the right selectors. Two ways to give it that.