Skip to main content

Setting up price testing

One-time work per theme: confirm your plan, enable the app embed, and tag your price elements.

Written by Shashank Agrawal

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 price

  • data-lc-price-cmp="{{ product.id }}" — the compare-at / struck-through price

  • data-lc-price-dis="{{ product.id }}" — a discount or savings label

  • data-lc-price-v="{{ variant.price }}" — goes alongside -p and -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 as 2999

  • data-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]').length

Both 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.

Did this answer your question?