This is a one-time exercise per store and per theme. Once done, every future price test works without touching it again. Budget 30–60 minutes for a typical theme, and treat it as developer work — it involves editing Liquid.
1. Confirm your Shopify plan
Price testing needs Shopify Plus. The price a customer is charged is applied by a Cart Transform Function, which Shopify only makes available on Plus[1]. On a lower plan the storefront would show the test price and checkout would charge the original — worse than not testing at all. If you are not on Plus, stop here.
2. Enable the Cooee app embed
In Shopify admin go to Online Store → Themes → Customize → App embeds and turn on the Cooee embed. This loads the extension that assigns visitors to groups; without it nobody is enrolled and every test reports zero.
Do this on the live theme. A newly published theme does not inherit the setting, so re-check it after any theme change.
3. Tag your price elements
This is the substantial part of setup. Cooee does not guess which numbers on the page are prices — you mark them once in your theme, and only what you have marked is ever rewritten.
There are four attributes:
data-lc-price-p="{{ product.id }}"— the selling pricedata-lc-price-cmp="{{ product.id }}"— the compare-at / struck-through pricedata-lc-price-dis="{{ product.id }}"— a discount or savings labeldata-lc-price-v="{{ variant.price }}"— goes alongside-pand-cmp, carrying that element's own price
The first three take the product ID and say what each element is. data-lc-price-v is different: it carries the price itself, so Cooee knows what number your theme actually rendered there.
data-lc-price-p and data-lc-price-v must appear together. Without -v, Cooee leaves the price exactly as your theme drew it — the test still charges correctly at checkout, but the displayed price will not change, which is the one failure you do not want. Treat them as a pair.
Use the raw value, with no money filter
Shopify stores prices as a whole number of cents, and that is what Cooee expects:
data-lc-price-v="{{ variant.price }}"— correct, renders as2999data-lc-price-v="{{ variant.price | money }}"— wrong, renders as$29.99
A formatted string cannot be read back reliably across currencies and locales, so a value with a money filter is ignored and the element is treated as untagged.
On a compare-at element use that element's own value, data-lc-price-v="{{ variant.compare_at_price }}". A product with no compare-at price renders this as empty, which is read as "no compare-at" and needs no guard.
Finding the price elements
Search your theme for the Liquid variables that render prices — product.price, variant.price, product.price_min, product.compare_at_price, and any money filter. Look in at least:
the product page section or template
product card / grid snippets, used by collections and recommendations
search results and any predictive-search template
quick view and quick add components
the cart drawer and cart line templates
any mobile-specific markup — many themes render prices twice
Adding the attributes
Put them on the element that contains the price text:
<span class="price-item price" data-lc-price-p="{{ product.id }}" data-lc-price-v="{{ selected_variant.price }}">{{ price | money }}</span>
<s class="compare-at-price" data-lc-price-cmp="{{ product.id }}" data-lc-price-v="{{ selected_variant.compare_at_price }}">{{ compare_at_price | money }}</s>
<span class="price-badge" data-lc-price-dis="{{ product.id }}">Save 20%</span>Inside a loop, the product variable is whatever the loop names it:
{% for item in collection.products %}
<span data-lc-price-p="{{ item.id }}" data-lc-price-v="{{ item.price }}">{{ item.price | money }}</span>
{% endfor %}Use the product ID for -p, -cmp and -dis — not the variant ID or handle. Use the variant price for -v, since that is the number on screen.
Where not to add them
Not checkout. The amount charged is applied by the Cart Transform Function on Shopify's side. Tagging is for display only.
Not cart totals or subtotals. Tag individual line prices if you want the cart to display test prices; totals are computed by the theme and by Shopify.
Not anything that is not a price — inventory counts, review scores, sizes.
Dynamically loaded content
Cooee watches the page for changes, so tagged elements added after load — quick view, infinite scroll, variant switching — are picked up without extra work. They still have to carry the attributes.
The value has to move with the price. When a shopper switches variant, whatever updates the displayed price must update data-lc-price-v too. Themes that re-render the section through Shopify get this for free, because the new markup comes from your Liquid. Themes that swap the price text in JavaScript from an embedded product JSON need the attribute updated in the same place. If it is missed, the price on screen belongs to one variant and the test adjustment is calculated from another.
4. Verify your tagging
On a product page, in the browser console:
document.querySelectorAll('[data-lc-price-p]').length
document.querySelectorAll('[data-lc-price-p][data-lc-price-v]').lengthBoth should be greater than zero, and the two numbers should match. A gap means some elements were tagged with the product but not the value, and those prices will not change.
Check the value looks like cents:
document.querySelector('[data-lc-price-p]').dataset.lcPriceV"2999" is right. "$29.99" means a money filter slipped in.
Repeat on a collection page, a search results page and a quick view, then switch variant on a product page and confirm the number changes. Check mobile widths too, since many themes swap markup.
5. Record what you changed
Keep a note of every file and line you touched. A theme update or a theme swap can silently drop these attributes, and the failure mode is quiet — the test simply stops changing prices in that place. This note is what makes recovery quick.
6. Cart Transform Function
Nothing to do. Cooee installs and activates it when you publish your first price test, and removes it when no price tests remain active. If it cannot be created, publishing fails safe — the display data is cleared too, so your storefront never shows a price checkout would not charge.
7. Check your products
Products must be active and published to the Online Store to appear in the product picker.
8. Know what will not pick up test prices
Cooee rewrites tagged elements on your storefront. These render prices elsewhere and will show your normal Shopify price:
email and SMS flows
sales channel feeds — Google Shopping, Meta, marketplaces
third-party apps that render their own prices from their own data
anything served from an aggressive edge cache
None of these break a test. They just will not reflect it.
Once tagging is done and verified, continue to Creating a price test.
