Blog·August 4, 2026

How to control discounts on sale items in Shopify

Blocking codes on sale items protects margin but costs conversions. A two-rate discount (full rate on regular items, a token rate on markdowns) does both jobs.

Blocking discount codes on sale items is the standard fix for the double-discount problem, and it works. But it has a cost nobody puts on a dashboard: the customer whose code “doesn’t work” at checkout, who was maybe going to spend $150, and who closes the tab instead.

If codes are part of how your brand sells, there’s a smarter shape for this. Don’t block the code on sale items. Shrink it.

All items 20% off. Sale items 5% off. One code.

The customer’s code always works. You just decided in advance what it’s worth on each side of the markdown line. The double-dip still happens, technically, but at a rate you priced in, and a rate you priced in is a plan rather than a leak.

Why this converts better than blocking

A rejected code feels like a broken promise, even when the fine print was on your side. A code that applies, but applies modestly to clearance items, feels like it worked. The customer sees a discount land; you see 5% instead of 20% on the lines that were already marked down 30%.

For stores where a big share of traffic arrives holding a code (from email, from an influencer, from a welcome popup), that difference is real revenue. The all-or-nothing lock trades those checkouts away for margin. The two-rate version keeps both.

How to build it in PromoLock

The whole thing lives inside one discount, using cart groups with a sale-status filter. No collections to maintain, no product tagging. The split happens live at checkout based on each item’s price versus its compare-at price.

  1. Create your discount in PromoLock (code or automatic).
  2. Open SafeGuards and untick Skip on-sale items. This matters: it’s on by default, and while it’s on, sale items are removed before your offer ever sees them, so a sale-item rate would have nothing to apply to. The sale-status filter doesn’t even appear until this is off.
  3. Create two cart groups. Group one, call it Full-price items: turn on Filters, tick Sale status, choose Only full-price items. Group two, Sale items: same filter, Only items on sale. Leave the catalog pickers empty on both. The filter alone splits the entire cart, and every item lands in exactly one group.
  4. In the offer, add two product discounts: 20% aimed at Full-price items, 5% aimed at Sale items.
  5. Set Cap total discount amount so even a giant mixed cart has a ceiling.

Because the groups are computed from live prices, the setup maintains itself. Mark a product down tomorrow and it moves to the 5% side on its own. Restore the price and it moves back.

One thing to switch off

If you’ve been running PromoLock’s sale-items lock in the Controller, turn it off before launching this. That lock blocks all codes on sale-heavy carts, including your carefully built two-rate one. The lock and the two-rate discount are two answers to the same question, so pick one.

And keep the stacking lock on. The two-rate discount prices in the dip; a second code stacked on top un-prices it.

Which stores should still just block

There is another side to this. If your sale prices are final-final, if you run deep clearance where even 5% on top hurts, or if codes are rare on your store anyway, the plain block is simpler and there’s nothing wrong with it. The two-rate structure earns its keep when code usage is high and checkout abandonment has a price.

What to watch afterwards

In PromoLock’s analytics, the sale-item loss report won’t go to zero under this policy, and that’s correct, because the 5% is planned spend now. What you want is a line that stays low and doesn’t trend anywhere. If it starts climbing, some other code is reaching your sale items ungoverned, and the report’s top-discounts list will tell you which one.

Loss calculator

Estimate your unintended loss.

Four quick questions. Planned promotions never count.

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