Media mix modelling: adstock, saturation and where the next pound goes

Attribution reports are honest about the clicks they can see and blind to everything else. At my demo hamper shop the report hands 61 percent of revenue to paid search and nothing to the printed catalogue, even though branded searches jump by a third the week the catalogue lands. Media mix modelling works the other way round: it takes two years of weekly totals, gives every channel a memory through adstock, a curve of diminishing returns through saturation, and separates the channels that create demand from the ones that collect it. The output is not a credit split but a marginal ROI per channel, the revenue the next pound would bring, with an interval around it. I walk through the maths, fit the model to 104 weeks at The Gift Bow, and show the reallocation that moves 15 percent of budget out of search and into social and email with a projected lift, then explain how a geo test keeps the model honest. It needs no user level tracking at all, which is increasingly the point. This is part 16 of 21 of the Marketing Analytics series.

The catalogue that does nothing and the search campaign that does everything

Every January at The Gift Bow, my Solidus demo hamper shop at hampers.keferboeck.com, I sit down with two years of weekly numbers and the same argument breaks out in my head. The attribution report says paid search delivered 61 percent of tracked revenue, paid social 14 percent, email a respectable 18 percent because the click lands on a tagged link. The printed catalogue, which goes to 40,000 households in early October and again in late November, gets precisely nothing, because nobody clicks on paper.

I know that is wrong. The week after the catalogue lands, searches for "gift bow hampers" jump by a third, and paid search takes the credit for demand a mailing created. I can also see that the search line has flattened: we doubled the budget in the second autumn and search revenue rose by a fraction of that. Something is saturating, something is carrying over, and something is feeding something else. Attribution cannot see any of it, because it only knows about clicks it can follow.

Media mix modelling, MMM for short, is the method for this situation. It works top down, on weekly totals, with no user level tracking, and it answers the question finance actually asks: if I move the next pound from here to there, what happens to revenue? The numbers in this chapter are illustrative, but the shape of the problem is the one I meet in every account with more than two channels.

Where this sits in the series

This is chapter 16 of 21 and we are in part four, media and loyalty, chapters 15 to 19. The previous chapter, Modelling the value of marketing communications, asked what a message is worth once it has landed; this one asks what a channel is worth once you account for memory and diminishing returns, and where the next pound should go. The next chapter changes register and moves to the customer side with Loyalty: the three Rs, the spectrum, and designing earn and burn.

What MMM answers that attribution cannot

Attribution asks: of the sales we can trace to a person, which touchpoints were on the path? MMM asks: of all the sales we made this week, how many would we not have made without each channel? The first is bookkeeping about tracked journeys. The second is a causal question about aggregate outcomes.

That gives MMM three practical advantages. It sees channels that do not produce clicks: catalogue, radio, out of home, a sponsorship. It sees interaction between channels, so it can tell you that a good share of your branded search is created upstream. And it needs no cookies, pixels, consent banner or user identifiers, because its input is a table with one row per week. I have written elsewhere about privacy first growth hacking and MMM is the most privacy friendly measurement method I know: the most personal thing in the dataset is the weather.

The price is resolution. MMM cannot tell you which ad, audience or keyword worked. It tells you what the channel did at the level of weekly spend, with an error margin, and it needs history: two years of weekly data is the sensible minimum, and 104 weeks is what The Gift Bow gives me. The keyword level view belongs in the search account, and I have covered how long tail keywords drain a budget separately. MMM sits above that and decides how big each bucket should be.

Adstock: advertising has a memory

The first idea that separates MMM from a naive regression of sales on spend is carryover. A catalogue that lands on a Tuesday sells hampers for six weeks. A social campaign builds recognition that pays out after it has stopped. Even a search click has a tail: the visitor bookmarks the page and orders on payday. Regress this week's sales on this week's spend and you get the timing wrong and underestimate slow channels.

Adstock fixes this by replacing raw spend with a stock that decays. The simplest and, in my experience, most robust version is the geometric recursion:

At=xt+λ At−1,λ=0.51/hA_t = x_t + \lambda \, A_{t-1}, \qquad \lambda = 0.5^{1/h}

