case study · liquid · metafields · pricing

Promo pricing with an ownership guard

Background. A home-goods client ran rotating percentage promotions on curated product sets. Editing compare_at_price on hundreds of variants for every campaign wasn’t viable, and pricing apps fought their theme. The pattern that stuck: a sync writes promo_* metafields per product, and the theme renders sale pricing from them — one source of truth, no variant surgery.

How it works on the demo store. Six ceramics carry custom.promo_percentage: 20 plus custom.promo_owner_product_id, and a real automatic discount (20% off the same collection) backs them — so the price you see struck through on the collection page is exactly what checkout charges. The theme computes the promo in the price snippet and reuses the theme’s own on-sale markup, so promo pricing is visually indistinguishable from native sales. A date window (promo_starts_at / promo_ends_at) is honored when present.

The ownership guard — the part that earns its case study. When a merchant duplicates a product, Shopify copies its metafields. But the duplicate is not a member of the discount’s collection, so checkout won’t apply the promo. Without a guard, the duplicate’s product page advertises −20% and the checkout silently refuses it — a support ticket, or worse, a pricing-law problem. The fix is one field: the sync stamps promo_owner_product_id with the product it wrote to, and the theme suppresses the promo whenever that field names a different product:

assign promo_owner = product.metafields.custom.promo_owner_product_id.value
if promo_owner != blank
  assign self_gid = 'gid://shopify/Product/' | append: product.id
  if promo_owner != self_gid
    assign promo_active = false
  endif
endif

See the guard live. The demo store has the failure case staged: Ribbed Ceramic Vase shows −20% ($44.00 → $35.20). Its duplicate, Ribbed Ceramic Vase (Copy), carries the very same promo metafields — and shows no promo, because the guard catches the mismatch. Add each to the cart and walk to checkout to see the totals agree with what the pages promised.

← All case studies