For technical readers

This page is the methodology overview — what Robyn produces, how analysts call it, and how the four-component bridge translates a Robyn fit into a Bayes Server structural causal model.

If you want the code-level detail — public APIs, file structure, the GitHub repository — see the Components page. If you're evaluating whether to engage rather than how it works, see the Strategy page.

Most explanations of Robyn jump straight to hyperparameter tuning and Pareto fronts. This page walks the other way — what the tool actually does for a marketer, why it exists at all, and where its limitations open the space for a causal layer on top.

Robyn takes weekly numbers and tells us what each marketing channel is doing for sales.

We give it a spreadsheet that has, for every week of the last two or three years: how much we sold, how much we spent on TV, how much on Facebook, how much on Google, how much on each other channel, and a few side things like price, promotions, and holidays. Robyn looks across all those weeks and figures out, for each channel, two things: how much sales each dollar of spend produces, and what the best mix would be if we were redoing the budget today.

The output we get back is essentially three pictures per channel:

  • A response curve — "if you spend $X per week on TV, you get $Y of incremental sales."
  • A contribution chart — "of last year's total sales, this much came from TV, this much from Facebook, this much from price, this much would have happened with no marketing at all."
  • A recommendation — "you spent $50M last year split this way; here's the better split."

That's it. It's not magic. It's a regression — the same statistical machinery we'd see in a stats class — wrapped in a bunch of marketing-specific machinery that captures things like "TV ads keep working for a few weeks after the spot runs" and "the tenth million you spend on Google search isn't worth what the first million was."

Meta wrote and open-sourced Robyn between 2020 and 2023 for a specific reason. The old way of measuring marketing — tracking individual users across the web through cookies and mobile IDs — broke between 2021 and 2024 because of Apple's privacy changes and tightening regulation. Once we can't follow individual users, we can't do "this person clicked this ad and then bought." All that's left is the aggregate view: "we spent this much last week and sold this much."

That aggregate view is what marketing-mix modeling has always been. It used to be unfashionable because the user-tracking approach felt more modern. Once tracking broke, MMM was suddenly the only working method, and there was a sudden need for tooling the average analyst could actually use.

Robyn was Meta's contribution to that — open-sourcing a working MMM so that any company could run one without paying $200K to Nielsen or Analytic Partners. Meta's commercial interest is roughly: if advertisers can measure their marketing properly, they spend more on the channels that work, and Meta is one of those channels. Open-sourcing the tool helps the whole ecosystem rebuild measurement on the post-tracking foundation, which is good for the channels with a real causal effect — including Meta's.

Google did the same thing

Google open-sourced Meridian in 2024, with the same underlying logic. Aggregate measurement is the future; give the industry a working tool; the channels with real effects benefit when measurement gets honest. Meta and Google publishing competing open-source MMM tools in the same eighteen-month window is the clearest signal possible that the industry has settled the methodology question — even if individual advertisers haven't caught up yet.

Robyn is an R package. We install it, we load it, we run it.

The way we interact with Robyn is by writing R code that says "here's my data, here are the channels, here are the constraints, run the model." We don't click buttons. We write maybe 100–200 lines of R that configure the run, then we call the main fitting function, then we call output functions that produce the response curves and the budget recommendations.

We'd do this in RStudio (the standard R editor) running on a laptop or a server. The fitting takes anywhere from 20 minutes to several hours depending on how many channels we have and how thorough we want the search to be. When it's done, Robyn writes a folder with charts (PNG files), a JSON file describing the chosen model, and a CSV of the budget recommendations.

The typical workflow

1

Prepare the data

A CSV with weekly rows. One column per media channel (spend), one for sales, columns for price, promotions, holidays, and any other controls.

2

Configure the run in R

Open RStudio. Write the configuration: which columns are media, which are controls, which are calibration constraints from our experiments. This is the part that benefits most from an experienced analyst — it's where domain knowledge enters the model.

3

Run robyn_run() and wait

The fitting kicks off a hyperparameter search across thousands of candidate models. Twenty minutes for a small model; several hours for a large one. Output is a folder of charts and JSON files.

4

Pick a model from the Pareto front

Robyn produces a "Pareto front" — a few dozen candidate models trading off statistical fit against decomposition stability. We pick one based on the diagnostics. This is judgment, not automation.

5

Run robyn_allocator()

Against the chosen model, get the budget recommendation. Inspect the response curves. Decide whether to act.

It's not a polished SaaS product. It's research-grade software for analysts who can read R code and understand what a regression coefficient means. That's a real barrier — marketing teams without an analyst on staff can't use Robyn directly.

Worked example

A reproducible synthetic dataset, the Robyn run script, and the standalone SCM all live in mmm-bayes/. Because the data is generated from a known structural causal model, the true causal ROIs are knowable in advance: $2.00 per $ of TV, $4.00 per $ of Search, $0.00 for newsletter (a placebo). A naive Robyn fit will systematically overstate TV and Search ROI by roughly 40-55%. That gap is what the bridge tool exists to close.

What's built and runnable today:

  • robyn_dataset.csv — 200 weeks (2022-01-03 to 2025-10-27) in Robyn's input schema.
  • robyn_run.R — end-to-end Robyn fit, Pareto selection, allocator, model save.
  • build_robyn_dataset.py — generates the Robyn-shaped CSV from the underlying SCM data.
  • verify_robyn_diagnostic.py — OLS sanity check on the dataset before Robyn runs.
  • MarketingMixSCM-AllRungs.bayes — the standalone Bayes Server SCM, hand-built with the same structural truth that generated the dataset. Demonstrates the three Pearl-ladder queries and produces the corrected ROIs the bridge tool aims to compute automatically.
  • robyn_dataset_README.md — schema, derivation, and the truth-vs-naive comparison.