Here AtA_t is the adstock in week tt, xtx_t is the spend or the impressions in that week, λ\lambda is the retention rate between 0 and 1, and hh is the half life in weeks, the time it takes for the effect of a burst to fall to half. I talk to clients in half lives, never in λ\lambda, because "the catalogue has a five week half life" is a sentence a managing director can argue with, and "lambda is 0.87" is not.

The chart shows a single burst of 100 in week 0 and nothing afterwards, for a channel with a one week half life and one with a four week half life.

Two decay curves: half life of one week (fast) and four weeks (slow). The slow channel is still doing a quarter of its work eight weeks later.

The recursion is cousin to the distributed lag models of chapter 5. A polynomial distributed lag lets the tail take any smooth shape, including a hump where the effect peaks a week or two after the spend. Geometric adstock forces the peak into the spending week. With 104 weeks and four channels I almost always prefer the geometric version, because it costs one parameter per channel instead of three or four, and the data rarely supports more. If a client insists that their TV takes two weeks to peak, I add a peak parameter and say honestly that the peak is a prior as much as a finding.

Saturation: the second pound is worth less than the first

The second idea is diminishing returns. Doubling paid search spend does not double the clicks, because the good keywords are already bought and the extra money goes into weaker positions and broader matches. Doubling email frequency does not double revenue, because your list is finite and fatigues. Every channel has a curve, and the curve is what makes allocation a real question instead of "spend it all on the channel with the best average ROI". I have argued at length that marginal ROI beats average ROI; MMM is the machinery that estimates the marginal number.

The curve I use most is the Hill function:

S(A)=AαAα+KαS(A) = \frac{A^{\alpha}}{A^{\alpha} + K^{\alpha}}

SS is the saturated response between 0 and 1, AA is the adstock, KK is the half saturation point, the adstock level at which half of the maximum effect is reached, and α\alpha controls the shape: values near 1 give a concave curve that bends from the first pound, values above 1 give an S shape that starts slowly, accelerates, then flattens. A catalogue follows the S shape, because the first 5,000 copies barely register. Search follows the concave curve, because the first pound buys your best keyword.

A simpler alternative is the logarithmic form S(A)=ln⁡(1+A/K)S(A) = \ln(1 + A/K), which never fully saturates. It is easier to fit and harder to defend when a client asks "so there is no limit?". I use it when the data is thin, and say so.

The response for one channel is then βc Sc(Ac,t)\beta_c \, S_c(A_{c,t}), where βc\beta_c is the maximum weekly revenue the channel could ever add. The full single equation model is:

yt=β0+∑cβc Sc(Ac,t)+∑kγk zk,t+εty_t = \beta_0 + \sum_{c} \beta_c \, S_c(A_{c,t}) + \sum_{k} \gamma_k \, z_{k,t} + \varepsilon_t

yty_t is revenue in week tt, β0\beta_0 is the baseline, the revenue you would make with no media at all, the first sum runs over the channels, the second over control variables zz such as seasonality, promotions, price changes and bank holidays, with coefficients γk\gamma_k, and εt\varepsilon_t is the noise. The controls are not decoration. At The Gift Bow the eight weeks before Christmas make 55 percent of the year, and if the model does not know that, it hands Christmas to whichever channel spent most in November, which is search.

0k2k4k6k0k7k14kWeekly spend in poundsWeekly revenue in poundsPaid searchPaid socialfilled dot: todayhollow dot: after the shiftResponse curves, steady state, illustrative

Illustrative response curves for paid search (pink) and paid social (blue) at The Gift Bow. Search sits far up its curve; social is still on the steep part.

When channels feed each other

The single equation quietly assumes that each channel's spend is set independently of the others and of sales. At The Gift Bow neither holds. Search spend is largely set by the auction, and branded queries rise when the catalogue lands or a social campaign runs, so search spend goes up because the other channels worked. Sales push spend too, because the shop tops up budgets in good weeks. That is the simultaneity problem of chapter 11 wearing a media hat, and the honest fix is a second equation:

