ClearStock is live on the Shopify App Store.Install free →

← All blogs

Guides8 min read

Shopify sale price vs compare-at: what each does

Price is what customers pay; compare-at is the struck-through anchor. Field by field, how markets change the display, and the errors that stick.

InventoryX is in development and not available today. ClearStock is the live Shopify app.

On Shopify, price is what the customer pays and compare-at price is a higher number shown struck through beside it. That's the whole distinction, and it matters because those two facts have almost nothing to do with each other. Price drives the cart, tax, shipping thresholds, discounts, and every report you'll ever run. Compare-at drives one thing: whether a customer sees a "was" price. Get the two confused and you'll produce a storefront that looks discounted while charging full price, or one that charges a sale price with no visual evidence of a sale.

Here's what each field does, where the display logic actually lives, and the six mistakes that outlive the sale they were made for.

The field-by-field breakdown

Field What it does Affects checkout? Where it appears Set at
Price The amount charged for the variant Yes — cart, tax, shipping thresholds, discounts, revenue Product page, collections, cart, checkout, feeds, receipts Variant level
Compare-at price Display-only anchor, must be above price to render No Product page and collection cards, as a struck-through figure with a savings badge where the theme supports it Variant level
Cost per item Your unit cost, used for margin and profit reporting No Admin only (profit reports, margin columns) Variant level
Unit price Price per measurement (per 100g, per litre) No — informational display Product page, beside price Variant or product, depending on setup
Discount Reduces the amount charged at checkout Yes Cart and checkout, per the discount's settings Discount object, not the product

The line to memorise: compare-at never reaches checkout. Whatever you put there, the customer pays the price field. If your product page says "$80 struck through, $60" and the cart charges $60, that's price doing the work and compare-at doing the marketing.

How the strike-through actually renders

Shopify's storefront shows the compare-at price as a struck-through figure only when it's higher than the price. If compare-at is equal to or lower than price, it doesn't display — no error, no warning, just nothing. Themes then add their own layer: a "Save 25%" badge, a sale-colour price, a "Sale" label on the collection card. Those are theme features, not Shopify features, so what you see in a preview theme may not be what your live theme renders.

That produces a category of bug reports that aren't bugs: "the sale price shows but the old price is gone." Usually compare-at was never set, or was set below price, or the theme's sale badge only reads compare-at while the collection card reads price.

Two related details:

  • Both fields are per-variant. A product with six variants can have six prices and six compare-at values. Setting them at the product level in the admin is a convenience in some surfaces; the stored values are variant-level, and a new variant starts with neither.
  • Compare-at appears in product feeds. Google Shopping and similar channels read the compare-at field to determine whether a product is "on sale." A compare-at value left behind after a sale keeps advertising a discount that no longer exists — in the feed, not just the page.

Markets, currencies, and tax

Multi-market stores break naive assumptions here.

Markets and price lists. If you sell in several markets, your base price is one thing and each market's price can be another. Market price adjustments and price lists can override both price and compare-at, so a storefront in one currency can display a different pair of numbers than the admin shows. After any price edit, check one product per market — the base price is not the whole story.

Currency rounding. A converted compare-at and a converted price can round to numbers that produce an odd percentage, or to a compare-at that lands below price in a weak-currency market. If the anchor disappears in one market only, this is why.

Tax display. If your store displays prices tax-inclusive (common in the UK, EU, and Australia), both price and compare-at should be entered on the same basis, because the display doesn't tax-adjust the anchor — it shows what you typed. A compare-at entered ex-tax next to a price displayed inc-tax produces a "saving" that's partly VAT.

Reference-pricing rules. In several jurisdictions, showing a struck-through price implies it was your recent selling price, and rules on how long and how recently it applied vary. This isn't legal advice and the specifics depend on where you sell, but the practical habit is safe everywhere: only set compare-at for products genuinely being sold at a discount, and remove it when the discount ends.

Where discount apps fit

This is the source of most confusion about the two fields, because there are two different mechanisms in the market and they behave differently:

  • Price-editing tools write to the price and compare-at fields. The product page changes, the anchor appears, the cart charges the new price. Restoration depends entirely on the tool keeping your original values.
  • Discount-based tools leave price alone and apply a reduction at checkout through Shopify's discount system. The customer pays less, but the product page and collection cards still show full price — unless the theme or the app injects a display layer, which some do and some don't.

Neither is wrong. But if you set up a discount app expecting the product grid to show a sale price, you'll conclude it's broken when it's working exactly as designed. And if you use a price-editing tool and it doesn't restore, you'll be doing the cleanup described in restoring prices after a sale.

The six mistakes that stick

1. Setting compare-at equal to price. No display, no error, no clue. Half the "my sale badge doesn't show" questions end here.

2. Inverting the fields. Original price in the price field, sale price in compare-at. The customer pays full price on a page that says they're getting a deal. This one survives review because the page looks right.

3. Leaving compare-at on permanently. Every product reads as on sale forever. Customers stop believing the anchor, and in regulated markets you've created a reference-pricing problem.

4. Overwriting the MSRP. Compare-at held your manufacturer's suggested price; you replaced it with the pre-sale price; the MSRP is gone. If you use compare-at as a sale anchor, store the prior value somewhere else first.

5. Forgetting new variants. A seasonal colour added mid-sale has no compare-at and no sale price — it's full price on a page full of discounts, and nobody notices until a customer does.

6. Trusting the admin over the storefront. The admin shows what's stored; the storefront shows what the theme renders after market, currency, and theme logic. Only the guest test order reconciles all of it.

How to set a sale price correctly

The clean procedure for a price-based sale:

  1. Record the current price and current compare-at for every included SKU — export, don't retype.
  2. Set price to the sale price.
  3. Set compare-at to the original price, but only if it isn't already holding something meaningful; if it is, save that value first.
  4. Publish the change and verify on the storefront in each market, as a guest.
  5. Put the restoration date in a calendar with the export attached.
  6. On that date, put the original back in price and the original compare-at value back in compare-at.

Step 6 is the one that gets skipped, and its absence is visible for months. If you're running timed events repeatedly, scheduling the sale price covers the calendar structure that makes restoration automatic by habit rather than by memory.

Common questions

What's the difference between price and compare-at price on Shopify? Price is the amount charged and flows into checkout, tax, discounts, and reports. Compare-at is a display-only anchor that produces the struck-through "was" price and has no effect on what anyone pays.

Does compare-at price affect discounts or checkout? No. Discounts calculate from price. A discount percentage applies to price, and tax applies to the discounted price — compare-at is never part of the arithmetic.

Why is my compare-at price not showing? It only renders when it's higher than the price. If it's equal or lower, Shopify displays nothing. After confirming that, check whether the theme controls the display and whether a market price list is overriding the values on the storefront you're looking at.

Should compare-at price include tax? Enter it on the same basis as your price field. In tax-inclusive markets the storefront shows what you typed, so a compare-at entered without tax beside a tax-inclusive price overstates the saving.

Can I use compare-at price to show an MSRP? You can, and many stores do — but then it can't also serve as your sale anchor, because a sale overwrites it. If you need both, keep the MSRP elsewhere and use compare-at deliberately for one job at a time.

Next step: open three products in your admin and check both fields on each variant. If price equals compare-at anywhere, that anchor is doing nothing. If compare-at is set on a product that isn't on sale, that anchor is lying — and both are five-minute fixes today, versus a reference-pricing question later.