Marketing mix modelling · 15 min read · Interactive · Video
How much should I spend on each channel, and where do the extra euros stop paying off? Marketing mix modelling
It is the quarterly planning meeting, and the slide says Social brings in a sale for about 22 euros and Video for just over 40. Somebody says "Feed Social, cut Video." On my example account that move is exactly backwards. I show how to read the return on the next euro, how sure you can be of it, and the ways the method misleads you.
The short answer
Put the next euro where the next euro still earns the most, which is rarely the channel with the best average. An average blends a channel's productive first euros with its wasted last ones, so it cannot tell you whether a channel is already full. Marketing mix modelling (MMM), the method behind Google's open-source Meridian, learns a diminishing-returns curve for each channel from weekly spend and revenue and reads the slope at your current spend. Move budget from flat channels to steep ones and revenue rises at the same total spend. It needs no user tracking, but Meridian's documentation asks for two years of weekly data. Google researchers found models that fitted the same data within a few per cent yet differed by up to 50 per cent in predicted sales. It cannot prove that a channel caused a sale, so a big move still needs an experiment.
The question a per-channel average cannot answer
Picture the three channels on that slide. An average return over every euro you spent can make them look alike, all profitable, all worth keeping. But euros are not interchangeable. The first euros on a channel land on the steep part of its curve and work hard. The later ones land on the flat part and barely move revenue. Two channels with the same average can sit in completely different places.
The budget decision lives in the slope at your current spend: the extra revenue the next euro would bring. Economists call it the marginal return, and modellers call it mROI. A high average with a flat slope is a place to stop adding. A lower average with a steep slope is a place to grow. You cannot read the slope off two totals. You have to recover the whole curve, and every channel's curve is made of two shapes.
The two shapes every channel has
Diminishing returns. Spend a little on a channel and each euro finds a fresh, willing customer. Spend a lot and you start paying to reach people you would have reached anyway, or who were never going to buy. So revenue rises, bends over and flattens toward a ceiling (a saturation curve, in the trade). Below the bend you are underspending. Above it you are feeding a channel that is already full.
Carryover. Advertising has an echo. Someone sees your ad this week and buys next week, so a burst of spend keeps paying out for a few weeks, fading as it goes. Modellers call it adstock. It matters only while spend is changing. At a steady weekly budget the echo settles and the response is just the saturation curve.