xsearch,t=δ0+δ1 Asocial,t+δ2 Acat,t+δ3 yt−1+utx_{\text{search},t} = \delta_0 + \delta_1 \, A_{\text{social},t} + \delta_2 \, A_{\text{cat},t} + \delta_3 \, y_{t-1} + u_t

Search spend in week tt is explained by the adstock of social and the catalogue, by last week's sales, and by its own noise utu_t. Estimating the two equations together, or using predicted search spend in the sales equation, strips out the part of search that was merely collecting demand made elsewhere. In the Gift Bow data roughly 30 percent of the apparent search effect moved to social and the catalogue once I did this. It is the biggest single correction in the exercise, and most off the shelf MMM tools skip it.

The worked example: 104 weeks at The Gift Bow

Four channels, two years, weekly revenue averaging £38,000 with a baseline of £17,600 that the shop would make with no media at all. Total weekly media budget is £8,000. I fitted geometric adstock, Hill saturation, controls for Christmas, two promotion weeks, one price change and a week of site trouble, and a second equation for search spend. The estimates are illustrative but they are the shape of what came out.

ChannelAvg weekly spendHalf lifeRetention λHalf saturation KShape αMax effect βModelled weekly revenueAverage ROI
Paid search£4,0000.6 weeks0.312,8001.3£9,500£6,8601.72
Paid social£2,0002.0 weeks0.719,0001.6£17,000£6,6503.33
Email£7001.0 week0.502,6001.5£7,000£1,9802.83
Catalogue£1,3005.0 weeks0.872,0002.2£5,000£4,8603.74

Reading it line by line. Paid search has a half life of 0.6 weeks: the effect is gone by the following week, which fits a channel that harvests demand rather than creating it. Its steady state adstock of about 5,800 is well past its half saturation point of 2,800, so it runs at 72 percent of its maximum effect. Its average ROI of 1.72 in revenue per pound looks acceptable until you remember that hamper gross margin is 45 percent, so a pound needs to bring back £2.22 in revenue just to break even. The average is already below that line.

Paid social has a two week half life, an S shape with α of 1.6, and a half saturation point far above its current adstock; it runs at 39 percent of its maximum. Email, once you strip out the clicks that were coming anyway, adds about £1,980 a week from £700 of tooling and creative cost, at 28 percent of its maximum. The catalogue looks superb on average ROI, 3.74, and terrible on anything marginal: at 97 percent of its maximum it is fully saturated at the current print run, which is what I would expect from a channel that only varies twice a year. I come back to that under pitfalls.

Now the number that decides where the money goes. Marginal ROI is the derivative of revenue with respect to spend, evaluated where you stand today:

mROIc=∂y∂xc=βc⋅αc Kcαc Acαc−1(Acαc+Kcαc)2⋅11−λc\text{mROI}_c = \frac{\partial y}{\partial x_c} = \beta_c \cdot \frac{\alpha_c \, K_c^{\alpha_c} \, A_c^{\alpha_c - 1}}{\left(A_c^{\alpha_c} + K_c^{\alpha_c}\right)^2} \cdot \frac{1}{1 - \lambda_c}

The first factor is the channel's maximum effect, the middle one is the slope of the Hill curve at the current adstock, and the last converts a permanent one pound change in weekly spend into its steady state change in adstock, because a pound spent every week accumulates to 1/(1−λ)1/(1-\lambda) pounds of stock. The unit is revenue per additional pound per week, sustained.

ChannelSpend beforeMarginal ROI beforeSpend afterMarginal ROI afterRevenue beforeRevenue after
Paid search£4,0000.62£2,8001.04£6,860£5,900
Paid social£2,0003.24£2,8002.42£6,650£8,910
Email£7003.05£1,1002.35£1,980£3,060
Catalogue£1,3000.23£1,3000.23£4,860£4,860
Total£8,000£8,000£20,350£22,730

The reallocation moves 15 percent of the budget, £1,200 a week, out of paid search and into social (plus £800) and email (plus £400), and leaves the catalogue alone because you cannot change a print run in March. The last pound in search was returning 62 pence of revenue, which at a 45 percent margin means every extra pound destroyed about 72 pence of profit. After the shift, search sits at 1.04 and the two receiving channels come down to 2.42 and 2.35. The projected lift is about £2,400 a week in revenue, roughly 12 percent of the media driven revenue and just over £120,000 a year, for the same budget. The 80 percent interval around that lift runs from about £900 to £3,600 a week. Both numbers go in the memo. A lift without an interval is a slogan.

