Meridian provides automated prior calibration using past experiments with
CalibrationBuilder to automate the translation of
incrementality experiment results into ROI priors for paid media and reach &
frequency channels. The builder accepts results from any experiment source,
featuring direct integration for Meridian GeoX to streamline
the workflow.
Calibration
requires defining a Meridian
prior, and incrementality
experiment results are a strong way to drive that intuition. However, MMMs and
experiments differ in important ways: specifically in their scope, timing and
duration. To help you bridge this gap the CalibrationBuilder is designed to
automatically account for these differences, translating your experiment results
into robust priors.
CalibrationBuilder resolves these differences by automatically applying
adjustments to the experiment results before merging them into a single
calibrated prior distribution per channel.
The workflow consists of:
- Registering experiments: User adds generic or Meridian GeoX experiment results to a channel.
- Applying adjustments:
CalibrationBuildercomputes and applies spend, recency, and duration adjustments. - Merging distributions:
CalibrationBuildercombines the adjusted distributions from all registered experiments using Bayesian updating. - Fitting parametric distributions:
CalibrationBuilderfits a parametric distribution family (LogNormal, Truncated Normal, Gamma, or Normal) to the posterior to produce the finalroi_mandroi_rfprior distributions.
Step 1: Registering experiments
You can register experiments using the CalibrationBuilder Python API. The
builder supports two types of experiment sources:
- Meridian GeoX Experiments: Registered using
with_meridian_geox_experiment_result. Directly accepts theAnalysisResultobject from Google's GeoX tool.CalibrationBuilderautomatically extracts the point estimate, standard error, spend, and experiment dates from theAnalysisResultto compute adjustments. - Generic Experiments: Registered using
with_incrementality_experiment_result. Useful for non-GeoX experiments where you manually specify the point estimate, standard error, spend, and dates.
For complete interactive code walkthroughs, see the TensorFlow Colab or JAX Colab.
Step 2: Applying calibration adjustments
An experiment and an MMM have different measurement goals and conditions. To bridge this gap, Meridian adjusts the experiment's point estimate (scaling it by a factor \(\gamma\)) and increases the standard error (adjusting variance by a factor \(\tau\)) to reflect the additional uncertainty of translating the experiment to the MMM.
The adjusted mean (\(\mu_{adj}\)) and standard deviation (\(\sigma_{adj}\)) for a single experiment are calculated as:
Where:
- \(\mu_{exp}\) is the experiment point estimate.
- \(\sigma_{exp}\) is the experiment standard error.
- \(\gamma_{duration}\) is the duration scaling factor (automatically computed; baseline is \(1.0\) when the experiment captures 100% of the adstock effect).
- \(\gamma_{user}\) is an optional user-specified point estimate adjustment (default is \(0\)).
- \(\tau_{spend}\), \(\tau_{recency}\), and \(\tau_{duration}\) are the variance adjustments for spend, recency, and duration respectively (automatically computed; baseline is \(0.0\) when no adjustment is needed).
- \(\tau_{user}\) is an optional user-specified standard error adjustment (default is \(0\)).
Automation and defaults
While \(\gamma_{user}\) and \(\tau_{user}\) allow manual fine-tuning and default
to \(0\), the other adjustments (\(\tau_{spend}\), \(\tau_{recency}\),
\(\tau_{duration}\), and \(\gamma_{duration}\)) are calculated automatically by
CalibrationBuilder:
- Meridian GeoX Experiments: The adjustment calculation is fully
automated.
CalibrationBuilderdirectly extracts \(\mu_{exp}\) and \(\sigma_{exp}\) from the GeoXicpdmetrics (metrics.icpd.point_estimateandmetrics.icpd.standard_deviation), the experiment spend fromestimated_bau_spend(metrics.descriptive_metrics.estimated_bau_spend), and the start and end dates fromanalysis_config(analysis_config.analysis_start_dateandanalysis_config.analysis_end_date). Non-revenue KPI experiments are automatically converted to the revenue scale using the model'srevenue_per_kpi. You don't need to manually supply spend, duration, or date parameters. - Generic Experiments:
CalibrationBuildercalculates the adjustments using the identical formulas from the spend, start date, and end date arguments you provide inwith_incrementality_experiment_result. - Model Defaults: Duration calculations use the
CalibrationBuilderdecay parameters, which default toadstock_decay_spec='geometric',alpha=0.5, andmax_lag=8(matching theModelSpecdefaults). Recency calculations use a fixed half-life of 52 weeks (1 year).
Spend adjustment
The spend adjustment (\(\tau_{spend}\)) accounts for the differences in spend scale and intensity. An experiment typically covers only a fraction of the total spend observed in the MMM window. To compare spend scale independently of experiment duration, Meridian compares the average daily spend of the experiment with the average daily spend of the channel across the modeled period.
For Meridian GeoX experiments, the experiment spend is extracted automatically
from estimated_bau_spend in the GeoX AnalysisResult (under
metrics.descriptive_metrics.estimated_bau_spend).
The spend adjustment is calculated as:
Where \(r\) is the spend ratio comparing average daily spend rates:
Where:
- \[\text{experiment_avg_daily_spend} = \frac{\text{experiment_total_spend}}{\text{experiment_duration_days}}\]
\[\text{channel_avg_daily_spend} = \frac{\text{total_channel_spend}}{\text{model_duration_days}}\]
If the experiment daily spend rate matches the channel daily spend rate (\(r = 1.0\)), then \(\tau_{spend} = 0.0\) (no added uncertainty).
As the experiment spend rate becomes a smaller (or larger) fraction of the channel spend rate (\(r \rightarrow 0\)), \(\tau_{spend}\) increases, which widens the prior distribution.
The spend ratio \(r\) also accounts for differences in media granularity. For example, if you run a campaign-level experiment but model at the channel level in the MMM, the experiment spend rate will be compared to the total channel spend rate. If the campaign represents a large portion of the channel's activity, the campaign will be more representative of the channel and there is less uncertainty when translating the results. Conversely, if it is a small campaign, the adjustment will be larger to reflect the uncertainty of scaling that campaign's lift to the entire channel.
Recency adjustment
The recency adjustment gives more weight to more recent experiments as these may be more accurate to model up-to-date incremental outcomes. The further in the past the experiment was conducted relative to the end of the MMM modeling period, the less likely its results reflect the current business reality.
For Meridian GeoX experiments, the experiment end date is extracted
automatically from analysis_config.analysis_end_date in the GeoX
AnalysisResult.
The recency adjustment is calculated using an exponential decay with a half-life of 52 weeks (1 year):
Where \(w\) is the number of weeks passed between the experiment end date and the last modeled date in the MMM.
- If the experiment ended at the last modeled date (\(w = 0\)), then \(\lambda = 1.0\) and \(\tau_{recency} = 0.0\).
- For older experiments, \(\lambda\) decreases, causing \(\tau_{recency}\) to increase and add more uncertainty.
- If the last modeled date falls before the experiment, no adjustment is applied (\(\tau_{recency} = 0.0\)).
Duration adjustment
The duration adjustment (\(\gamma_{duration}\) and \(\tau_{duration}\)) accounts for the difference between the experiment's duration (\(D\), in weeks) and the model's maximum lag window (\(L\), in weeks).
For Meridian GeoX experiments, the experiment duration (\(D\)) is computed
automatically from analysis_config.analysis_start_date and
analysis_config.analysis_end_date in the GeoX AnalysisResult.
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. Conversely, if the experiment is very long, it might capture effects beyond the model's truncated lag window.
Meridian calculates the capture proportion (\(p\)), which is the proportion of total adstock decay weights captured during the experiment's active weeks.
Let \(w_s\) be the decay weights calculated using the adstock decay function
(geometric or binomial) with decay rate \(\alpha\) over the model window \(L +
1\) (configured on CalibrationBuilder, defaulting to
adstock_decay_spec='geometric', alpha=0.5, and max_lag=8):
- If the experiment duration is shorter than or equal to the model window (\(D
\le L + 1\)):
- Binomial and Geometric Decay: The capture proportion \(p\) is the sum of the normalized decay weights up to \(D\):
- If the experiment duration is longer than the model window (\(D > L + 1\)):
- Binomial Decay: Binomial weights decay to zero within the lookback window, so the experiment captures all possible effects: \(p = 1.0\)
- Geometric Decay: Geometric weights decay infinitely, so the numerator includes the tail of the geometric series up to \(D - 1\):
The capture proportion \(p\) is bounded to a minimum value of \(10^{-6}\) and a maximum value of \(1.0\) (for binomial decay).
Using \(p\), the duration adjustments are:
- Point estimate scaling factor:
If the experiment is shorter than the model window (\(p < 1.0\)), the point estimate is scaled up (\(\gamma_{duration} > 1.0\)) to estimate the full long-term effect. If the experiment is longer (\(p > 1.0\) for geometric decay), the point estimate is scaled down (\(\gamma_{duration} < 1.0\)).
- Standard error adjustment:
If the experiment is shorter (\(p < 1.0\)), add uncertainty (\(\tau_{duration} > 0.0\)) because the unobserved tail of the effect is extrapolating. If the experiment is longer or equal (\(p \ge 1.0\)), no additional uncertainty is added (\(\tau_{duration} = 0.0\)).
Step 3: Merging experiments
If you register multiple experiments for a single channel, Meridian combines
them (along with an optional baseline_prior) using Bayesian updating.
By Bayes' theorem, the posterior density of the channel ROI is proportional to the product of the baseline prior and the likelihoods of all independent experiments:
Where the likelihood function for each experiment \(i\) is:
Note that we can think of this product definition as its own Bayesian model. Mathematically, we treat each adjusted experiment as a noisy observation of the true channel ROI. The model is formulated as:
Where:
- \(\mu_{adj,i}\) is the adjusted point estimate for experiment \(i\).
- \(\sigma_{adj,i}\) is the adjusted standard error for experiment \(i\).
- \(\text{ROI}\) is the true, unknown ROI parameter to be estimated for the channel.
- \(\pi(\cdot)\) is the
baseline_priordistribution. If no baseline prior is specified, an improper flat uniform prior over positive real numbers is used (\(\pi(\text{ROI}) \propto 1\) for \(\text{ROI} > 0\)). - \(N\) is the number of registered experiments.
The builder evaluates this posterior density numerically on an adaptive parameter grid to find the combined distribution. See the Technical Appendix for more details.
Step 4: Fitting and building the calibrated prior
Finally, Meridian fits a standard parametric distribution family (Truncated
Normal, LogNormal, Gamma, or Normal) to the numerical posterior distribution
computed in Step 3. Candidate distribution families are chosen based on the
baseline_prior: Truncated Normal is evaluated for baseline priors with
non-negative support (the default), whereas Normal is evaluated when the
baseline prior permits negative support. In either case, LogNormal and Gamma are
also evaluated if the posterior mass on negative values does not exceed 10%. The
best-fitting distribution shape is chosen by minimizing the cross-entropy loss
(equivalent to minimizing the KL divergence) against the numerical posterior.
Once the optimal prior distribution is found for each calibrated channel,
CalibrationBuilder wraps them. For any channels that did not undergo
calibration, CalibrationBuilder assigns the custom prior provided in
custom_prior. The default ROI prior of \(\text{LogNormal}(0.2, 0.9)\) is only
used if a custom prior is not provided for that channel.
The final output of build() is a CalibratedPriors dataclass containing:
priors.roi_m: ACalibratedDistribution(subclass ofIndependentMultivariateDistribution) representing the calibrated prior for paid media channels.priors.roi_rf: ACalibratedDistribution(subclass ofIndependentMultivariateDistribution) representing the calibrated prior for reach & frequency channels.
These calibrated distributions are passed to PriorDistribution and then to
ModelSpec to initialize the Meridian model.
Technical Appendix
This section provides the mathematical formulations and algorithmic details
underlying the CalibrationBuilder numerical posterior computation and
distribution fitting.
Posterior Distribution Formulation
For a given channel, let \(\theta\) represent the true channel ROI. Observe \(N\) independent adjusted experiment results. For each experiment \(i \in \{1, \ldots, N\}\), there is an adjusted point estimate \(\mu_{adj,i}\) and an adjusted standard error \(\sigma_{adj,i}\).
Assume each adjusted point estimate is a normally distributed observation around the true ROI:
The likelihood function for the \(i\)-th experiment is:
If a baseline_prior is provided, denote its probability density function as
\(\pi(\theta)\). If no baseline prior is provided, use an improper flat uniform
prior over positive values, \(\pi(\theta) \propto I_{\{\theta > 0\}}\), where
\(I\) is the indicator function.
By Bayes' theorem, the posterior density of the channel ROI, \(p(\theta \mid \{\mu_{adj,i}, \sigma_{adj,i}\})\), is proportional to the product of the prior and the likelihoods of all independent experiments:
Grid-Based Numerical Integration
Since the posterior distribution \(p(\theta \mid \{\mu_{adj,i}, \sigma_{adj,i}\})\) may not have a standard analytical form (such as when using non-Normal baseline priors like LogNormal or Gamma), Meridian evaluates it numerically on a grid.
- Scouting Pass: Meridian first performs a "scouting" pass to locate the region of high probability mass. It defines a broad grid centered around the empirical mean of the distributions and finds the range containing \(99.8\%\) of the cumulative probability (from the \(0.1\)-th percentile to the \(99.9\)-th percentile).
- Fine Grid Evaluation: It then constructs a fine grid of 10,000 equally spaced points over this resolved range \([\theta_{\text{min}}, \theta_{\text{max}}]\) and evaluates the unnormalized posterior density at each point.
Normalization: The density is normalized using Riemann sum integration:
$$ p(\theta_j \mid \{\mu_{adj,i}, \sigma_{adj,i}\}) = \frac{u(\theta_j)}{\sum_k u(\theta_k)\Delta\theta} $$where \(u(\theta)\) is the unnormalized posterior density, \(\theta_j\) is the \(j\)-th grid point, and \(\Delta\theta\) is the step size.
Distribution Fitting
Once the numerical posterior PDF is computed on the grid, Meridian fits a parametric distribution \(q(\theta; \phi)\) (where \(\phi\) represents the distribution parameters) to approximate the posterior.
Meridian determines candidate distribution families based on the support of the
baseline_prior:
- Non-negative support (Default): If no
baseline_prioris provided (which defaults to non-negative support) or if thebaseline_priorrestricts support to non-negative values (such asLogNormalorGamma), Meridian considers Truncated Normal (left-truncated at zero: \(\text{low}=0\), \(\text{high}=\infty\), restricting support to \([0, \infty)\)) and does not consider Normal. - Negative support: If the
baseline_priorassigns finite probability density to negative values (such asNormal), Meridian considers Normal (defined on \((-\infty, \infty)\)) and does not consider Truncated Normal. - LogNormal and Gamma: For both cases, LogNormal (\((0, \infty)\)) and Gamma (\((0, \infty)\)) are also evaluated as candidate families provided that the fraction of posterior probability mass in the negative region (\(\theta < 0\)) does not exceed \(10\%\).
For each candidate family, Meridian finds the parameters \(\phi\) that minimize the cross-entropy loss between the numerical posterior \(p(\theta)\) and the candidate distribution \(q(\theta; \phi)\):
Minimizing this loss is mathematically equivalent to minimizing the Kullback-Leibler divergence \(D_{KL}(p \parallel q)\) from the approximation \(q\) to the true numeric posterior \(p\).
Meridian uses the L-BFGS-B optimization algorithm to find the optimal parameters. The distribution family that achieves the lowest loss is selected as the final calibrated prior for the channel.