Case study · commercial analytics · five minutes

Was the promo worth it?

Every grocery store runs promotions. Fewer check whether they made money. I took two years of store data, scored all 317 promotions against what each line would have sold anyway, and followed the margin all the way through.

The answer: shoppers bought 47% more on promotion, but only 5% of promos paid their way. Over two years they cost $10,154 of margin, and the biggest cost was not the extra units: it was the $8,934 discount given on units that would have sold at full price anyway.
Python · pandasbaseline modellingcannibalisationprice responsebasket analysisCRISP-DMsynthetic data

1 · The question behind the question

A store owner asks "how did the promo go?" and usually hears "we sold heaps". Units are the wrong scoreboard. The real question is: did this promotion leave the store with more margin than not running it?

Who needs the answer

What success looks like

A keep, change or stop call for every line, a funding ask for the supplier, and a weekly short list of actions, all traceable to the numbers.

2 · What the data could and couldn't say

68,829daily sales rows by line and channel
50lines in 11 categories
317in-store promos, ~3 days at ~20% off

What I checked first

3 · The baseline: what would have sold anyway

Everything hinges on the counterfactual. For each promo day, the baseline is the average units on the same weekday over the four weeks before, with promo days left out, so one promotion can't inflate the next one's baseline.

baseline = units.where(promo == 0) # promo days don't count .shift(1) # only the weeks before .rolling(4, min_periods=2) # four same weekdays .mean() # per line, per weekday

Both actual and baseline margin use the same list unit cost, so the comparison is like for like.

4 · Following the margin all the way through

Each promotion's result splits into four parts. Added up across all 317:

+$4,103
−$8,934
−$3,551
−$1,773
−$10,154
Margin on the extra unitsDiscount on units that would have sold anywayTaken from other lines in the categoryThe dip in the 3 days afterNet

Why it loses

A 20% discount on a line with about 27% margin leaves about 9% margin per unit. To stand still, the promo needs roughly three times the usual sales. It got 1.47 times.

Two more models

5 · How I know the numbers hold

What it can't tell you yet

6 · From analysis to Monday morning

The model runs inside Shelly, my open-source analytics agent, so the answer is a working tool, not a slide:

This week's actions it produced

With real data, next

Add supplier funding, run promotions as a simple test (alternate weeks or stores) to measure lift cleanly, and use real receipts for baskets.

Open the Commercial lab in Shelly ↗ · Source on GitHub ↗