Two things I would say to the board. First, the model still wants to move more out of search, since 1.04 is below break even, and I stop at 15 percent on purpose: the curves are only trustworthy where the data has actually been, and search has never been below £2,800 a week in these two years. Move, measure, refit, move again. Second, equalising marginal returns across channels is the goal, not maximising any one channel's average. The three movable channels end up between 1.0 and 2.4 instead of 0.6 to 3.2, and that is what an efficient budget looks like.

A plain Bayesian note

With 104 weeks, four channels, adstock and saturation parameters for each, plus controls, I am fitting fifteen to twenty parameters on a hundred data points, most of them quiet summer weeks. Least squares will happily give me a catalogue half life of 40 weeks or a negative email coefficient if the noise falls that way. So I fit these models Bayesian, and the idea is less exotic than the word. Before I look at the data I write down what I believe: email carryover is short, a half life between half a week and two weeks; catalogue carryover is long, three to eight weeks; every channel's effect is positive. Those are priors. The data pulls the estimates away from them as far as the evidence justifies, and what comes out is a distribution for each parameter rather than a single number. That is where the interval on the lift comes from. The priors are printed in the appendix, so the client can see how much of the answer was mine and how much was the data's.

How MMM and incrementality tests fit together

An MMM is a model of history and inherits every quirk of it. A geo holdout test, where you switch a channel off in a few postcode areas or Austrian districts for four weeks and compare against matched areas, is a measurement of the present. They need each other. The test gives one clean, causal number for one channel at one spend level. The model spreads that knowledge across all channels and spend levels, and tells you which test is worth running next.

The loop I run: model, test the shakiest channel, feed the test result back in as a prior, refit, decide.

At The Gift Bow the shakiest number was search, so that is the channel I would test first: pause search in a fifth of the UK by postcode district for four quiet weeks and watch total revenue, not search revenue. If the measured lift lands inside the model's interval, the model gains credibility. If not, the model was wrong and I would rather know.

Running it yourself

You need one row per week with revenue, orders, spend per channel (or impressions where spend is lumpy), catalogue drop dates, a Christmas indicator or a smooth seasonal term, promotion flags, average selling price, and any events you know moved the business. Two years minimum; three is better, but only if the business has not changed shape in between. The first pass takes me about two weeks: three days assembling and checking the data, always the longest part, a week fitting and stress testing, two days writing the memo.

The core transformation is ten lines of Python:

import numpy as np

def adstock(x, half_life):
    lam = 0.5 ** (1 / half_life)
    a = np.zeros_like(x, dtype=float)
    for t in range(len(x)):
        a[t] = x[t] + (lam * a[t - 1] if t > 0 else 0.0)
    return a

def hill(a, K, alpha):
    return a ** alpha / (a ** alpha + K ** alpha)

search = 9500 * hill(adstock(spend["search"].values, 0.6), 2800, 1.3)

Fit the nonlinear model with a probabilistic library such as PyMC or Stan, or with the open source MMM packages from the large platforms, which are decent as long as you understand that their default priors are opinions. Whatever you use, four checks before you trust it. One: hold out the last twelve weeks, fit on the rest, and see whether the model predicts them within ten percent; if it cannot forecast, it cannot allocate. Two: plot residuals over time and look for structure, especially around Christmas; structure means a missing control. Three: every half life and saturation point should be a number you could explain to the channel owner without embarrassment. Four: compare the implied lift for at least one channel against a real test, and if you have never run one, run one.

Pitfalls

Channels that move together. At a hamper shop every channel spends more in November. When search, social and email rise and fall together, the model cannot tell them apart and the coefficients trade off: one channel gets too much, another too little, and the total is fine. The cure is variation you create deliberately, a month where social is up and search is flat, plus priors that stop the estimates wandering. Collinearity is why MMM results sometimes flip between refits, and a client should hear that before it happens.

