← Back to Blog
Quantitative MarketingPromo EconomicsFinancial EngineeringPython

The Expected Value of a Promo: Why Your $20 Discount Nets $500, Not $13,500

A discount is not a cost of $20. It is a contingent payout you wrote, and most of it subsidises customers who were going to buy anyway. Here is the arithmetic, the breakeven conversion rate you have to clear, and the Python that finds it.

SPSantosh Paudel· July 22, 2026· 9 min read· 1 views
Table of contents

A promo is not a marketing expense. It is an option you wrote to your customer, and you are short it.

That distinction sounds academic until you price one. Send a $20 code to 10,000 people, lift conversion from 4% to 6.5%, and the campaign nets $500. Not $13,500. The gap between those two numbers is where most promo budgets go to die.

The short answer

The expected value of a promo is incremental gross margin minus total discount cost. Incremental margin comes only from buyers who would not have purchased otherwise. Discount cost is paid on every redemption, including the buyers who were always going to convert. When those two are close, the promo is a transfer, not a growth lever.

The worked example

Ten thousand people receive an email. Average order value is $120 at 45% gross margin, so a full-price order earns $54. The offer is $20 off. Baseline conversion is 4%. With the promo it reaches 6.5%.

LineValue
Margin per full-price order$54.00
Buyers without the promo400
Buyers with the promo650
Incremental buyers250
Incremental gross margin$13,500.00
Total discount cost$13,000.00
Of which subsidises buyers who would have bought anyway$8,000.00
Net$500.00

The campaign produced 250 additional customers and $13,500 of additional margin. It also handed $20 to all 650 buyers, and 400 of them were never in doubt. That is $8,000 of pure transfer, and it is 62% of the total discount spend.

Nothing here is a mistake in execution. The conversion lift was real and substantial: 4% to 6.5% is a 62.5% relative improvement, better than most email promos achieve. The offer still barely cleared zero, because the structure of a blanket discount guarantees that the people most likely to redeem it are the people least likely to need it.

The number to check before you launch

There is a single threshold that tells you whether an offer can work at all. Set incremental margin equal to discount cost and solve for the conversion rate the promo has to hit:

Let b be baseline conversion, x be promo conversion, M be margin per order, D be discount value. Breakeven is where (x - b) x M = x x D, which rearranges to:

x = (b x M) / (M - D)

For this offer: (0.04 x 54) / (54 - 20) = 2.16 / 34 = 6.3529%.

The promo delivered 6.5%. Breakeven was 6.3529%. The entire campaign rested on 0.147 percentage points, which is well inside the noise of a single send.

That is the number worth knowing before the creative is approved, because it is knowable before the creative is approved. It depends only on your baseline conversion, your margin, and the discount you are considering. All three are sitting in your data right now.

Why deeper discounts make this worse, not better

Look at the breakeven formula again. The discount D appears in the denominator. As D rises toward M, the denominator collapses and the required conversion rate explodes.

DiscountMargin after discountBreakeven conversionRelative lift required
$10$44.004.91%1.23x baseline
$20$34.006.35%1.59x baseline
$30$24.009.00%2.25x baseline
$40$14.0015.43%3.86x baseline
$50$4.0054.00%13.50x baseline

A $50 discount on a $54 margin needs you to convert more than half the list. No email campaign does that. The offer is arithmetically impossible before anyone writes a subject line, and you can see it in one line of code.

The model

Runs on the standard library. No dependencies.

def promo_ev(audience, aov, gross_margin, discount, conv_base, conv_promo):
    """Expected value of a blanket discount promo."""
    margin = aov * gross_margin
    buyers_base = audience * conv_base
    buyers_promo = audience * conv_promo

    incremental = buyers_promo - buyers_base
    incr_margin = incremental * margin
    discount_cost = buyers_promo * discount
    subsidy = buyers_base * discount

    # breakeven: (x - b)*M = x*D  ->  x = bM / (M - D)
    breakeven = (conv_base * margin) / (margin - discount) if margin > discount else float("inf")

    return {
        "incremental_buyers": incremental,
        "incremental_margin": incr_margin,
        "discount_cost": discount_cost,
        "subsidy_to_existing": subsidy,
        "net": incr_margin - discount_cost,
        "breakeven_conv": breakeven,
        "headroom_pts": (conv_promo - breakeven) * 100,
    }


r = promo_ev(10_000, 120.0, 0.45, 20.0, 0.040, 0.065)
for k, v in r.items():
    print(f"{k:24} {v:>12,.4f}")

Output:

incremental_buyers            250.0000
incremental_margin         13500.0000
discount_cost              13000.0000
subsidy_to_existing         8000.0000
net                          500.0000
breakeven_conv                 0.0635
headroom_pts                   0.1471

Point it at your own numbers. If headroom_pts is under about 0.5, the offer is inside measurement noise and you cannot tell a winner from a loser after the fact.

What to do instead of guessing

Three changes make the arithmetic work, and none of them involve a bigger discount.

Target the promo at people whose baseline conversion is low. The whole problem is the subsidy paid to certain buyers. If you can exclude the segment that converts at 12% anyway, you remove most of the transfer. A promo sent to a lapsed cohort with 1% baseline has a breakeven of 1.59%, which is a far easier bar than 6.35%.

Attach a condition that non-incremental buyers will not meet. A minimum basket above your current AOV, a bundle, a category they have not bought from. The condition is what turns a blanket transfer into something closer to a real option, because it moves the strike away from where the customer already was.

Measure against a holdout, not against last month. Baseline conversion is the single most important input to the breakeven, and seasonality will lie to you about it. A randomised holdout gives you the b in the formula. Without one, you are estimating the most sensitive parameter in the model by eye.

The general point

Every promo has a breakeven conversion rate implied by three numbers you already have. Calculating it takes about a minute. Not calculating it is how a campaign that lifted conversion by 62.5% ends up netting $500, and how a slightly deeper version of the same campaign ends up losing money while looking, in every dashboard, like a success.

The related mechanics get harder from here. A bonus with a wagering requirement is path dependent, so its cost depends on the whole sequence of a customer's balance rather than its endpoint. Points and cashback are a liability you carry on the balance sheet. Both are priced with the same three pillars, and both punish intuition more severely than a flat discount does.

Free resource

Get the Promo & Bonus Economics Workbook

Every formula for pricing a promo before you launch it: expected value, wagering cost, breakage, breakeven conversion. Worked examples with real executed numbers.

No spam. Unsubscribe anytime.

Browse all free guides →

Want to implement this with guidance?

Santosh helps founders turn insights like this into real systems.

Promo Economics Audit

External Resources

Further Reading & Tools

Related Posts

01
9 min
Risk ManagementPromo Economics
TodayQuantitative Marketing

Value at Risk and Kill Switches for Live Promotions

A spend cap set at expected payout shuts down 46% of perfectly healthy campaigns. The right multiple is 1.52x. Sizing exposure limits and automated kill switches against a real payout distribution.

Read article
02
8 min
Incentive DesignBehavioral Economics
TodayQuantitative Marketing

The Line Between Motivating and Manipulating: An Incentive Design Ethics Test

Every mechanic in this series works because of a cognitive bias. That makes them powerful and makes some of them indefensible. A six-question test for which side of the line your design sits on, and what regulators have already acted against.

Read article
03
8 min
Price DiscriminationPricing
TodayQuantitative Marketing

Why Promo Codes Beat Sales: Price Discrimination in Practice

A blanket 20% discount earns $20,000 less than no discount at all. The same discount behind a code that only bargain hunters bother to find earns $64,000 more. The friction is the entire mechanism.

Read article