End-to-end Marketing Mix Modeling implementation using Meta's Robyn framework in R.
This project applies adstock transformations, saturation modeling, Pareto-optimal model selection, and budget allocation optimization across 5 paid media channels over 4 years of weekly FMCG data.
Jhoan Sebastian Meza
Economist & Junior Data Scientist Β· Universidad Nacional de Colombia
GitHub
Marketing Mix Modeling (MMM) is a statistical technique used to quantify the impact of media investments on sales. Unlike digital attribution models, MMM works across all channels β including TV, OOH, and Print β and provides business-interpretable metrics such as ROI, elasticities, and channel contribution.
This project implements a full MMM pipeline using Meta's Robyn framework, covering:
- Automated adstock and saturation transformation via Nevergrad optimization
- Prophet-based decomposition of trend, seasonality, and holidays
- Pareto-optimal model selection balancing NRMSE and DECOMP.RSSD
- Budget reallocation recommendations to maximize media-attributed revenue
The project uses dt_simulated_weekly β a synthetic FMCG dataset included in the Robyn package.
| Variable | Type | Description |
|---|---|---|
DATE |
Date | Weekly time index (2015β2019) |
revenue |
Dependent variable | Weekly sales in $ |
tv_S |
Paid media spend | TV investment |
ooh_S |
Paid media spend | Out-of-Home (billboards, transit) |
print_S |
Paid media spend | Print media |
facebook_S |
Paid media spend | Facebook/Meta investment |
search_S |
Paid media spend | Search/Google investment |
competitor_sales_B |
Context variable | Competitor sales β control |
events |
Context variable | Special brand events and promotions |
208 weeks Β· 5 paid media channels Β· 2 context variables Β· 0 missing values
robyn_inputs() β robyn_run() β robyn_outputs() β robyn_allocator()
| Parameter | Value | Rationale |
|---|---|---|
| Adstock type | Weibull CDF | Flexible decay β more realistic than geometric |
| Iterations | 2,000 per trial | Recommended minimum for stable Pareto front |
| Trials | 5 | Ensures convergence stability |
| Regression | Ridge (L2) | Handles multicollinearity between channels |
| Prophet | trend + season + holiday | Isolates structural effects from media effects |
| Channel | Shapes | Scales | Business rationale |
|---|---|---|---|
tv_S |
0.1β1 | 0.3β0.9 | Long brand memory β effect lasts weeks |
ooh_S |
0.1β1 | 0.3β0.8 | Continuous exposure β moderate carryover |
print_S |
0.5β3 | 0.1β0.5 | Medium memory β between TV and digital |
facebook_S |
2β8 | 0.1β0.4 | Short digital effect β fast decay |
search_S |
3β10 | 0.0001β0.2 | Near-immediate intent capture |
Each dot is one model. Orange lines connect Pareto-optimal candidates β models where you cannot improve NRMSE without worsening DECOMP.RSSD. Dark blue dots were found in later iterations, showing Nevergrad's progressive optimization. The target zone is the bottom-left corner.
Robyn automatically selected 3 clusters using the WSS (Within Sum of Squares) method. The red line marks the 6% variance threshold β adding more clusters beyond k=3 produces diminishing improvements.
Each cluster's winning model is shown in the Pareto space. The selection criterion balances prediction accuracy (NRMSE) and business plausibility (DECOMP.RSSD).
Before estimating media contributions, Prophet decomposes total sales into structural components β trend, seasonality, and holidays. This prevents the model from incorrectly attributing seasonal peaks to media channels.
Adj.RΒ² train = 0.853 | NRMSE val = 0.065 | DECOMP.RSSD = 0.338
Selected for best predictive performance on the validation set.
Channel efficiency summary:
| Channel | Spend Share | Effect Share | Verdict |
|---|---|---|---|
search_S |
8.5% | 24.1% | β Highly efficient |
print_S |
5.3% | 15.8% | β Highly efficient |
tv_S |
21.3% | 25.1% | β Balanced |
ooh_S |
61.9% | 34.2% | β Over-invested |
facebook_S |
3.1% | 0.9% | β Low efficiency |
Immediate vs. Carryover highlights:
search_S&facebook_S: ~90% immediate β digital channels with near-instant responsetv_S: 42% immediate / 58% carryover β brand memory extends several weeks after campaignooh_S: 90% immediate / 10% carryover β driven by continuous physical exposure
Adj.RΒ² train = 0.806 | NRMSE val = 0.126 | DECOMP.RSSD = 0.074
Selected for the lowest DECOMP.RSSD β most business-plausible channel decomposition.
Notable finding: print_S shows 0% immediate and 0% carryover response in this model β indicating that print's hyperparameter ranges may require refinement or that the channel lacks sufficient spend variation for reliable estimation in this specification.
Using robyn_allocator() with the max_response scenario on the DΓa 3 reference model:
Key result: By simply redistributing the existing $11.9M budget β without increasing total spend β the model projects a +27.8% increase in media-attributed revenue (from $17.4M to $22.2M), reducing overall CPA from $0.68 to $0.54.
| Channel | Current spend | Optimal spend | Change |
|---|---|---|---|
ooh_S |
$57K/week | $31K/week | β¬οΈ -46% |
tv_S |
$15K/week | $31K/week | β¬οΈ +107% |
search_S |
$4.2K/week | $8.5K/week | β¬οΈ +102% |
print_S |
$4.3K/week | $8.5K/week | β¬οΈ +98% |
facebook_S |
$2.2K/week | $4.3K/week | β¬οΈ +95% |
git clone https://github.com/jmeza-data/Robyn_Marketing_Mix_Modeling.git
cd Robyn_Marketing_Mix_Modelinginstall.packages("remotes")
remotes::install_github("facebookexperimental/Robyn/R")
install.packages("reticulate")
reticulate::py_install("nevergrad", pip = TRUE)source("MMM.R")
β οΈ robyn_run()with 5 trials Γ 2,000 iterations takes approximately 25β30 minutes depending on hardware.
| Tool | Version |
|---|---|
| R | β₯ 4.4.1 |
| Robyn | 3.12.1 |
| Python | β₯ 3.9 |
| nevergrad | 1.0.12 |
| reticulate | β₯ 1.46 |
- OOH is significantly over-invested β absorbing 61.9% of media budget while generating only 34.2% of effect
- Search and Print show the highest efficiency β generating 3x and 2x their spend share respectively
- TV shows healthy carryover β 58% of its impact persists beyond the week of investment
- Budget reallocation from OOH toward TV and Search could increase media revenue by +27.8% with zero additional spend
Built as part of NIQ Analyst preparation Β· April 2026 Β· BogotΓ‘, Colombia






