Finding where each dollar has the biggest impact
Budget allocation isn't about finding the "best" channel and giving it all your money. It's about finding the right balance—the mix that maximizes total return given the unique characteristics of each channel.
The key insight: every channel eventually hits diminishing returns. The first million dollars you spend on TV might be highly effective, but the tenth million is much less so. Smart allocation means finding where each additional dollar has the biggest impact.
Imagine you have a limited water supply for your garden. Some plants are already well-watered—giving them more won't help much because they're saturated. Other plants are thirsty and would flourish with extra water.
Smart gardening means identifying the thirsty plants. Budget optimization works the same way: find the channels that still have room to grow.
Diminishing returns means each additional dollar of spend produces less incremental outcome than the previous dollar. This is nearly universal in marketing:
Drag the slider to see how effectiveness changes as spend increases.
A saturation curve shows the relationship between spend and response for a channel. The curve's shape tells you how quickly diminishing returns kick in.
Each channel has a different curve shape. Some saturate quickly (steep early, flat later); others have more linear response. The vertical markers show current spend levels.
This is the most important distinction for budget decisions:
Average ROI = Total return ÷ Total spend. "For every dollar I've spent so far, I got back $X on average."
Marginal ROI = Return from the next dollar. "If I spend one more dollar, how much will I get back?"
Key insight: A channel can have high average ROI but low marginal ROI if it's already saturated. For budget decisions, marginal ROI is what matters.
Understanding your position on each channel's saturation curve reveals opportunities. Channels early on their curves have growth potential; those late are saturated.
| Channel | Current Spend | Saturation Level | Position | Marginal ROI | 94% Interval | Recommendation |
|---|---|---|---|---|---|---|
| TV | $2.5M | 72% | Mid-curve | 1.15 | 0.85 – 1.48 | Limited headroom |
| Paid Search | $1.2M | 85% | Near saturation | 0.65 | 0.42 – 0.91 | Consider reducing |
| Social | $0.8M | 35% | Early curve | 2.10 | 1.30 – 2.95 | Growth opportunity |
| Display | $0.5M | 60% | Mid-curve | 0.85 | 0.55 – 1.20 | Near break-even |
| Radio | $0.3M | 25% | Early curve | 1.85 | 1.10 – 2.65 | Growth opportunity |
Comparing marginal ROI across channels shows where the next dollar should go. This is different from which channel has historically performed best!
Use the sliders below to explore different budget allocations. The model predicts outcomes for each scenario in real-time.
Click a scenario to see its impact:
Reduce all channels by 20%
Current allocation
Model-recommended mix
Increase high-ROI channels
The "Optimized" mix above is illustrated by hand. In the framework it is not hand-waved: the shipped optimizer searches the allocation space for you, respects per-channel floors and caps, and—because it re-optimizes under every posterior draw—tells you how confident to be that the recommended mix actually beats what you are doing today.
The optimizer lives in mmm_framework.planning. It samples per-channel response curves from the fitted model's posterior, then runs a greedy marginal allocation (exact for saturating curves). Crucially, it re-optimizes under each posterior draw—turning parameter uncertainty into decision uncertainty: not just "how wide are the ROIs" but "how stable is the recommended allocation".
Read the uplift the same way you read everything else on this site: the interval, not the point. A median uplift of $740K with a 5–95% interval of $210K–$1.29M and P(uplift > 0) of 97% is a strong case for reallocating; the same median with an interval straddling zero is not. And if a channel's optimal_share_p5–p95 range is wide, the posterior does not pin down that channel's share—treat the recommendation as a direction, not a number. Caps above the sampled curve range are clamped and reported in result.notes rather than silently extrapolated.
optimize_budget() treats the fitted model the way the model is built: additive in channels. Each channel's response curve responds only to its own spend, so the optimizer assumes shifting budget into one channel never changes what another channel—or another product—delivers. There is no halo or cannibalization term anywhere in the shipped optimizer. If TV lifts a sister product's sales, or two brands cannibalize each other, optimizing each single-outcome model separately will miss or double-count those effects. Cross-outcome effects need the MultivariateMMM extension—see the multivariate section of the technical guide—and its budgets should then be assessed jointly, not channel by channel.