What's not built yet (the bridge components themselves):

  • Component 1 — Reader. Reads the JSON from robyn_write() and extracts channel coefficients, adstock decays, saturation curves, calibration constraints. Build target: next.
  • Component 2 — SCM constructor. Translates the Robyn fit into a Bayes Server .bayes file with the latent confounder added.
  • Component 3 — Query runner. Runs the three Pearl-ladder queries and produces the corrected ROIs and per-campaign attribution.
  • Component 4 — Shiny app. The interactive front-end with sensitivity sliders, scenario planner, and audit report.

The current artifacts demonstrate the methodology with the SCM hand-built; the bridge automates the Robyn → SCM translation. The end state is a Shiny app: an analyst points it at a Robyn fit, the bridge produces the corrected audit, the analyst takes that to the budget meeting.

Robyn is an R package. Calling it from R is the only supported way to use it. We install it from CRAN or GitHub, load it with library(Robyn), and we have access to all its functions.

# Install once install.packages("Robyn") # Or for the development version: remotes::install_github("facebookexperimental/Robyn") # Use it library(Robyn)

There is no Python version, no command-line tool, no web interface. If we want to use Robyn, we use it from R. Some teams wrap it in Shiny apps to give non-technical users a click-through experience, but those are custom builds — not part of Robyn itself.

Practical notes about the R dependency

Robyn pulls in a number of other packages — glmnet for the regression, nevergrad via Python for the hyperparameter search, prophet for trend and seasonality decomposition. The Python dependency through nevergrad means we actually need both R and Python installed, with the Python bridge configured. This is annoying the first time and routine after that, but it's a real onboarding friction worth flagging — particularly for organizations whose IT teams treat any new language runtime as a significant approval hurdle.

The bridge tool is essentially a layer that sits between Robyn's output and the marketing decision-maker. Robyn does what it does well — fit a regression, produce response curves, recommend a budget. The bridge takes that output and answers a different class of question: not "what does the data look like?" but "what would happen if we intervened?" and "what would have happened if we hadn't?"

Four components.

Component 1
A reader
A short R script — maybe 200 lines — that takes Robyn's output object (the saved model and its associated data) and pulls out the pieces we need: channel coefficients, adstock half-lives, saturation curves, calibration constraints if any. Plain R code calling Robyn's accessor functions. Nothing exotic.
Component 2
An SCM constructor
The new part. A program that takes the structured output from the reader and builds a Bayes Server .bayes file representing the same fitted relationships, but with the back-door confounder added explicitly. For each channel: create three nodes — spend, adstock, noise term. Add the latent demand state as a root node with arrows into every spend node and into sales. Set conditional distributions to match Robyn's fit at the operating point. To talk to Bayes Server from R, the standard route is the rJava package; the alternative is to write the .bayes file as XML directly and load it separately.
Component 3
A query runner
Once the SCM is built, this component runs the three Pearl-ladder queries: observational (matches what Robyn says), interventional (the back-door-corrected ROI), and counterfactual (per-campaign attribution). Calls to Bayes Server's inference engine through the Java bridge. Output is a structured object: corrected ROIs per channel, attribution decompositions per campaign, sensitivity sweeps across the latent-strength assumption.
Component 4
The front-end
Either a static report (PDF or HTML) summarizing the corrected output, or a Shiny app letting the user interact with the results — drag the latent-strength slider, watch the response curves move, run scenario analyses on proposed budget reallocations.

From the analyst's perspective

The whole thing, end-to-end, looks like this:

  1. Run Robyn the normal way, get a fitted model.
  2. Run the bridge tool — something like bridge_audit(robyn_output). Takes a few minutes: building the SCM, running the queries, producing the report.
  3. Open the report or the Shiny app. See what Robyn said versus what the bridge says, with the gap explained.
  4. Take that to the budget meeting.
Robyn is the working horse that does the regression part of MMM well; the bridge is the layer that takes Robyn's output and asks the causal questions Robyn doesn't ask.
— Working principle for the bridge tool

The licensing constraint that shapes the product

The Bayes Server license is the one piece that can't be replaced by open-source. Bayes Server is commercial software with per-seat licensing. For a consulting practice this is fine — we license seats for our consultants. For a self-serve product distributed to clients it's awkward, because every end-user needs a license.

The likely product shape, given that constraint, is consultant-fronted: the consultancy holds the Bayes Server licenses, the client gets the Shiny app and the report, the back-end runs on the consultancy's infrastructure. Building the bridge as a SaaS available to anyone with a credit card requires either a different inference engine or a different licensing arrangement with Bayes Server.

Honest scope

Building this bridge is not a one-week project. The reader is a few days. The SCM constructor is two to four weeks of careful work, because the translation from a fitted Robyn model to a structurally-explicit SCM has judgment calls that have to be made deliberately. The query runner is straightforward once the model is built. The front-end is whatever we want it to be — a basic Shiny app is a week, a polished one is a month.

Plan for two to three months of focused build to have something a paying client could meaningfully use.

That's the picture. Both pieces matter — the bridge alone, without something doing the underlying fit, would be re-implementing what Robyn already does well, which is not the right place to put our effort. The leverage is in the layer Robyn doesn't have, not in rebuilding the layer Robyn has.

Next Step

A team running Robyn and asking what causal questions it doesn't answer is the right starting point for a bridge conversation.

info@rung3.ai

Meta, 2023, Robyn (open-source MMM, R package on CRAN and GitHub) · Google, 2024, Meridian (open-source Bayesian MMM, Python) · Bayes Server, Java and .NET API documentation · Urbanek, S., rJava: Low-level R to Java interface · Facebook Open Source, Robyn project documentation and tutorials.