The maths, written out
Here are the only formulas in this post. There are two, and anyone who builds spreadsheets can follow both.
The saturation curve. Each channel's revenue, as a function of its spend x after carryover, is a ceiling times a fraction that rises and flattens:
contribution = β · Hill(x)Hill(x) = xs / (xs + ecs)
- β
- the ceiling, the most weekly revenue the channel could ever add.
- ec
- the half-saturation point, the weekly spend at which the channel delivers half its ceiling (at x = ec the fraction is ½).
- s
- how sharply the curve bends: s ≤ 1 gives the plain diminishing-returns shape, s > 1 a gentle S that is slow to start. This is the Hill curve from the Google paper that set out the modern form of the method [1].
Carryover. Before spend reaches the curve, this week's spend is blended with recent weeks':
adstockt = ( Σ αl xt−l ) / ( Σ αl )
- α
- the decay (between 0 and 1): how much of last week's effect carries into this week.
- l
- how many weeks back you look (eight weeks, Meridian's default). The weights add up to one, so a steady spend passes through unchanged.
Where α comes from. Not from a survey. The fit tries decay rates and keeps the one whose echo best explains the revenue you actually had, so its only evidence is variation in spend: bursts, pauses, budget changes. A channel held at a flat budget supplies almost none, and then the model's starting assumption (its prior) fills the gap, not your data. That makes carryover the part your data pins down least. If the decay matters to your decision, switch the channel off in some regions and watch how many weeks the gap takes to open. That is a geo holdout, doing the job history cannot.
The order, and the total. Carryover comes first, then saturation, the order Jin and colleagues chose for steady weekly spend (they note the reverse suits bursty spend) [1]. Add up the channels and a baseline for trend, season and everything else, and you have the model's guess at weekly revenue:
revenuet = baselinet + Σc βc · Hill(adstockc(x)) + noise
- the slope
- the number you act on is the slope of each curve at your current spend. Fit the curves, read the slopes, move budget toward the steep ones. That is the method in one sentence.
A worked example synthetic data
The notebook invents 156 weeks of data for an online shop running Search, Social and Video, plus a baseline and noise. It is the shop from the planning meeting. By construction it has overfed one channel and starved another, and the model is told none of this.
The shop spends about €26,000 a week, €1.36M a year, half of it on Social. Revenue averages about €179,000 a week, and media drives about 44% of it.
| Weekly spend | Share of budget | |
|---|---|---|
| Social | €13,404 | 51% |
| Search | €8,899 | 34% |
| Video | €3,793 | 15% |
| All three | €26,096 |
Many different curves fit the same history almost equally well, so the real libraries add priors, gentle nudges toward sensible shapes, and the notebook does a light version of the same. Its fit is off by 2.0% on a weighted average (the measure is called wMAPE). I deliberately do not lead with R², the usual score for fit. Chan and Perry, at Google, showed models fitting the same data within a few per cent of each other yet differing by up to 50% in the sales they predicted for the same spend [2]. A good fit tells you the model is not broken. It does not tell you the budget answer is right.

Here is what the model reads off its curves: the return on the next euro at each channel's current spend, with a range that holds 90% of the answers from refitting on resampled data. Because I built the shop, the last column holds the truth.
| Channel | Spending now | Next euro returns | 90% range | True value |
|---|---|---|---|---|
| Video | €3,793/wk | €2.69 | €2.01 to €3.45 | €2.70 |
| Search | €8,899/wk | €1.24 | €1.02 to €1.50 | €1.10 |
| Social | €13,404/wk | €0.99 | €0.88 to €1.18 | €0.79 |
The gap is the recommendation. Video is underfed: each extra euro still returns nearly €2.70. Social is full. Its next euro returns 99 cents, less than it cost, which is a loss on profit unless every euro of revenue were margin. Search is about right.
So the model moves money from the full channel to the hungry one and keeps total spend fixed. It takes €2,680 a week off Social and puts €2,861 onto Video, with the small remainder coming off Search. That is a tenth of the whole budget and a fifth of Social’s own spend, a real reweighting rather than a rounding adjustment. Weekly media revenue rises by about €2,061 at no extra spend, and the move gained on 499 of 500 refits of the model. The direction is safe even though the size is not.
The truth column marks the model's homework. The ordering is recovered exactly, and Video and Search land inside their ranges. Social does not: its true return sits below the €0.88 floor of its range. The ranges cover the noise around one fit under one set of priors, not a curve shape the priors pinned wrongly, which is why the direction is the reliable read.
The yearly figures below are the weekly result times fifty-two. That assumes nothing changes all year: no season, no saturation shifting as Video is fed, no competitor answering back. And it is all synthetic, a demonstration of a method rather than a result from a real account.
| The move's gain | Per week | Per year |
|---|---|---|
| Fitted estimate | €2,061 (a 2.6% lift) | about €107,000 |
| 90% range | €967 to €3,755 | €50,000 to €195,000 |
| True value (known here) | €3,339 |

One limit is built into the recommendation itself. The suggested Video spend sits near the top of what this shop has actually run. Push further and the model is guessing a curve where it has no data, and the range fans out fast.
Play with the budget
Caveats to watch out for
Every method has situations where it gives a confident wrong answer. These are this one's, most of them documented by the Google researchers who build it [2].
The model reads history and cannot prove that a channel caused the sales. Chan and Perry put it plainly: such models "produce correlational, not causal results" [2]. Use it to decide what to test, then confirm the big moves with an experiment such as a geo holdout.
If you spend more exactly when demand is already high (the season, a launch, a trend), the model can credit the ads with sales the demand would have brought anyway. Statisticians call this selection bias. Google’s team counts it among the most demanding problems in applied statistics, and no amount of curve fitting removes it [2].
Retargeting and brand search point ads at people who already want the product. The model sees those channels next to the sales and credits them, when many of those people would have bought anyway. Settle a suspiciously high return there with a holdout.
The model can only separate two channels whose spend varied independently. If you always scaled two channels together, the fit splits the credit more or less arbitrarily. Their combined effect is solid. The split is not. In the notebook, forcing two channels into lockstep pushes the correlation between their spend to 0.95, and the warning fires. Vary their budgets apart for a few weeks, or report them as one bucket.
Ask "what if I double it?" and the model is guessing in territory it has never seen, where curves that fit your history equally well fan out to very different answers [2]. Trust a recommendation near where you already spend. Treat one far beyond it as a hypothesis to step toward gradually.
Sales vary far more than spend does, so many models fit well yet disagree sharply on the budget advice. In Chan and Perry’s example, models within a few per cent of each other on fit differed by up to 50% on predicted sales [2]. That is why every number here is a range.
A model can match the weeks it learned from and still miss the next ones. Refit it without the last few weeks and ask it to predict them: if it does much worse there than on the rest, its channel numbers are less dependable than they look. Then refit each month. If the channel answers jump with nothing in the account to explain it, treat that month as unsettled, not as a real change. The notebook runs neither check for you.
This bites hardest on carryover. When the history is thin, or the budget barely changed, the gentle nudges that make the fit possible can also decide it. Rerun the model with deliberately vaguer starting assumptions. If the next-euro returns move a lot, the answer was the assumptions’ and not the data’s. The worked example shows the milder form: Social’s true return falls outside a range that only ever measured noise. Until more history arrives, read the direction and treat the size as provisional.
The model’s moving baseline can absorb a shift in the overall level, such as a repricing or a market won or lost. It cannot absorb a change in how well one channel works, such as a redesign that lifted conversion on Search. The curve then averages before and after, and neither the fit nor its ranges will say so. Model the change rather than throw history away: a step in the baseline at that date, or the channel split into before and after, once something other than the alarm that raised it has confirmed the change. Cut the window only when the business is no longer the same business, and even then keep two years.
Why one method is not enough
Back to the slide in the meeting. Its single cost per sale is quietly answering three questions at once: who earned the sale, whether the channel caused it, and whether the next euro still works. Large field experiments at Facebook found that methods reading history often fail to match what a randomised experiment measures on the same campaigns [3]. Separating the questions takes three methods, the three posts in this series.
Attribution fixes the credit. The Markov removal effect shares credit across the whole journey. Video opens journeys it rarely closes, so its share climbs from a tenth to about a third, while Social, a closer, falls from nearly two thirds. Put that back into cost per sale and the slide turns over: Video becomes the cheapest channel and Social the dearest. But attribution cannot prove that Video caused a sale.
A geo holdout fixes the cause. Turn each channel off in test regions and measure the drop. Video gives back €5.26 for every euro withheld and Social €3.23, so both earn their place. The holdout is also the check on the mix model, because it reads the shop's real response rather than the model's curve. The model puts Social's average euro at €2.26, below the whole of the holdout's range (€2.80 to €3.66), so the holdout catches the model understating Social; on Video the model's €6.38 sits inside the holdout's wide range. But switching a channel off prices its average euro, and the decision is about its last one. A holdout also settles one channel at a time and draws no curve.
The mix model fixes the saturation. That is the gap the holdout cannot see: Social's average euro comes back more than three times over while its next euro returns 99 cents. But the mix model can be fooled by hidden demand.
Each method is strongest where the last is blind, and they use different data and different maths. When all three point the same way (feed Video, trim Social), the agreement is far stronger evidence than any one alone. When they disagree, I report the split, trust the experiment on cause, and name what would settle it. Google's Meridian closes the loop: it is built to "set custom ROI priors using past experiments" [4], feeding a holdout's measured lift into the model.
How the industry uses it
The biggest platforms have each open-sourced a mix model and put their name to it. Google ships Meridian, which its documentation says is "designed to estimate the true causal impact of your marketing" [4]. Meta ships Robyn [5]. The open-source PyMC-Marketing library builds the same two pieces as this post, though its saturation curve is logistic where mine is Hill [6].
The comeback is about privacy. Because the method works from weekly totals rather than tracking people, it survives the loss of cookies and device IDs that broke click-based measurement, a point two measurement vendors make in almost the same words [7], [8]. That is why a technique from the television era is back at the centre of modern measurement, alongside established firms such as Analytic Partners [9].
Meta's Robyn case studies include an advertiser called Resident reporting a 20% rise in revenue after adopting it [10]. That is a reported case for a different advertiser, not a promise about yours.
Run it on your own data
Every download runs on your own machine, and your data never leaves it. They take one weekly table with a row per week:
| column | meaning | example |
|---|---|---|
week | Monday of the week | 2024-01-01 |
revenue | net sales that week, after refunds and without VAT | 184320 |
spend_<channel> | one column per channel | spend_Search = 9100 |
control_<name> (optional) | anything else that moves sales | control_promo = 1 |
The notebook fits the curves, prints each channel's next-euro return and proposes the rebalance, and it refuses to give a confident answer it cannot support. Below 104 weeks it stops (two years, the minimum Meridian states for regional data, so every season is seen twice; a single national series like this one wants three). On thin data it labels every number an estimate. If two channels moved together, it warns you that it cannot split them.
It reads a CSV or an .xlsx in any row order, with money written as it comes. It takes "spend now" as your average over the last thirteen weeks, and marks any proposal past the most you have ever spent in a week as extrapolation. Set your gross margin and it prints the profit on the next euro, because a return of €1 breaks even only when every euro of revenue is profit. Its last lines are the fitted curves in the spreadsheet's column order, ready to paste. Revenue needs two years from one source. GA4's BigQuery export does not backfill, so a recently linked property needs the shop or finance system's weekly sales instead.
Getting your data into that shape
Most exports are daily, one row per channel per day. The notebook's daily_to_weekly helper rolls a daily spend log and a daily revenue series up into the weekly table. Spend comes from Google Ads and Meta, revenue from GA4 or your shop, and no cookies, device IDs or user tracking are needed.
The one real judgement call is mapping your campaigns into a handful of channels, because spend lives under campaign names, not tidy buckets. Take revenue from the system that sees all your sales, never from one ad platform's reported revenue, which double counts across platforms and misses offline sales.
You do not have to do this part alone. Hand the give-it-to-your-AI brief to ChatGPT, Claude or any capable assistant, and it will walk you through pulling your data, shaping it and running the notebook, even if you have never written a line of code.
Common questions
Is MMM the same as attribution?
How much data do I need?
Does it need cookies or user tracking?
Can I trust the exact euro figures?
My model says to pour money into one channel. Should I?
Should I build this myself or buy a tool?
Try it on your own account
Export two years of weekly spend per channel, and weekly revenue from the one system that sees every sale. Run the notebook and look at a single column, the return on the next euro. If the channel with the best average has the flattest slope, you have found your Social. At the next planning meeting you can say why the obvious move is backwards before anyone reaches for the budget. If you want a hand with the method, or with the paid media underneath it, I take on freelance work, and I answer questions about anything published here.
Get in touchReferences
- [1] Jin, Y., Wang, Y., Sun, Y., Chan, D. and Koehler, J. (2017). Bayesian methods for media mix modeling with carryover and shape effects. Google Inc. (accessed 23 July 2026). https://research.google/pubs/bayesian-methods-for-media-mix-modeling-with-carryover-and-shape-effects/
- [2] Chan, D. and Perry, M. (2017). Challenges and opportunities in media mix modeling. Google Inc. (accessed 23 July 2026). https://research.google/pubs/challenges-and-opportunities-in-media-mix-modeling/
- [3] Gordon, B. R., Zettelmeyer, F., Bhargava, N. and Chapsky, D. (2019). A comparison of approaches to advertising measurement: evidence from big field experiments at Facebook. Marketing Science, 38(2), 193 to 225. https://doi.org/10.1287/mksc.2018.1135
- [4] Google for Developers (2025). Meridian: Introduction. Meridian documentation (accessed 23 July 2026). https://developers.google.com/meridian/docs/basics/meridian-introduction
- [5] Meta Marketing Science. Welcome to Robyn. Robyn documentation (accessed 23 July 2026). https://facebookexperimental.github.io/Robyn/docs/welcome/
- [6] PyMC Labs. MMM example notebook. PyMC-Marketing documentation (accessed 23 July 2026). https://www.pymc-marketing.io/en/stable/notebooks/mmm/mmm_example.html
- [7] Northbeam. What is media mix modeling (MMM)? Northbeam blog (accessed 23 July 2026). https://www.northbeam.io/blog/media-mix-modeling-mmm-guide
- [8] Measured. Eight (8) benefits of media mix modeling (MMM) for modern marketing. Measured FAQ (accessed 23 July 2026). https://www.measured.com/faq/eight-8-benefits-of-media-mix-modeling-mmm/
- [9] Analytic Partners. Marketing mix modeling. Analytic Partners solutions page (accessed 23 July 2026). https://analyticpartners.com/solutions/marketing-mix-modeling/
- [10] Meta Marketing Science. Case studies. Robyn documentation (accessed 23 July 2026). https://facebookexperimental.github.io/Robyn/docs/case-studies/
From Stochastic Strata. I build marketing measurement that shows its working: every number carries its range, and when the data cannot answer a question, I say so and tell you what would. The worked example here is synthetic. The method is the real thing, and you can run it on your own data with the notebook or spreadsheet above. Nothing in this post is financial advice.