Skip to main content
Shopify checkout applies a test only when the cart carries the visitor’s test groups. This page shows how to put them there for every way a visitor reaches checkout. The samples use abconvert, the client your stack guide creates from the request. The attributes describe the visitor, so create that client where you change the cart, not in a page a cache shares.

Write the attributes

Write the SDK’s attributes when you create the cart, each time you update it, and on your cart page when they changed. One call covers every test the visitor is in, whatever its type. Shopify replaces the cart’s whole attribute list on every update, so send the attributes the cart already has together with ABConvert’s. Keep every attribute whose key the SDK did not return, and let the SDK’s values replace the rest. Both methods return only ABConvert’s attributes. Pass the values to the Storefront API’s cartLinesAdd and cartAttributesUpdate mutations, or to your framework’s cart helper that calls them:
Server (cart action)
Your stack guide shows the same code in your stack’s cart action: Hydrogen, Next.js. Every cart mutation returns userErrors. When the attribute update reports one, the cart still carries its old attributes, so return the error to your cart as you do for a failed add to cart instead of sending the visitor to checkout. A cart keeps a test’s attributes until the SDK returns different values for them. Nothing has to remove them: ABConvert ignores an ended test’s attributes, and a request on which your tests could not load returns only the marker described in Loading and failures, which leaves the cart’s test groups in place.

Prices by country

If you pass country to the client, give the cart the same country in its buyer identity. Shopify prices the order by the cart’s country and ABConvert sets the test price by the country in the attributes, so the two must agree. When the visitor switches country, update the buyer identity and ABConvert’s attributes in the same action. See Prices by country.

On your cart page

Checkout charges what the cart attributes say. A test you launch after the visitor’s last cart change shows its price on your cart page, but the cart does not carry it yet. Compare the attributes when you render the cart, and write them when they differ:
Server (cart page)
The country is one of the attributes, so this check also catches a visitor who switched country since their last cart change. On Hydrogen 2026.10 and later, the component from Step 4 of the Hydrogen guide already does this. A cart drawer is a cart page too. If its checkout button links to checkoutUrl from any page, run the same check in the server action or route handler that returns the drawer’s cart, so the button never carries attributes older than the prices the drawer shows. Price the drawer there too, with the client made from the request.

Show what checkout charges

Once a cart carries ABConvert’s attributes, Shopify prices it with the test price. In the Storefront API, a line’s cost (cost.amountPerQuantity) and the cart’s subtotal (cost.subtotalAmount) already include it, while the product variant’s own price does not. Show the line cost in your cart and drawer: it is what checkout charges, even in the minutes after you launch or end a test.
For a product that is not in the cart yet, such as a recommendation in your drawer, use getPriceByVariantId.

Express checkout

A visitor can reach checkout without your cart page. Whether the test applies depends on how the button creates the checkout.
Server (cart action)

Checkout URLs

getCheckoutUrl() builds a Shopify cart permalink that carries the visitor’s test groups. The visitor lands in checkout with the test applied, and you make no Storefront API call.
Server or browser
Build the URL when you render the button, so it carries the current visitor’s test groups. Do not share or cache it: everyone who opens it would land in the same test group. A checkout URL has two limits that come from Shopify:
  • It cannot sell a subscription. Create a cart for those. A price test does not change the price of a subscription product, on your storefront as on a theme store.
  • It carries cart line attributes for the first line only. Its cart attributes still cover every line, so the test applies to the whole order.

Common mistakes

  • Writing the attributes once. A cart created before a test launched has none for it, so your cart page shows the test price and checkout charges the original. The fix: write them each time you create or update the cart, and on your cart page or drawer when they changed.
  • Replacing the cart’s other attributes. Shopify replaces the whole list on every update. The fix: send the attributes the cart has and ABConvert’s together, as in Write the attributes.
  • Sending the visitor to checkout after a failed update. The cart still carries its old attributes, so checkout charges the old price. The fix: read userErrors and show the cart again.
  • Sharing or caching a checkout URL. Everyone who opens it lands in the same test group. The fix: build the URL when you render the button.