What a Marketing Mix Model Can and Cannot Do
A mix model is a good allocation tool and a weak causal one. Where its identification would have to come from, why a Bayesian version does not create any, and what makes one worth acting on.
A mix model regresses an aggregate outcome, usually weekly conversions or revenue, on spend by channel plus everything else that moves the outcome: seasonality, price, promotions, distribution, weather if you are being thorough. It has no cookies in it and no identity graph. It reads spend against results at the level a finance team already thinks at.
That design buys real things, and it costs one big one.
What it does that nothing else does
It sees channels that leave no trace. Television, radio, out of home, sponsorships, and increasingly anything on a platform that will not pass back user-level data. A mix model does not need a click, so these channels enter the analysis at all, which is more than attribution can say.
It survives tracking loss. Consent rates, platform restrictions, and app privacy changes move what user-level measurement can see, and they do it without warning. Weekly spend and weekly conversions keep arriving.
It puts every channel in one frame. Paid, owned, and offline get compared on the same axis with the same outcome, the only way a total budget question can be answered at all.
It models diminishing returns. This is the part that matters most and gets discussed least. Attribution assigns credit per conversion, so it has no opinion about what the next dollar buys. A mix model fits a curve, so it does.
Two questions, and it answers one of them much better
A mix model gets asked two things that sound related.
What did each channel contribute last year? That is a causal claim about the past, and it turns into a slide the CFO reads.
Where should the next dollar go? That is a question about the slope of each curve near current spend, and it turns into a media plan.
The model below fits its history at an r² of 0.96 with a mean absolute percentage error of 1.3%. It tracks three years of weekly conversions almost exactly. Here is how well it did on the first question.
- Model estimate
- True cost per conversion
Show the data
| Cost per conversion | Model estimate | True cost per conversion | Gap |
|---|---|---|---|
| Affiliate | 433 | 151 | 282 |
| Branded search | 65 | 165 | -100 |
| Non-brand search | 211 | 148 | 62 |
| Paid social | 45 | 92 | -47 |
| Online video | 105 | 78 | 28 |
Ranked by the model, the three cheapest channels are Paid social, Branded search, and Online video. Ranked by the truth they are Online video, Paid social, and Non-brand search. Branded search moves from second cheapest to most expensive, and it is the largest line in the account at $4,850,567 over three years.
A contribution slide built on this model would be wrong by 154% on its biggest number, and nothing in the fit statistics would hint at it.
That combination is the thing to hold onto. Badly wrong about contribution, roughly right about the next dollar. It is not luck. Allocation depends on the shape of each curve near where you are currently spending, and a model can recover a local slope while getting the level and the total attributed volume badly wrong. Marginal, Not Average is the argument for why the slope is the decision-relevant quantity in the first place.
Where the identification would have to come from
To read a coefficient on spend as an effect, the variation in spend has to be unrelated to whatever else is driving the outcome.
Consider how a media plan is built. Budgets rise into the season when demand rises. They rise behind a product launch. They get cut in a bad quarter, which is usually a quarter when something else was also going wrong. Channels go up and down together because they are planned together in one meeting.
Every one of those makes spend a function of expected demand. The regression sees spend and outcome moving together and has no way to tell which direction the arrow points.
Collinearity makes it worse in a specific way. When channels move together, many combinations of coefficients produce nearly the same predicted series. The likelihood is close to flat along that ridge. The model still returns one answer, because an optimizer returns one answer, and there is nothing in the output that says the answer was arbitrary along that direction.
Why a Bayesian mix model does not fix this
The standard response is that a Bayesian specification handles it: put priors on the channel coefficients, sample the posterior, report credible intervals.
That is a genuine improvement in how uncertainty is communicated. It is not identification, and the difference is worth being precise about.
Identification is a property of the map from data to parameters. If two very different parameter sets imply nearly the same predicted series, no amount of inference machinery can separate them, because the data does not contain the distinction. That is what a flat ridge in the likelihood means.
A prior is a statement about which values you considered plausible before seeing the data. Along a direction the data cannot resolve, the posterior in that direction is the prior, renormalized. The data contributed nothing there. The credible interval will still be narrow, because the prior was narrow.
The curves in this model make the point concretely. It recovered an adstock decay and a saturation point for every channel, and several are nowhere near the values that generated the data, while the series still fits at r² 0.96. Non-brand search saturates at 126 in the fitted model against 17 in truth. Paid social’s decay comes back at 0.05 against a true 0.45.
Fitted curve parameters against the ones that generated the data Code
- Branded search: decay 0.65 fitted against 0.15 true, saturation 6.2 fitted against 4.0 true.
- Non-brand search: decay 0.45 fitted against 0.25 true, saturation 125.8 fitted against 17.0 true.
- Paid social: decay 0.05 fitted against 0.45 true, saturation 4.6 fitted against 22.0 true.
- Online video: decay 0.45 fitted against 0.60 true, saturation 47.7 fitted against 48.0 true.
- Affiliate: decay 0.05 fitted against 0.20 true, saturation 54.1 fitted against 8.0 true.
Only online video came back close on both. The rest are wrong by enough to change any statement about how long a channel’s effect persists, and the fit barely notices. That is what a flat likelihood looks like from the outside.
There is one prior that does create identification, and it is worth naming because it is the exception that explains the rule. A prior derived from an experiment carries information the history does not, because it came from variation somebody created on purpose rather than variation a planner chose. The work is being done by the experiment. The Bayesian machinery is how the experimental estimate gets carried into the model, and that is a transport problem rather than an inference one.
Turning the model into a plan
A fitted model is not a media plan. Something has to take the curves and solve for an allocation, and that something is a scenario planner: pick a budget, set bounds on how far each channel may move, maximize modeled outcome.
Google’s Meridian is the reference implementation worth knowing about, and it is open source. Its scenario planner takes a trained model and optimizes either a fixed budget across channels or a flexible one against a target return, with per-channel spend bounds set as ratios of historical spend.
That last constraint is worth understanding rather than treating as a knob. A response curve carries information only near the spend levels that occurred. Beyond them the curve is the functional form talking, not the data. Meridian bounds its search with a minimum and maximum spend shift ratio for that reason, and a planner without such a bound will happily recommend zeroing a channel it has never seen at zero.
Meridian’s own documentation is unusually direct about the limit underneath all of this: goodness-of-fit metrics, it notes, do not tell you how good a model is for causal inference, and the best-fitting model may not be the best one for it. That is the same argument this lesson is making, in the tool’s own manual.
Scenario planner
Solve for the allocation that maximizes modeled conversions, then score the same plan against the curves that generated the data. A real planner can only show you the first number.
What the model predicts
+31.4
Conversions a week, against the current allocation. This is the number a planner reports.
What it delivers
+30.4
Scored on the curves that generated the data. Knowable here only because the data is simulated.
| Channel | Now | Plan | Change |
|---|---|---|---|
| Branded search | $31,093 | $21,765 | − $9,328 |
| Non-brand search | $35,936 | $42,435 | + $6,499 |
| Paid social | $23,055 | $26,466 | + $3,412 |
| Online video | $13,635 | $17,687 | + $4,053 |
| Affiliate | $15,451 | $10,815 | − $4,635 |
Simulated data · scripts/mmm_calibrated.py. The allocation rule equalizes marginal return across channels, which is the same rule the allocation track argues for throughout.
Calibrating a level does not calibrate a slope
Move the planner to the calibrated model and the delivered number falls. That is worth sitting with, because the calibrated model is the better model by every measure of the past: it puts paid social within 3% of its true contribution, against 103% for the history-only fit.
The reason is specific and it generalizes. Anchoring a channel to an experiment fixes how much it contributed. The planner does not use how much it contributed. It uses the derivative of the curve at current spend, and the anchor left that alone.
For paid social, the next $1,000 a week buys 3.67 conversions in truth. The history-only model puts it at 3.42, which is close. The calibrated model puts it at 1.63, roughly half, so the planner stops buying a channel it should be buying. Correcting the level moved the curve down without changing its shape, and the slope came down with it.
The practical version: if a calibrated model is going to drive allocation, the anchor has to constrain the curve rather than sit on top of it. That means refitting the shape under the anchor rather than keeping the unanchored shape, and preferring experiments that vary spend across two or more levels, because a single on-off holdout measures a level and a spend-change test measures a slope.
What makes a mix model worth acting on
- At least one experiment behind it, on the largest or the most contested channel. One holdout does not validate the model; it pins one channel and pushes error onto its neighbors. That is still the single highest-value thing you can add.
- Deliberate variation in the spend history. Flighting, staggered launches, regional differences, a pause somebody was brave enough to run. A model fitted on three years of smoothly planned spend has very little to learn from.
- Out-of-time validation, fitted on earlier weeks and scored on later ones. This does not test identification, and it does catch overfitting, a different failure that also happens.
- Recommendations rather than contributions in the output. A mix model is on much firmer ground saying “move budget here” than “this channel produced 74,000 conversions.” Report the decision it supports.
- A stated stability check. Refit with a channel dropped, with a different control set, and with the window shifted a quarter. If the recommendation survives all three, it is about the data. If it does not, it was about the specification.
Context
Best suited for
Allocating a total budget across channels, including ones with no click, when a few quarters of spend variation exist and at least one experiment can anchor the largest line.
Data requirements
- Two to three years of weekly spend by channel, at consistent definitions across the whole window
- The non-media drivers that move the outcome: price, promotion, distribution, seasonality
- Real variation in spend, ideally some of it created rather than observed
- At least one experimental estimate to anchor a channel, and a plan to add one per quarter
What changes by context
- B2C ecommerce
- Heavy branded search and promotion-driven demand make the endogeneity worst here. Promotions have to be controlled for explicitly, or the model hands their effect to whichever channel was scaled up alongside them.
- B2C subscription
- The outcome arrives on a lag and churn runs underneath it, so weekly conversions are a poor target on their own. Modeling gross adds and retention separately is usually better than modeling net growth and hoping the model separates them.
- Marketing-led
- This is the natural home for a mix model, because media is a large enough share of the driver set that the regression has something to explain. In an organization where growth comes mostly from product or sales motion, the media coefficients are picking up whatever those did.
When it breaks down
- Fewer than about two years of history, or a channel launched inside the window with no variation after it.
- Spend that never varies except with season, where the model cannot separate marketing from the calendar.
- A question about a specific campaign or creative. The unit is the channel-week, and nothing finer is in there.
- Any use where channel contribution gets reported as fact. That is the claim the design does not support.
What this does not establish
- That mix models are unreliable in general. This one recovered a reallocation worth acting on while getting contributions badly wrong. Both halves are the finding.
- That the errors here transfer. A 154% overstatement on branded search is a property of one simulated program with a particular correlation between spend and demand.
- That Bayesian specifications are worse than frequentist ones. They are better at reporting uncertainty. The argument is that reporting uncertainty and identifying an effect are different problems.
- That experimental calibration validates a model. It anchors the channels you tested, and the worked example shows error moving onto the ones you did not.
- That good out-of-sample fit indicates a trustworthy model. A confounded model forecasts confounded futures accurately, which is why forecast accuracy is not offered here as evidence.
What to test next
Run a holdout on the channel with the largest modeled contribution. That is usually branded search or the biggest retargeting line, and it is usually the channel whose modeled contribution is least defensible, for the same reason it is in What Multi-Touch Attribution Actually Computes: it sits closest to demand that already existed.
If a model is already in production and nobody has tested anything, the cheapest diagnostic is a specification check. Refit with the largest channel dropped entirely, and see how much the other coefficients move. Coefficients that swing hard were never separately identified, and now you know which parts of the deck to stop reading aloud.
Where these figures came from Code
One simulated advertiser, 156 weeks of weekly spend across five channels, with adstock and saturation applied to each and a true contribution known by construction. Spend was planned to correlate with expected demand, which is the condition the lesson is about. The history-only model is fitted to that series with no experimental information.
The full setup, including a version calibrated to a geo holdout, is the experiment-calibrated mix model worked example. These are not measurements from a real company.