Skip to content
Bach.ai

How a 20%-Off Code Silently Moves Your Break-Even ROAS

You launched a 20%-off code, orders jumped, and your dashboard still shows a ROAS around 2.8. Looks healthy. The problem: at a 20% discount, 2.8 may now be a loss. The discount didn’t just shave your price — it quietly lifted the ROAS you have to clear just to break even, and almost no reporting surface tells you the target moved.

This is the common silent margin leak in promo-heavy accounts. Spend looks efficient against a number that is no longer the right number.

For the neighboring economics, compare Where Your Checkout Leaks: A Step-by-Step Drop-Off Audit and use Payment & Processor Fees: The 2-3% That Breaks Break-Even to validate the measurement decision.

Break-even ROAS is just inverted contribution margin

Break-even ROAS isn’t a marketing benchmark you inherit from a blog or a peer. It’s arithmetic, derived entirely from your unit economics:

Break-even ROAS = 1 ÷ contribution margin

Contribution margin here means the share of each order’s revenue left after every variable cost that scales with that order: cost of goods, pick/pack/ship, payment processing, and a realistic returns/refund reserve. It does not include fixed overhead, and it does not include the ad spend itself — that’s what the ROAS is measuring against.

If 40% of each order’s revenue survives as contribution, your break-even ROAS is 1 ÷ 0.40 = 2.5. Below 2.5 the incremental sales don’t pay back what you spent to acquire them. That’s the whole relationship: the lower your margin, the higher the revenue-per-spend you need.

A discount is a margin event, not a marketing event

Here’s where operators get caught. A discount feels like an acquisition lever — a thing you do to the campaign. Mechanically, it lands entirely on the margin line. Your cost of goods doesn’t fall when you cut the price. The discount comes straight out of contribution, and contribution is the denominator of break-even ROAS.

Walk a clean, illustrative example. List price 100, total variable cost 60, so contribution is 40 and margin is 40%.

Discount Price paid Contribution Contribution margin Break-even ROAS
0% 100 40 40.0% 2.50
10% 90 30 33.3% 3.00
20% 80 20 25.0% 4.00
30% 70 10 14.3% 7.00
40% 60 0 0% never

(These figures are a planning illustration, not a benchmark — plug in your own costs.)

Read the 20% row. The discount is 20 points off price, but break-even ROAS moves from 2.50 to 4.00 — a 60% jump in the bar you need to clear. At 30% off it more than doubles. At 40% off, the order breaks even on its own and no amount of ad efficiency can make it profitable; you’d be paying to lose money on every unit.

Why the target moves more than the discount

The move is non-linear, and that’s the part that ambushes people. Each point of discount removes a roughly fixed amount of contribution (your cost base doesn’t budge), but it removes it from a margin that’s already shrinking. So every additional discount point is a bigger share of a smaller pie. The break-even target doesn’t drift up gently — it accelerates.

This is why “we’ll just push a bit harder on a slightly deeper code” so frequently turns a profitable promo into a subsidy. The price cut feels arithmetic and gentle; the break-even response is convex and steep.

The measured-revenue trap

The second half of the trap lives in the dashboard. The platform reports the actual transaction value — the post-discount amount the customer paid, captured through the pixel and the conversions API. So your reported ROAS already reflects the haircut on the revenue side. The numerator is honest.

What’s stale is the target you’re comparing it against. You correctly see ROAS fall during a promo, shrug, and keep judging it against your everyday 2.5. But the bar quietly became 4.0. You’re holding a correctly-lowered actual up against an out-of-date threshold and reading “still above break-even” when you’re well under it. Nothing in the reported number is wrong. The reference point is.

Leakage makes the real number worse

Everything above assumes the discount only touches orders your ads actually drove. It seldom does. A sitewide or shared code gets applied to buyers who’d have paid full price, to organic and email orders, and to repeat customers who didn’t need the nudge. Coupon-extension behavior surfaces a code at checkout for shoppers who never went looking for one.

That means the margin compression isn’t confined to your paid cohort — it spreads across blended revenue. So your MER break-even (blended marketing-efficiency target across all revenue, not just attributed) rises too, not only your campaign-level break-even. If you only recompute the campaign number, you’ll still understate the damage. Watch the blended view to see how far the code leaked beyond the audience it was meant for.

There’s a slower, compounding cost as well: always-on or predictably-cadenced discounting trains buyers to wait for the code. Over time that drags your baseline contribution margin down structurally — which permanently raises break-even, promo or not.

Recomputing your discount break-even ROAS

The fix is a short, repeatable loop you run for every active code:

  1. Pin true pre-discount contribution margin. Use real landed costs — COGS, fulfillment, payment fees, returns reserve. Not the rosy gross-margin number from a pitch deck.
  2. Apply the discount to price, hold variable cost flat. Most of your cost base doesn’t move when price drops (payment fees scale slightly; COGS and fulfillment don’t). Recompute contribution and the new margin on the discounted price.
  3. Invert it. New break-even ROAS = 1 ÷ new margin. That’s the floor for the promo window.
  4. Add a buffer for your target. Break-even is the loss line, not the goal. Set the target ROAS above it by whatever covers fixed costs and the profit you actually want.
  5. Judge incrementality against the higher bar. The real question isn’t “did sales rise” — it’s “did the promo add enough new volume to clear the raised break-even, net of the buyers who’d have paid full?” Discounting that mostly subsidizes inframarginal orders fails this test even when revenue looks great.
  6. Track MER for leakage. If blended efficiency sags more than paid efficiency, the code is escaping its audience. That’s a structuring problem (gate it, make it single-use, or scope it tighter), not a bidding problem.

A read-only operator layer helps here because the recompute has to happen per promo, per margin, not once a quarter. This is the kind of drift Bach is built to catch — recomputing break-even on the discounted contribution margin and flagging the campaigns now running under the new floor. It surfaces the gap and waits for your call; it doesn’t quietly retune spend on its own.

The takeaway

Stop treating a discount as a campaign setting and start treating it as a margin event. Every point off the price compresses contribution and lifts your break-even ROAS — non-linearly, and by far more than the discount looks like on the sticker. Your dashboard will keep showing the post-discount revenue honestly while comparing it to a target that no longer applies.

Before the next code goes live, recompute the break-even at the discounted margin, set your target above it with a buffer, and check the blended number for leakage. The promo that “still looks profitable at 2.8” is frequently the one quietly costing you the most.

See what your Meta ads are really costing you.

Connect your account and Bach ranks every revenue leak in minutes — each with the money it costs and a one-tap fix. Free for 7 days, no credit card.

Start Free Audit
Start your free audit