Blog·September 16, 2026

How to stop double discounts on sale items in Shopify

A double discount is a markdown and a code landing on the same item. Shopify allows it by default. Here's how to make it sale or code, never both.

A jacket lists at $120. You mark it down to $90 for the week. A customer arrives with FALL20, and the code takes 20% off $90, not $120. They pay $72. You thought you were running a $30 sale or a $24 code. You ran both, and gave $48.

That’s a double discount. Nobody set it up on purpose. It’s just how Shopify does the math.

What Shopify does with compare-at

To Shopify, the price is the price. The compare-at field draws the strikethrough on your product page and that’s the end of its job. A discount code takes its percentage or its dollar amount off whatever the current price is, and the discount editor has no setting that says “measure this against the original price instead.”

If you want a code to count against the original price, the fix has to happen somewhere else.

The native ways around it

Three of them, and each is fine for the right store.

Pause the sale during the promo. Restore the prices, run the code week, put the sale back. The code now takes 20% off $120, which is what you meant. This works well for stores whose sales are short and rare. It falls apart when the sale is permanent (a clearance collection that never goes away) or when a code is live all year in a welcome popup.

Keep the code away from sale items. Build the discount so it only applies to the collections that aren’t on sale. Clean, no app needed, and the honest answer for a lot of stores. The cost is upkeep: every time a product moves in or out of a sale you’re editing a discount’s collection list, and an order-level code can’t be scoped this way at all.

Block codes on sale-heavy carts. PromoLock’s Controller has a lock for this (how it works). The code is rejected when the cart is mostly markdowns. Strong protection, but the customer sees a rejection, and some of them leave.

None of these give you the thing the customer would find most reasonable: the code works, on everything, and you never pay out on top of a markdown.

Sale or code

Every discount you build in PromoLock has an On-sale items setting under Margin guards. A new discount ships with it on No discount, which keeps the code off marked-down lines entirely. The setting this post is about is the middle one, Sale or code.

The idea in one line: whichever saves more, not both.

The markdown the sale already gave counts toward the code. The customer gets the code measured against the original price, and if the sale was already worth more than that, the code adds nothing. Back to the jacket:

Code on the $120 jacket, marked down to $90 Code off the original Sale already gave Code adds
20% off $24 $30 $0
30% off $36 $30 $6
50% off $60 $30 $30
$25 off $25 $30 $0

Full-price items in the same cart get the full code as usual, and where a product discount is limited to a number of items (cheapest one free, say), full-price items take those slots before sale items do. Fixed-price offers (“this item for $50”) aren’t affected, since they already name an exact price.

The promise you can print is short: 20% off the original price, sale items included. No fine print about exclusions, no rejected codes at checkout, and no line where a markdown and a code both land.

What it changes for the customer

Be straight about this part. Under Sale or code, a customer with a 20% code and a cart full of 25%-off clearance sees their code apply and the total not move. To them that can look like a broken code, and “20% off the original price” in the promo copy is worth adding for exactly that reason. If the feeling of a discount landing matters more to you than the arithmetic, the two-rate setup (full rate on regular items, a small rate on top of the markdown) is the better fit. It costs a little more per sale item and never leaves a customer wondering.

And if your sales are rare and short, pausing them for a code week is still the simplest answer of all. This setting earns its place on stores where markdowns and codes are both always live.

Setting it up

  1. Open the discount in Discounts, or create one.
  2. In the right rail, under Margin guards, set On-sale items to Sale or code.
  3. Leave Skip gift cards on and set Cap total discount if the offer has more than one part.
  4. Save. The math runs inside Shopify’s checkout from then on, so nothing in the theme changes.

The setting lives on the discount, so an old code built in Shopify’s own editor doesn’t get it. Recreate that code in PromoLock with the same rate and it will.

Check what it was costing you

PromoLock’s Analytics has a sale-item loss report: every dollar a code took off a line that was already marked down, from your own order history. Switch a discount to Sale or code and that number should drop for it over the next month. If it doesn’t, another code is still reaching your sale items, and the top-discounts list will name it.

Loss calculator

Estimate your unintended loss.

Four quick questions. Planned promotions never count.

?$3.5M
Which of these are true for you?
?
?
?
?