Media mix model & budget optimizer
A media mix model fitted to two years of weekly spend and revenue reads each channel's response curve and shows where the next euro of media budget earns most. Change the budget or the limits and the plan recomputes.
Adjust inputs ↓Optimizer
Where the next euro should go
| Channel | Change | Next € returns (at plan) |
|---|
Model fit
Does the model track revenue?
Curves are chosen on the first 91 weeks. The last 13 weeks are held out and predicted blind.
Decomposition
What each channel added
Incremental revenue per channel over the full period. The plan is built on marginal ROI, what the next euro returns at today's spend.
| Channel | Revenue | ROI | Marginal ROI |
|---|
Response curves
Where each channel flattens
Parameter recovery
Does the model recover the known curves?
The synthetic data comes from known curves, so this table checks the fit against the answer. Real data has no answer key, so calibrate the model with geo tests.
| Channel | True ROI | Fitted ROI | Error | Within 20% |
|---|
How it works
The model
Each channel's weekly spend goes through two transforms. Adstock carries part of this week's effect into later weeks (a decay of 0.6 means 60% carries over). The Hill curve then makes returns shrink as spend grows. Revenue is modelled as baseline (intercept, linear trend, three yearly Fourier terms) plus the transformed channels.
For each channel the fit searches 216 curve shapes (9 decays × 8 half-saturation points × 3 steepness values), one channel at a time, until nothing improves. Every candidate gets a ridge regression with media coefficients held non-negative. Weak priors on the curve shape stop the search chasing noise. Curves are chosen on 91 weeks; the last 13 are the holdout. Coefficients are then refit on all weeks for the decomposition and the plan.
The optimizer uses each channel's steady-state curve. It adds budget in small steps to whichever channel returns most for the next euro, then swaps budget between channels while that still pays. An exact grid search runs alongside, because S-shaped curves can trap a greedy step. On the same budget, the plan never scores worse than today's split.
In production
Weekly spend, revenue and controls (price, promos, holidays) come from the warehouse, modelled in dbt on BigQuery or Snowflake. The model runs as a Bayesian MMM such as PyMC-Marketing or Meridian, which puts a credible interval on every estimate. Geo-lift results become priors for the channels they cover (see the geo-lift demo). The plan lands in the planning sheet with ranges, and gets re-tested with the next experiment. The sentence above the plan is a template filled from the model output.
Limits
- It's correlational. If spend follows demand (search in Q4), the model can mistake demand for media effect.
- It needs spend variation. A channel that never moves, or moves with another, can't be separated. The Collinear scenario shows this.
- Steady-state curves ignore flighting effects: a burst can beat the same budget spread evenly.
- Plans far outside the observed spend range are extrapolation. Keep the per-channel limit tight, and calibrate with experiments.