Channels that never vary. The catalogue in my example only changes at two drop dates a year, so the model knows what a mailing does versus no mailing and knows nothing about 30,000 copies versus 40,000. Its marginal ROI of 0.23 is a number computed from a curve fitted mostly by prior. Do not reallocate on a channel whose variation you have not observed; test it instead.

Small data dressed as big data. A hundred weekly rows is a small dataset, however many gigabytes of raw clicks sit behind it. Daily data looks like more, but day of week noise and the delay between click and order usually make it worse. Be suspicious of any MMM that reports coefficients to three decimal places with no interval.

Seasonality eating the media effect, or media eating the season. Too flexible a seasonal term absorbs the Christmas lift that the catalogue and search created. Too little and the media coefficients inherit Christmas. I fit both and show the client how much the answer moves; if it moves a lot, the data cannot separate the two and I say so.

Believing the curve outside the data. The Hill curve is a smooth guess about spend levels you have never tried. It predicts what happens at zero search spend, but nobody has run zero search spend, so treat the far ends of every curve as a hypothesis. That is why the reallocation stops at 15 percent.

Attribution and MMM disagreeing, and picking the comfortable one. They will disagree, usually with attribution flattering search and MMM flattering whatever creates demand. The disagreement is information, not a bug, and the wrong response is to average the two.

How I do this for clients

The deliverable is a decision memo with a number and a risk, not a model file. It reads something like: move 15 percent of the weekly budget from paid search into paid social and email, projected lift £2,400 a week with an 80 percent interval from £900 to £3,600, biggest uncertainty is the search coefficient, recommended geo test to resolve it, refit in twelve weeks.

It starts with the free workshop, where we list your channels, work out whether you have two years of weekly spend and revenue that can be trusted, and agree the one question the model must answer. Then I do two weeks of real work at my own risk: I assemble the weekly table from your ad accounts, email platform, shop or CRM and finance exports, fit the model with priors we have discussed, run the holdout checks, and write the memo. If you do not think it was worth it, you owe me nothing and keep the table and the code.

If we continue, you get the model as a repository you own, a one page dashboard that answers "where should next month's budget go" and nothing else, a quarterly refit, and a testing plan that tightens the shakiest channel each quarter. Because I also run campaigns, I can act on the memo rather than hand it to an agency with a reason to dislike it; that side is described under performance marketing and can be commission based, and the modelling side sits under data science. The pricing page sets out how the monthly arrangement works without a sales call. What you will never get from me is a model without an interval, or a lift figure I would not defend in front of your accountant.

Questions to ask before you trust a media mix model

  • How many weeks of data went in, and how many parameters came out?
  • What are the half lives per channel in weeks, and would the channel owner recognise them?
  • Where does each channel sit on its saturation curve today, as a percentage of its maximum effect?
  • How did you handle branded search collecting demand that other channels created?
  • What is the marginal ROI per channel, and what is the interval around the recommended reallocation?
  • Did the model forecast a held out period, and by how much did it miss?
  • Which channel is least certain, and which test would resolve it?
  • What did you assume before you saw the data, and where is that written down?

This series is inspired by Mike Grigsby's Marketing Analytics (Kogan Page). The explanations, examples and numbers here are my own.

If your channels all spend more in the same months and your attribution report hands everything to search, send me your weekly spend and revenue for the last two years, one row per week, and I will tell you within a day whether a media mix model can be fitted to it and what it is likely to show. Or book the free workshop and we work out together which channel deserves the next pound and which test would settle the argument. Two weeks of real work on my risk come after that, and you keep the table, the code and the memo either way.

1%of every invoice goes to a UK charity you pick.

A donation, never sponsorship. You choose the cause at onboarding.

The story behind the pledge →

Stay ahead of your competition.

The latest innovative products and services, straight to your inbox before your competitors hear about them.

Get up to 5% off your first six months: 1% per topic you pick, the full 5% when you take everything. Limited offer · ends 31 December 2026.

New clients only. Terms apply.

* Up to 5% off your first six monthly invoices, new clients only. Full terms.

Questions about pricing, contracts or how we work together?

Read the FAQ