Marketing mix modelling
Work adstock and saturation by hand, read each coefficient's interval against zero and break-even, and say what a mix model cannot know.
On this page
A marketing mix model regresses weekly sales on weekly spend by channel, alongside the things that move sales without any ad: the season, price changes, promotions, a trend. It needs no clicks and no user-level tracking, so it sees the podcast and the billboard that attribution cannot, and it covers every channel at once. Its limit is the data. It can separate only the effects that the spend history separated.
The regression, and what it needs
The model, in one line:
weekly sales = base + season + price + Σ over channels of effect × response(adstock(spend)) + noise
Each channel brings three numbers to estimate: its effect, how long its spend keeps working (adstock), and how fast its returns flatten (saturation). Five channels make fifteen; add ten for season, price and trend and there are about 25 numbers to learn. Two years of weekly data is 104 observations, roughly four per number. That is why two years is the usual minimum, why the open-source models start from priors (stated assumptions about each number that the data then updates), and why the intervals are wide.
What the model can recover is the effect of a channel whose spend went up and down independently of the others and of the season. Three common histories defeat it:
- Channels that moved together. If social and search were both doubled every November, the model has no way to split the November sales between them. It may hand one of them all the credit, or give both wide intervals.
- Spend that followed demand. If search spend rises because more people searched, the model credits search with demand it merely followed, the same trap brand search sets for attribution.
- Spend that never varied. A channel run at $40,000 every week for two years has no variation to learn from, so its estimate is mostly the prior.
The fix for all three is deliberate variation: change a channel's spend on purpose, by region or by period, so the data contains the contrast the model needs.
Adstock: spend keeps working after the week it is paid
An ad seen this week still nudges a purchase next week, at a fraction of the strength. Adstock models that with a decay rate. At a decay of 0.5, $10,000 spent in week 1 counts as $10,000 that week, $5,000 of effective spend in week 2, $2,500 in week 3, and so on, halving each week:
10,000 + 5,000 + 2,500 + 1,250 + ... = 10,000 ÷ (1 − 0.5) = $20,000 of effective spend
Half the effect lands after the week of spend. A model without adstock gives those later sales to the base or to whichever channel spent in those weeks, so it undervalues channels with long carryover, such as a podcast or video, and flatters channels whose effect is immediate, such as search. The decay is itself estimated, and it matters: at 0.7 the same $10,000 becomes $10,000 ÷ 0.3 ≈ $33,000 of effective spend.
Saturation: the second $100k returns less than the first
The first dollars in a channel reach the most responsive people; later dollars reach the same people again or reach people less likely to buy. Assume a channel's return halves with each further $100,000 a month: the first $100,000 buys 400 orders at $250 each, the second 200 at $500, the third 100 at $1,000. At $200,000 a month the average is 600 orders, $333 each, but the last $100,000 cost $500 an order.
The model fits a curve of this shape for every channel, and the allocation decision lives on the curve, not in the average. Money should move from the channel where the next $1,000 buys least to the one where it buys most, until the two are equal. A channel's average return over its current spend always overstates what its next dollar buys. Paid media basics prices the same flattening from the media side, as rising frequency.
Reading the coefficient table
A model's output is a table of returns with intervals. Assume it reports, for orders per $1,000 of spend at current levels:
- Search: 3.2, with a 95% interval of 2.1 to 4.3
- Social: 1.1, with a 95% interval of −0.4 to 2.6
Each order brings $400 of contribution, so break-even is $1,000 ÷ $400 = 2.5 orders per $1,000. Read each row against two lines, zero and break-even.
Search clears zero comfortably, and its point estimate is above break-even, but the lower end, 2.1, is below it: search probably pays at current spend, not certainly. Social's interval crosses zero, so the model cannot say social works. It also reaches 2.6, above break-even, so the model cannot say social fails. What the row says is that this history cannot tell, usually because social's spend moved with search or with the season. Cutting social on this table is a decision taken on no evidence. The next step is an experiment on social, whose result goes back into the model as calibration and narrows the interval.
The open-source references
Two documented open-source mix models are the reference implementations: Robyn (opens in a new tab), from Meta's marketing science team, and Meridian | Google for Developers (opens in a new tab). Both model carryover and saturation (Key Features | Robyn (opens in a new tab); Meridian | Google for Developers (opens in a new tab)), and both document calibrating the model with experiment results. Both also come from companies that sell advertising, which is a reason to keep the experiments that calibrate them in your own hands.
Feeding one is unglamorous: spend by channel by week from each platform, orders from your own systems, prices and promotions from the finance calendar, joined on the week and refreshed by a weekly job. That is a batch pipeline, and batch versus stream says why nothing about it needs to be real-time.
In practice
To the analyst or vendor who delivers the model, ask four things: an interval on every return; the adstock decay per channel and how the results move if it changes; which channels' spend varied independently in the history; and which experiments calibrated it. A table of point estimates with none of these is a ranking of opinions.
To the CFO, say what the model is for: splitting next quarter's budget across channels, at the margin. It is not proof that any one channel works; that is an experiment's job.
The mistake that costs money is cutting a channel because its interval crosses zero. "The model cannot say it works" is not "it does not work", and the cut removes the spend variation, and often the demand, that the next model needed.
Check yourself
1. A $30,000 podcast flight runs for one week, and its adstock decay is 0.6. How much effective spend lands after the flight ends, and how long after it should a geo test keep counting sales?
Total effective spend is $30,000 ÷ (1 − 0.6) = $75,000, so $45,000, 60% of the effect, lands after the week of spend. The share counted after k weeks is 1 − 0.6^k, which passes 90% at k = 5. Count for at least four weeks after the flight, or the test misses a large part of what it is measuring.
2. A channel spends $200,000 a month on the halving curve above, averaging $333 an order. Break-even is $400 an order. Do you hold its budget, raise it or cut it?
Cut it. The average is under $400, but the second $100,000 costs $500 an order, so the last dollars lose money. Read as a smooth curve whose marginal return halves every $100,000, the next $1,000 costs $400 at about $115,000 a month; trim toward that, and confirm with a lower-spend period in a few regions before cutting further.
3. Search reports 3.2 orders per $1,000 (2.1 to 4.3) against a break-even of 2.5, and its owner asks for 30% more budget. Approve?
Not the whole 30%. The interval dips below break-even, and 3.2 is an average at current spend, so the extra 30% earns less than 3.2. Approve 10% in half the regions for six weeks and compare them with the other half; the test answers the question the coefficient cannot.