How to Split Brand and Performance Budget With MMM Saturation Curves
How to optimize brand vs performance with MMM: read marginal ROI on each saturation curve, set spend bounds in Meridian or Robyn, and test what the fitted curve misses.
On this page
To optimize brand vs performance with MMM, compare the marginal ROI of each line at today's spend, move budget toward the higher one, and stop when the two marginal returns meet or a spend bound holds you back. Average ROI cannot make that call, because two lines with the same average can sit on very different parts of their curves. A fitted curve also counts only the effects that land inside the model's carryover window, so we treat the optimizer's number for a brand line as an estimate with a known blind side, then bound it and test it.
What a saturation curve tells you about each line
MMM saturation curves set the budget split between brand and performance through their slope at current spend. The ROI, mROI and response curves page on Google for Developers defines the three readings for Meridian. A response curve is "Incremental outcome as a function of spend", ROI is "A historical, channel-wide average", and mROI is "The return on the next dollar spent." The same page gives the rule for reading them together: "If the mROI is much lower compared to the ROI, then the channel is beginning to saturate at historical spend level."
Robyn's feature documentation from Meta, which says it was updated in December 2024 on R dev version v3.12.0, puts the same idea in calculus terms. Marginal response is the first derivative of the curve at a given spend level, and the page describes marginal ROAS, or mROAS, as "the most important metric for budget allocation". Both tools fit a Hill function for each channel. In Meridian a slope of 1 or less gives a concave curve and a slope above 1 gives an S shape, according to the media saturation page on Google for Developers. In Robyn the alpha parameter does that job, and a larger alpha means more of an S.
In the optimizer documentation we read for both tools, we found no brand or performance grouping, and allocation happens per channel. The split is therefore a sum you build yourself: tag each modeled channel as brand or performance, read its curve, and add up the recommended spend for each group.
A worked split where average ROI hides the answer
In marketing mix modeling, saturation curves turn into a budget allocation between brand and performance through marginal ROI, and a small hypothetical shows the mechanics. Assume a quarterly budget of $1,000,000, with $700,000 on performance lines and $300,000 on brand lines. Assume each group follows a concave Hill curve with a slope of 1, so incremental revenue equals the ceiling times spend, divided by spend plus the half-saturation point. The performance curve has a $4,000,000 ceiling and a $500,000 half-saturation point, and the brand curve has $3,000,000 and $600,000. Every figure in this example is invented for illustration.
| Scenario (hypothetical) | Performance spend | Brand spend | Performance mROI | Brand mROI | Incremental revenue |
|---|---|---|---|---|---|
| Current split | $700,000 | $300,000 | 1.39 | 2.22 | $3,333,333 |
| Brand increase capped at 30% | $610,000 | $390,000 | 1.62 | 1.84 | $3,380,016 |
| Marginal returns equal | $577,651 | $422,349 | 1.72 | 1.72 | $3,383,460 |
At the current split both lines show an average ROI of 3.33, so an ROI table suggests nothing needs to move. The marginal figures disagree, with the next brand dollar returning 2.22 and the next performance dollar 1.39. Moving money toward brand until both sit at 1.72 adds about $50,000 of modeled revenue, a gain of 1.5%. Capping the brand increase at 30% keeps about $46,700 of that, or 93%, while the two marginal returns are still apart.
Concave curves behave this way in real models too. Near the meeting point each dollar moved earns almost what it gives up, so the last step toward exact equality buys little, and it is the step furthest from the spend levels the model observed.
Running the split in Meridian and Robyn with spend bounds
To optimize a brand and performance budget using a marketing mix modeling saturation curve, pass the fitted curves to the tool's optimizer together with a spend bound for every channel. In Meridian, the budget optimization scenarios page on Google for Developers says the fixed budget scenario runs by default and finds the allocation that maximizes ROI for a given budget. Its spend_constraint_lower and spend_constraint_upper arguments both default to 0.3, which lets each channel move between 70% and 130% of its spend (the cap used in the table above), and in the flexible budget scenarios they default to 1, or 0% to 200%. Either argument accepts one value per channel. The flexible scenario with target_mroi spends until each channel's marginal ROI reaches a target you choose, with a caveat from Google: "It's still possible that the marginal ROI of some channels won't be equal to the target marginal ROI due to the feasible range of media spend."
In Robyn, robyn_allocator() offers a max_response and a target_efficiency scenario, and takes bounds through channel_constr_low and channel_constr_up as multiples of historical average spend. In the allocator source that Meta publishes on GitHub, as we read it on October 7, 2026, unset bounds fall back to 0.5 and 2 for max_response and to 0.1 and 10 for target_efficiency. The same file warns: "It's not recommended to 'exaggerate' upper bounds, especially if the new level is way higher than historical level."
Where diminishing returns get complicated for brand video
Marketing mix modeling saturation curves assume diminishing returns, and budget optimization across brand and performance lines gets harder where that assumption bends, which in our view is brand video. Meridian's default prior for the Hill slope assumes a concave shape, and the media saturation page says: "S-shaped curves can cause issues for budget optimization due to their convexity and may lead to convergence issues." For channels modeled on reach and frequency, the reach and frequency page on Google for Developers explains that the Hill curve applies to frequency while reach is treated as linear, and adds: "Optimization assumes that future campaigns will be executed at the optimal frequency, since frequency is something often in an advertiser's control, especially for digital channels." A brand video line can therefore look stronger in the optimized plan than its historical ROI suggests. If you cannot buy at that frequency, Google says the assumed frequency can be changed in the optimization options.
What a fitted curve cannot see
A marketing mix modeling diminishing returns curve for a brand line covers only the effect that lands inside the model's lag window, which limits how much weight the allocation between brand and performance can put on it. In Meridian that window is max_lag. The max_lag page on Google for Developers accepts that media can have an effect beyond it, then says: "For practical reasons, we truncate the effect at the max_lag value." Google recommends 2 to 10 time periods with geometric decay and 4 to 20 with binomial decay, and a separate calibration page, cited below, lists 8 as the ModelSpec default. Widening the window has a price, since the page says smaller values generally improve convergence and can reduce variance, and "Increasing max_lag doesn't necessarily mean that ROI estimates will also increase."
Robyn's documentation draws the boundary in a different place. It says that, without an agreed definition, it believes the long-term effect should describe media's impact on baseline sales, and continues: "In comparison, adstocking only addresses media's direct impact on the response and says nothing about the interaction with baseline." By that reading, anything brand advertising does through baseline demand sits outside the brand line's curve.
The size of the omission is unknown, and the split is sensitive to it. Return to the hypothetical and assume the fitted brand ceiling of $3,000,000 captures three quarters of the true effect, with the rest arriving after the window. Holding the $600,000 half-saturation point and the $1,000,000 budget fixed, the true ceiling is then $4,000,000, and the equal-marginal split moves from roughly 58/42 in favor of performance to 50/50.
Range is the second blind side. Hill parameters are estimated from the observed range of media data, and Google's saturation page says: "The fitted response curve can be extrapolated outside this range, but results based on extrapolation should be interpreted with an appropriate level of caution."
Bounds and tests that cover the gap
Set each bound by what the model observed and by the direction its error runs. We use three rules.
- Keep every upper bound close to spend levels the channel has run at during the modeling window, and treat anything above them as test budget.
- Give brand lines a tighter lower bound than performance lines, because the curve's omission runs against brand. In Meridian, for example, a
spend_constraint_lowerof 0.1 allows a 10% cut, against 30% at the default. - Rerun the optimizer under two or three assumed uplifts to the brand response. A recommendation that keeps its direction across them is safe to act on, and one that flips needs an experiment first.
The experiment that narrows the gap most is a geo incrementality test on the brand line with a long post-period, which fits the rhythm of a quarterly geo-holdout. Meridian's calibration page on Google for Developers describes a CalibrationBuilder that translates experiment results into ROI priors and adjusts them for duration, on this reasoning: "Because marketing effects carry over time (modeled by adstock decay), a short experiment might not capture the full, long-term effect of the media spend." The same page adds that a very long experiment "might capture effects beyond the model's truncated lag window," and under geometric decay the builder scales that estimate down to the window, so keep the extra effect for your sensitivity case. The builder is designed for lift measured against zero spend, and Google does not recommend registering marginal-lift results. Robyn's feature documentation says it accepts experiment results as a calibration input. Any test has its own window, so effects that arrive after the post-period still go unmeasured.
Our guide to reading a test result covers confidence intervals and delayed conversions. Our media mix calculator and Attribution Doctor are further resources, as is our data and analytics team if you want a second opinion on a model.
Present the split to finance as a range. The bounded optimizer answer is the low end for brand, the sensitivity case is the high end, and the next test is what narrows the distance between them.
Sources
- Google for Developers: Incremental Outcome, ROI, mROI & Response Curves
- Google for Developers: Budget optimization scenarios
- Google for Developers: Media saturation and lagging
- Google for Developers: Reach and frequency
- Google for Developers: Set the max_lag parameter
- Google for Developers: Set custom ROI priors using past experiments
- Meta: Robyn Key Features
- Meta: Robyn allocator.R source
