Budget Allocation Optimization: Where to Shift Your Next Marketing Dollar
By MCP Analytics Team | Published , updated
Every marketing team faces the same question at budget time: where should the next dollar go? Move it to the channel with the highest ROAS? Double down on what seems to be working? Spread it evenly and hope?
The problem is that average ROAS lies to you. A channel showing 5:1 average ROAS might already be saturated: the next dollar you put in could return only $0.50. Meanwhile, an underinvested channel showing 2:1 average ROAS might have room to scale to 4:1 at your next spend level. Without understanding diminishing returns and marginal economics, you are optimizing based on the wrong numbers.
This article covers the concepts and methods that separate data-informed budget decisions from expensive guesswork: marginal ROAS, saturation curves, diminishing returns analysis, and optimal reallocation.
Worked Example (Simulated): Should the Next $1k Go to Search or Social?
Question: With a set monthly fund of $10.0k, should the next part go to Search or Social?
Inputs: Simulated data, seed 17, with spend and revenue in thousands of dollars. The curves are built into the script (Search 6.0x - 0.30x2, Social 4.0x - 0.15x2, plus noise with standard deviation 0.12) and sampled at $0k, $2k, $4k, $6k and $8k. The starting split of $8.0k Search and $2.0k Social is the script's choice, not an observed budget.
Method: Fit a quadratic curve to revenue for each ad type. Then test every split of the $10.0k fund in $0.1k steps, keeping each ad type between $0.0k and $8.0k, and keep the split with the highest modeled revenue.
import numpy as np
# Simulated monthly spend and revenue, both in thousands of dollars.
rng = np.random.default_rng(17)
spend_points = np.array([0, 2, 4, 6, 8], dtype=float)
# The curves are built in: revenue = a*x - b*x^2, plus noise (sd 0.12).
curves = {
"Search": (6.0, 0.30),
"Social": (4.0, 0.15),
}
fit = {}
for name, (a, b) in curves.items():
true_revenue = a * spend_points - b * spend_points**2
observed_revenue = true_revenue + rng.normal(0, 0.12, size=len(spend_points))
fit[name] = np.polyfit(spend_points, observed_revenue, 2)
# Test $100 steps; keep each channel between $0 and $8k and total at $10k.
step = 0.1
budget = 10.0
limits = (0.0, 8.0)
def revenue(name, spend):
q, m, c = fit[name]
return q * spend**2 + m * spend + c
def marginal(name, spend):
q, m, _ = fit[name]
return 2 * q * spend + m
# The starting split is the script's choice, not an observed budget.
current = {"Search": 8.0, "Social": 2.0}
current_total = sum(revenue(n, s) for n, s in current.items())
best = None
for search in np.round(np.arange(limits[0], limits[1] + step / 2, step), 1):
social = round(budget - search, 1)
if limits[0] <= social <= limits[1]:
total = revenue("Search", search) + revenue("Social", social)
if best is None or total > best[0]:
best = (total, search, social)
opt_total, opt_search, opt_social = best
print("Simulated data, seed 17; spend and revenue in $1,000s")
print("Input spend points per channel: $0k, $2k, $4k, $6k, $8k")
print("Fitted curves: revenue = intercept + linear*spend + quadratic*spend^2")
for name in ("Search", "Social"):
q, m, c = fit[name]
print(f"{name}: {c:.3f} + {m:.3f}*x + {q:.3f}*x^2")
print(f"Limits: ${budget:.1f}k total; "
f"each channel ${limits[0]:.1f}k to ${limits[1]:.1f}k")
print(f"Tested split step: ${step:.1f}k")
print(f"Current: Search ${current['Search']:.1f}k, "
f"Social ${current['Social']:.1f}k; modeled revenue ${current_total:.3f}k")
print(f"Best tested split: Search ${opt_search:.1f}k, Social ${opt_social:.1f}k; "
f"modeled revenue ${opt_total:.3f}k")
print(f"Modeled change: ${opt_total-current_total:.3f}k "
f"({(opt_total/current_total-1)*100:.2f}%)")
print(f"Marginal returns at new split: Search "
f"${marginal('Search', opt_search):.3f}k/$1k, "
f"Social ${marginal('Social', opt_social):.3f}k/$1k")
Printed output:
Simulated data, seed 17; spend and revenue in $1,000s
Input spend points per channel: $0k, $2k, $4k, $6k, $8k
Fitted curves: revenue = intercept + linear*spend + quadratic*spend^2
Search: 0.135 + 5.947*x + -0.299*x^2
Social: -0.011 + 3.956*x + -0.144*x^2
Limits: $10.0k total; each channel $0.0k to $8.0k
Tested split step: $0.1k
Current: Search $8.0k, Social $2.0k; modeled revenue $35.896k
Best tested split: Search $5.5k, Social $4.5k; modeled revenue $38.670k
Modeled change: $2.774k (7.73%)
Marginal returns at new split: Search $2.657k/$1k, Social $2.658k/$1k
Result: The best tested split is $5.5k for Search and $4.5k for Social. Modeled revenue rises from $35.896k at the starting split to $38.670k, a gain of $2.774k (7.73%). At that split the next $1k returns about $2.657k in Search and $2.658k in Social, almost the same, which is the point where a further shift stops paying in this model.
Limit: The curves are built into the script and the fit recovers them, which is why the result looks tidy. The 7.73% is arithmetic on made-up curves and a chosen starting split. It is not a forecast for a real firm and not a typical gain.
Why Average ROAS Misleads Budget Decisions
Imagine two channels in your marketing mix (made-up numbers):
To see which of your own marketing channels drive sales, try the free media mix model tool.
| Channel | Monthly Spend | Revenue Attributed | Average ROAS |
|---|---|---|---|
| Google Search | $15,000 | $75,000 | 5.0x |
| Facebook Ads | $5,000 | $12,500 | 2.5x |
To see which of your own marketing channels drive sales, try the free media mix model tool.
Conventional wisdom says: move budget from Facebook (2.5x) to Google Search (5.0x). But what if Google Search is already saturated at $15K/month? The first $5,000 might generate $40,000 in revenue (8:1 ROAS), but the last $5,000 only generates $10,000 (2:1 ROAS). The next $5,000 you add might return only $3,000 (0.6:1), meaning you lose money on the margin.
Meanwhile, Facebook at $5K/month might be in the steep part of its response curve. Scaling to $10K could generate $30,000 in revenue: a 3.5:1 marginal ROAS on the incremental spend.
The right move is the opposite of what average ROAS suggests: shift budget from the saturated high-ROAS channel to the unsaturated lower-ROAS channel.
The Core Principle
Budget is optimally allocated when the marginal ROAS is equalized across all channels. If one channel's marginal return is higher than another's, moving a dollar from the low-marginal channel to the high-marginal channel increases total return. Optimal allocation is the point where no reallocation can improve total revenue.
Understanding Saturation Curves
Every marketing channel follows a response curve that looks roughly like an S-shape or a concave curve:
- Early phase (steep): First dollars in a channel produce high returns. You are reaching the most responsive audience. Marginal ROAS is high.
- Middle phase (linear): Returns are proportional to spend. Each additional dollar produces about the same as the last. This is the "sweet spot."
- Late phase (flat): Diminishing returns set in. You are reaching less responsive audiences, frequency increases, ad fatigue builds. Each additional dollar produces less than the previous one. Marginal ROAS declines.
- Saturation: Increasing spend produces negligible additional revenue. The curve flattens. You are burning money.
The shapes differ by channel. Search advertising often saturates faster because the query volume is finite: once you are capturing most relevant searches, more spend just raises your CPC. Display and social advertising have larger addressable audiences and may take longer to saturate, but creative fatigue accelerates the curve.
Marginal ROAS: The Number That Actually Matters
Marginal ROAS is the return on the next dollar, not the average dollar. It is the derivative of the response curve at your current spend level. The table below uses made-up numbers.
| Channel | Current Spend | Average ROAS | Marginal ROAS | Implication |
|---|---|---|---|---|
| Google Search | $15,000/mo | 5.0x | 0.8x | Saturated. Reduce spend. |
| Facebook Ads | $5,000/mo | 2.5x | 3.2x | Room to scale. Increase spend. |
| LinkedIn Ads | $3,000/mo | 1.8x | 2.1x | Moderate headroom. Consider increasing. |
| $500/mo | 8.0x | 6.5x | Highly underinvested. Scale up. |
In this example, the optimal move is clear: reduce Google Search spend, increase Facebook and email investment. The total budget stays the same, but total revenue goes up because you are moving dollars from low-marginal to high-marginal channels.
How to get marginal ROAS: You cannot read it off your Google Ads dashboard. It comes from fitting a response curve to historical spend-and-revenue data, which is exactly what media mix modeling does. The MMM output includes saturation curves for each channel, and marginal ROAS at your current spend level is the slope of that curve at the current point.
Finding Your Optimal Budget Allocation
The mathematical optimization is straightforward once you have the saturation curves:
- Estimate each channel's response curve from historical data (via MMM)
- Calculate marginal ROAS at the current spend level for each channel
- Identify the reallocation opportunity: move funds from an ad type with a lower next-dollar return to one with a higher return, within spend and scale limits. Stop when no allowed shift can raise sales.
- Shift budget from overspent channels to underspent channels until marginal ROAS equalizes across all channels
- Check with constraints: account for minimum spend thresholds (some channels require minimum budgets to function), maximum scalability (email list size caps email potential), and strategic priorities (brand building may have long-term value not captured in short-term ROAS)
MCP Analytics runs the model and shows the result; you decide what to change.
Practical Considerations That Models Miss
Budget optimization models are powerful but not omniscient. Here are the real-world factors to weigh alongside the math:
Minimum Viable Spend
Some channels do not work below a certain spend threshold. Google Search with $500/month might not generate enough impressions to learn and optimize. If the model suggests reducing a channel to $200/month, you might be better off cutting it entirely and reallocating the full amount.
Strategic Channels vs. Performance Channels
Brand advertising (awareness campaigns, sponsorships, PR) may show low short-term ROAS in an MMM model but build long-term brand equity that shows up in the baseline over time. Cutting brand spend to zero because the marginal ROAS is low today could erode your baseline revenue over the next 6-12 months. Use MMM for performance channel allocation; use judgment for brand investment.
Channel Interactions
Google Search and Facebook often work together: awareness from Facebook drives branded search on Google. Cutting Facebook might reduce Google Search effectiveness, even though Google looks independent in the model. Advanced MMM models test for interaction effects, but simpler models may miss this.
Scaling Constraints
Email ROAS is typically high, but you cannot scale email spend infinitely, your list size caps the audience. The optimization might suggest tripling your email budget, but if your list is 5,000 people, there is a physical limit. Always sanity-check the optimized allocation against real-world channel constraints.
How to Get Started with Budget Optimization
- Export your data. Weekly spend by channel + weekly revenue for the last 6-12 months.
- Run media mix modeling. Upload the CSV to MCP Analytics. The model produces channel contributions, response curves, and saturation analysis.
- Review the optimization recommendation. Check the suggested reallocation against your constraints: minimum spend thresholds, scaling limits, strategic priorities.
- Implement gradually. Do not flip the entire budget overnight. Shift a small share of spend each month toward the recommended allocation and measure the impact.
- Re-run quarterly. Channel economics change. New competitors enter, audiences shift, creative fatigue sets in. Re-run the model each quarter to update your allocation.
Your turn
Bring your own data and the question you actually need answered.
MCP AnalyticsData science by email Send us your data and your question, and we will reply. ds@mcpanalytics.ai
Frequently Asked Questions
What is marginal ROAS and why does it matter more than average ROAS?
Average ROAS is the total return divided by total spend. It tells you how the channel has performed overall. Marginal ROAS is the return on the next dollar you spend. It tells you what happens if you increase or decrease your investment. A channel can have excellent average ROAS (5:1) but terrible marginal ROAS (0.5:1) if it is saturated. Budget allocation decisions should be based on marginal ROAS, because you are deciding where to put the next dollar, not evaluating the first one.
How do I know if a marketing channel is saturated?
A channel is saturated when increasing spend produces diminishing returns. Quantitative signs: marginal ROAS below 1.0 (you lose money on the next dollar), CPA increasing as you scale, and flattening response curves in MMM output. Qualitative signs: frequency caps being hit, creative fatigue (declining CTR with same audiences), and no new audience segments available. Media mix modeling estimates the saturation point for each channel.
How often should I re-optimize my marketing budget allocation?
Use each quarter as a check point. This gives new spend time to show a pattern and sets a regular time to see if returns have changed. Some teams refresh monthly during high-spend periods (holiday season, product launches) or after significant market changes (new competitor, algorithm update).
Can I optimize budget allocation without media mix modeling?
You can make rough allocation decisions using platform-reported ROAS. Compare those numbers with your own revenue data before you act on them. Media mix modeling fits your spend by channel to your revenue data. For small budgets on 1-2 channels, platform ROAS may be sufficient.