← Back to Curriculum
Module 11

Budget Optimization

The goal of MMM isn't just to measure; it's to improve. How to maximize revenue by shifting dollars based on the Response Curve.

Your model is built. You know that Facebook has an Average ROAS of 3.0 and TV has an Average ROAS of 1.5.

The natural instinct is to say: "Cut TV budget and move it all to Facebook!"

This is a trap. Average ROAS looks backward at what happened. It ignores Saturation. If you double your Facebook spend, you might hit the "Ceiling" (Module 5), and your efficiency will plummet. To optimize, we must look at the Marginal ROAS (mROAS).

1. Average vs. Marginal

Average ROAS

"On average, last year, every $1 spent on Search yielded $5."

Use this for: Performance reviews and reporting.

Marginal ROAS (mROAS)

"If I spend the next $1 on Search, it will yield only $0.50 because the channel is saturated."

Use this for: Budget Planning.

2. The Response Curve

Because we used Hill Functions (S-Curves) in our model, we can plot the relationship between Spend (X-axis) and Revenue (Y-axis) for every channel.

The "Optimal Point" is usually where the curve starts to flatten. Mathematically, this is where the first derivative of the curve equals 1.0 (or your target profit margin).

mROAS = Derivative of Hill Function at Current Spend Level

If mROAS > 1.0, you are making profit on the next dollar. Spend more.
If mROAS < 1.0, you are losing money on the next dollar. Pull back.

3. Algorithmic Optimization (Python)

You cannot solve this in your head for 10 channels simultaneously. We use a solver like scipy.optimize. We define a "constrained optimization" problem.

from scipy.optimize import minimize

# 1. Define the Objective Function (Negative Revenue because we want to minimize the negative)
def objective_function(budget_allocation):
    total_sales = 0
    for i, channel in enumerate(channels):
        # Apply Hill Function to calculate expected sales for this spend
        sales = hill_function(budget_allocation[i], channel_params)
        total_sales += sales
    return -total_sales

# 2. Define Constraints (Sum of budget = Total Budget)
constraints = ({'type': 'eq', 'fun': lambda x: sum(x) - TOTAL_BUDGET})

# 3. Define Bounds (Don't let any channel go to $0 or Infinity)
bounds = [(current_spend[c]*0.8, current_spend[c]*1.2) for c in channels]

# 4. Run the Solver
result = minimize(objective_function, current_spend, bounds=bounds, constraints=constraints)

4. The Result: The Optimized Mix

The output of this script gives you the "Efficient Frontier." It might say:

By simply moving this money around—without increasing the total budget—you might squeeze out an extra 5-10% in Total Revenue. This is the ultimate value proposition of MMM.

Previous Module ← Decomposing Contribution