Choose and configure treatment prior types

In Meridian, there are multiple treatment variable types —namely paid media, organic media, or non-media treatments. For each treatment type, you can specify a prior type. A prior type is the specific metric—such as ROI, mROI, Contribution, or Coefficient—on which you set your prior belief. You can choose the metric for which you have the most business knowledge (e.g. from experiments) or the metric that you care most about when interpreting the model results.

Meridian sets a default prior distribution with each prior type based on some general business rationale. The default distribution can be overridden based on your specific domain expertise to better align the prior with your own business intuition. Understanding these options and the reasoning behind them is critical for incorporating domain expertise into Meridian.

Prior type definitions

Here are definitions of the prior types available in Meridian:

  • ROI (Return on Investment): The ratio of incremental outcome driven by a channel to the cost of that channel's media spend (Incremental Outcome / Spend). This is often the most intuitive metric for paid media, especially when calibrating with experiment results.
  • mROI (Marginal ROI): The return on investment for one additional monetary unit (for example, one dollar) of spend on a given channel. This is useful when thinking about budget optimization, as channels with higher mROI are good candidates for receiving more budget.
  • Contribution: The proportion of the total outcome that is attributable to a channel (Incremental Outcome / Total Outcome). Whereas ROI and mROI priors can only be used for paid media, contribution priors can be used for channels where there is no associated spend, such as organic channels or non-media treatments.
  • Coefficient: The underlying statistical coefficient for a given treatment in Meridian's regression model. Unlike ROI, mROI, and Contribution—which are business metrics—the coefficient is a more abstract statistical parameter that is difficult to translate into business terms without context from other model parameters and data.

The following table summarizes which prior types can be used with each treatment type.

Prior Type Paid Media Organic Media Non-media Treatments
ROI Yes* No No
mROI Yes* No No
Contribution Yes Yes Yes
Coefficient Yes Yes Yes

Business language examples

To make these concepts clearer, here's how you might express a prior for each type in plain business language:

  • Setting an ROI prior:

    "Based on our latest lift study, we're confident that our Search ads generate about $1.50 in revenue for every dollar we spend. I want the ROI prior to be centered around that value."

  • Setting an mROI prior:

    "If we were to spend one more dollar on Social Media ads, we'd expect to get back about $1.10 at our current spend level. I want the mROI prior to be centered and tightly distributed around that value."

  • Setting a Contribution prior:

    "We believe our digital video ads are responsible for about 5% of our total revenue. I want the contribution prior to be centered around that value."

  • Setting a Coefficient prior:

    This is less common for business users. It's like saying: "I believe the underlying regression beta for this variable should be 0.02." This is typically reserved for data scientists with specific statistical goals, as the interpretation depends heavily on the scaling of the input data and output metric.

Considerations for choosing treatment prior types

In this section, we cover the business and modeling rationale for picking different prior types across paid media, organic media and non-media treatments.

ROI priors are the default because they usually align best with prior knowledge, such as experiment results. This is usually the most intuitive option for setting reasonably well informed priors.

mROI priors can often be an attractive option when a lot of prior knowledge went into setting historical budgets or for advertisers who want more conservative budget recommendations. They work by imposing a prior capable of shrinking the optimal budget allocation toward the historical budget allocation, thereby regularizing the recommended budget shifts. This can be accomplished by setting a common mROI prior mean on all channels and adjusting the standard deviation. The stronger the prior (smaller standard deviation), the closer the optimal allocation will get to historical and the smaller the recommended budget shifts. Note that optimization spend constraints offer another way to limit recommended budget shifts, which can obviate the need for mROI priors. For more details, see subsection "Use mROI priors for budget regularization".

Contribution priors are very similar to ROI priors for paid media. The only difference is that the ROI prior denominator is channel spend, whereas the contribution prior denominator is total observed outcome. This means that any contribution prior can be translated to an ROI prior, and any ROI prior can be translated to a contribution prior for paid media.

Coefficient priors are the more traditional parameterization for a linear regression model. In the context of MMM, the interpretation of a coefficient is somewhat abstract, which makes it difficult to set an informed prior. A particular coefficient value can imply significantly different ROI values for different paid media channels, since the ROI depends on the channel's execution distribution over geos and time periods, the estimates of the channel's adstock and diminishing returns parameters, and the channel's cost per media unit.

Additional considerations for non-revenue outcome

When the outcome is non-revenue (when the KPI is not in monetary units and revenue_per_kpi is not provided), the availability and interpretation of paid media priors changes. Each parameter of PriorDistribution has a default distribution. There are two exceptions where the default is not used, and both occur when the outcome is non-revenue.

ROI priors function differently because a monetary ratio cannot be calculated. Instead, when you use media_prior_type = 'roi', the default prior is placed on the total contribution of all paid media channels. This lets you set a prior on the total proportion of the non-monetary KPI driven by paid media. When ROI priors are used, then the default is assigned according to a special total paid media contribution methodology.

mROI priors represent the marginal return in terms of outcome units per dollar (for example, additional sign-ups per dollar). Because this value is highly dependent on the specific KPI, a universal default is impractical. Consequently, Meridian does not provide a default prior for mROI in non-revenue cases and requires you to specify a custom prior based on your domain knowledge. In these cases, a custom distribution must be provided. There is no default because the reasonable range of values will vary greatly for each business.

Contribution priors are often a practical choice for non-revenue outcomes because they represent the proportion of the total outcome attributable to a channel. This definition remains consistent regardless of whether the outcome is revenue or non-revenue.

Organic media considerations

Contribution priors are the default option because they are the most intuitive quantity for setting an informed prior. Some channels might be expected to have greater contributions than others, so consider customizing the prior distribution in a way that makes sense for your business and marketing tactics. A Beta distribution often makes sense because it is constrained to the interval zero to one.

Coefficient priors are the more traditional parameterization for a linear regression model. Similar to paid media, the interpretation of a coefficient is somewhat abstract, which makes it difficult to set an informed prior. A particular coefficient value can imply significantly different contribution values for different organic media channels, since the contribution depends on the channel's execution distribution over geos and time periods and the estimates of the channel's adstock and diminishing returns parameters.

Non-media treatments considerations

Contribution priors are the default option because they are the most intuitive quantity for setting an informed prior. It is always a good idea to configure the prior distribution. Depending on each variable's specified baseline value, you might expect the contribution to be positive or negative, or the sign of the contribution might be unknown. For example, it may not be clear whether setting the price to a given baseline value would have a positive or negative impact on revenue. Or perhaps you have a prior expectation that price has a positive impact under one baseline price, but a negative impact under a different baseline price.

Coefficient priors are the more traditional parameterization for a linear regression model. Similar to paid media and organic media, the interpretation of a coefficient is somewhat abstract, which makes it difficult to set an informed prior. A particular coefficient value can imply significantly different contribution values for different non-media treatment channels, since the contribution depends on the treatment's distribution of values over geos and time periods and the baseline treatment value.

Flowchart for choosing treatment prior types

The following flowchart details the aforementioned considerations you should make when deciding on which treatment prior type you'd like to select.

Flowchart detailing considerations for choosing the right prior type given a certain treatment

Configure treatment prior types

In this section, we cover the available prior types for paid media, organic media, and non-media treatments, as well as different considerations for configuring them in the Meridian Library. We provide several code snippets and examples for configuring prior types across the treatment types.

Configure paid media priors

The prior type of paid media is specified by the media_prior_type and rf_prior_type arguments of ModelSpec. The following table shows which PriorDistribution parameters are associated with each prior type.

media_prior_type/rf_prior_type Parameter in PriorDistribution
'roi' * (default) roi_m*, roi_rf*
'mroi'* mroi_m*, mroi_rf*
'contribution' contribution_m, contribution_rf
'coefficient' beta_m, beta_rf

The following section provides hypothetical examples of how you might configure these priors for a model with two paid media channels. The bullets explain the reasoning behind the example prior settings in the code block that follows. The default distributions are also provided as reference point to understand the configuration process for each prior type.

  • ROI (roi_m): Configured here with LogNormal distributions means at 1.7 and 2.5 to align with experimental lift studies.

    For reference, the default distribution uses LogNormal(0.2, 0.9), with a mean of 1.22 and median of 1.83.

import tensorflow_probability as tfp
from meridian.model import spec, prior_distribution
# -----------------------------------------------------------------------------
# Option 1: ROI (Return on Investment)
# -----------------------------------------------------------------------------
# ROI (LogNormal) -> Means at 1.7 and 2.5
prior = prior_distribution.PriorDistribution(
    roi_m=prior_distribution.PriorDistribution.lognormal_dist_from_mean_std(
        mean=[1.7, 2.5], std=[0.3, 0.5]
    )
)
model_spec = spec.ModelSpec(prior=prior, media_prior_type='roi')
  • mROI (mroi_m): Configured with tight distributions means at 1.0. A common mean and small standard deviation were selected for both channels to help regularize budget optimization. A mean of 1.0 was selected because both channels are thought to be near saturation.

    For reference, the default distribution uses LogNormal(0.0, 0.5), with a mean of 1.13 and a median of 1.

import tensorflow_probability as tfp
from meridian.model import spec, prior_distribution
# -----------------------------------------------------------------------------
# Option 2: mROI (Marginal Return on Investment)
# -----------------------------------------------------------------------------
# mROI (LogNormal) -> Means at 1.0
prior = prior_distribution.PriorDistribution(
    mroi_m=prior_distribution.PriorDistribution.lognormal_dist_from_mean_std(
        mean=[1.0, 1.0], std=[0.2, 0.2]
    )
)
model_spec = spec.ModelSpec(prior=prior, media_prior_type='mroi')
  • Contribution (contribution_m): Uses Beta distributions to model specific "shares of effect" to 3% and 4%.

    For reference, the default distribution uses Beta(concentration1=1.0, concentration0=99.0) and has a mean 1%.

import tensorflow_probability as tfp
from meridian.model import spec, prior_distribution
# -----------------------------------------------------------------------------
# Option 3: Media Contribution
# -----------------------------------------------------------------------------
# Contribution (Beta) -> Means at 3% and 4%
prior = prior_distribution.PriorDistribution(
    contribution_m=tfp.distributions.Beta(
        concentration1=[3.0, 4.0], concentration0=[97.0, 96.0]
    )
)
model_spec = spec.ModelSpec(prior=prior, media_prior_type='contribution')
  • Coefficient (beta_m): Uses HalfNormal distributions with tighter scales (1.0 and 1.5) to apply statistical regularization.

    For reference, the default distribution is Normal(0, 5) and is considered a weakly informative prior.

import tensorflow_probability as tfp
from meridian.model import spec, prior_distribution
# -----------------------------------------------------------------------------
# Option 4: Media Coefficient
# -----------------------------------------------------------------------------
# Coefficient (HalfNormal) -> Scales at 1.0 and 1.5
prior = prior_distribution.PriorDistribution(
    beta_m=tfp.distributions.HalfNormal(scale=[1.0, 1.5])
)
model_spec = spec.ModelSpec(prior=prior, media_prior_type='coefficient')

Configure organic media priors

The prior type of organic media is specified by the organic_media_prior_type and organic_rf_prior_type arguments. The options are 'contribution' and 'coefficient', with 'contribution' being the default.

organic_media_prior_type/organic_rf_prior_type Parameter in PriorDistribution
'contribution' (default) contribution_om, contribution_orf
'coefficient' beta_om, beta_orf

Organic media configuration examples

This section provides code samples for configuring different prior types for organic media treatments. The bullets explain the reasoning behind the example prior settings in the code block that follows. The default distributions are also provided as reference point to understand the configuration process for each prior type.

  • Contribution (contribution_om): Set a Beta distribution with mean 3%.

    For reference, the default distribution is Beta(1.0, 99.0) and has a mean 1%.

import tensorflow_probability as tfp
from meridian.model import spec, prior_distribution
# -----------------------------------------------------------------------------
# Option 1: Organic Media Contribution
# -----------------------------------------------------------------------------
# Contribution (Beta) -> Mean at 3%
prior = prior_distribution.PriorDistribution(
    contribution_om=tfp.distributions.Beta(
        concentration1=[3.0, 3.0], concentration0=[97.0, 97.0]
    )
)
model_spec = spec.ModelSpec(prior=prior, organic_media_prior_type='contribution')
  • Coefficient (beta_om): Uses a HalfNormal distribution to apply tighter statistical regularization (scale 2.0).

    For reference, the default distribution is HalfNormal(5) and has a scale of 5.

import tensorflow_probability as tfp
from meridian.model import spec, prior_distribution
# -----------------------------------------------------------------------------
# Option 2: Organic Media Coefficient
# -----------------------------------------------------------------------------
# Coefficient (HalfNormal) -> Scale at 2.0
prior = prior_distribution.PriorDistribution(
    beta_om=tfp.distributions.HalfNormal(scale=[2.0, 2.0])
)
model_spec = spec.ModelSpec(prior=prior, organic_media_prior_type='coefficient')

Configure non-media treatment priors

The prior type of non-media treatments is specified by the non_media_treatments_prior_type argument. The options are 'contribution' and 'coefficient', with 'contribution' being the default.

The following table shows the PriorDistribution parameter corresponding to each non_media_treatments_prior_type, which can be used to customize the prior distribution.

non_media_treatments_prior_type Parameter in PriorDistribution
'contribution' (default) contribution_n
'coefficient' gamma_n

Non-media treatment configuration examples

This section provides several code samples for configuring different prior types for non-media treatments. The bullets explain the reasoning behind the example prior settings in the code block that follows. The default distributions are also provided as reference point to understand the configuration process for each prior type.

  • Contribution (contribution_n): Set a Truncated Normal distribution which concentrates mass at (-5%) for the first treatment and (5%) for the second treatment. Both have relatively wide uncertainty (10%).

    The prior for the first treatment allows only for negative contribution, as it is truncated to be within the range (-100%, 0%). This may be reasonable if the non-media treatment is price and the KPI is the number of units sold.

    The prior for the second treatment allows only for positive contribution, as it is truncated to be within the range (0%, 100%). This may be reasonable if the non-media treatment represents a promotion and the KPI is the number of units sold.

    For reference, the default distribution is TruncatedNormal(0.0, 0.1, -1.0, 1.0) and is considered a weakly informative prior.

import tensorflow_probability as tfp
from meridian.model import spec, prior_distribution
# -----------------------------------------------------------------------------
# Option 1: Non-Media Treatment Contribution
# -----------------------------------------------------------------------------
# Contribution (TruncatedNormal) -> Loc at -5% and 5%, Scale at 10%
prior = prior_distribution.PriorDistribution(
    contribution_n=tfp.distributions.TruncatedNormal(
        loc=[-0.05, 0.05],
        scale=[0.1, 0.1],
        low=[-1.0, 0.0],
        high=[0.0, 1.0]
    )
)
model_spec = spec.ModelSpec(
    prior=prior,
    non_media_treatments_prior_type='contribution'
)
  • Coefficient (gamma_n): Uses a Normal(0, 1), which has a smaller standard deviation than the default distribution. Sometimes stronger regularization is helpful to reduce the posterior variance.

    For reference, the default distribution is Normal(0, 5) and considered a weakly informative prior.

import tensorflow_probability as tfp
from meridian.model import spec, prior_distribution
# -----------------------------------------------------------------------------
# Option 2: Non-Media Treatment Coefficient
# -----------------------------------------------------------------------------
# Coefficient (Normal) -> Loc at 0.0, Scale at 1.0
prior = prior_distribution.PriorDistribution(
    gamma_n=tfp.distributions.Normal(
        loc=[0.0, 0.0], scale=[1.0, 1.0]
    )
)
model_spec = spec.ModelSpec(
    prior=prior,
    non_media_treatments_prior_type='coefficient'
)

Specify the proper prior arguments

The PriorDistribution object has an argument for each combination of treatment type and prior type. For each treatment type, only the argument corresponding to the selected prior type is used. The others are ignored.

For example, the arguments corresponding to non-R&F paid media are

  • roi_m

  • mroi_m

  • contribution_m

  • beta_m

If media_prior_type is 'roi', then roi_m is used and the others are ignored.

For example, a user specifies priors for multiple prior types. However, in this example, only contribution priors are used, since media_prior_type='contribution'.

In the following snippet, notice how roi_m and mroi_m are defined but will be ignored because media_prior_type is set to contribution.

import tensorflow_probability as tfp
from meridian.model import spec, prior_distribution

# Set custom prior for all paid media treatment parameters.
prior_dist = prior_distribution.PriorDistribution(
    roi_m=tfp.distributions.LogNormal(0.2, 0.9), # NOT used
    mroi_m=tfp.distributions.LogNormal(0.0, 0.5), # NOT used
    contribution_m=tfp.distributions.Beta(1.0, 99.0), # Used
    beta_m=tfp.distributions.HalfNormal(5.0), # NOT used
)

# Setting the treatment type to 'contribution' means that only the `contribution_m`
# prior will be used. The priors specified on `roi_m`, `mroi_m`, and `beta_m` will be ignored.
spec = spec.ModelSpec(prior=prior_dist, media_prior_type='contribution')

The behavior regarding specifying the right prior is also detailed in the following flowchart.

Flowchart detailing proper parameter usage for model spec

Further considerations

This section contains additional advanced considerations one can make when choosing between different treatment prior types in Meridian.

Customize contribution priors for non-media treatments

The default contribution prior is a Truncated Normal distribution, which allows both positive and negative values. You can set treatment-specific parameters on the Truncated Normal distribution to shift probability mass toward positive or negative values. For example, the following code snippet assigns a symmetrically truncated Normal(0, 0.1) distribution on the first treatment, a positive truncated HalfNormal(0, 0.2) distribution on the second treatment, and a negative truncated HalfNormal(0, 0.1) distribution on the third treatment.

PriorDistribution(
    contribution_n=tfp.distributions.TruncatedNormal(
        loc=[0, 0, 0],
        scale=[0.1, 0.2, 0.1],
        high=[1, 1, 0],
    )
)

Alternatively, you could use a scaled Beta distribution to specify a positive distribution for some treatments and a negative distribution for other treatments. For example, the following code snippet would assign a Beta(1, 49) prior on the first treatment and a negative Beta(1, 99) prior on the second treatment.

PriorDistribution(
    contribution_n=tfp.distributions.TransformedDistribution(
        tfp.distributions.Beta([1, 1], [49, 99]),
        tfp.bijectors.Scale([1, -1]),
    )
)

Understand induced priors and channel parity

When you specify a prior on one metric (for example, ROI), Meridian induces a prior on the other (mROI). This induced prior doesn't belong to a standard parametric family and depends on other model parameters, including the channel's media execution across geos and time.

This has a key implication for channel parity: for example, even if you set a common ROI prior for all channels, the induced mROI priors will differ for each channel, and vice-versa. Therefore, if your goal is to assume parity across channels for a specific metric, you should set the prior directly on that metric using the corresponding parameterization.

If you want to examine the induced ROI and mROI priors for a model, you can call sample_prior, then use the Analyzer class's roi or marginal_roi method with the argument use_posterior=False.

from meridian.analysis import analyzer
from meridian.model import model
import numpy as np

mmm = model.Meridian(...)
mmm.sample_posterior(...)
analyzer_instance = analyzer.Analyzer(mmm)

# Get the prior distributions using `use_posterior=False`.
roi_prior = analyzer_instance.roi(use_posterior=False)

# This is the induced prior on mROI.
mroi_induced_prior = analyzer_instance.marginal_roi(use_posterior=False)

# The shape of the prior samples is (chains, draws, channels).
# We calculate the mean across the 'chains' and 'draws' axes.
print("Mean of ROI prior per channel:", np.mean(roi_prior, axis=(0, 1)))
print("Mean of induced mROI prior per channel:", np.mean(mroi_induced_prior, axis=(0, 1)))

Advanced: Induction relationship between mROI and ROI

Although the induced prior doesn't belong to a standard parametric family, we can say something about the induced priors. Recall, the mROI is the return on investment for one additional monetary unit (for example, one dollar) of spend on a given channel.

For impression-based channels (those without R&F data), an additional monetary unit of spend is allocated by scaling up the media execution (e.g., impressions).

When the Hill function for a channel is concave (as is the default), the channel's overall ROI will always be higher than its mROI. This leads to a predictable relationship between the specified and induced priors:

  • An ROI prior induces an mROI prior that is strictly smaller.
  • An mROI prior induces an ROI prior that is strictly larger.

For reach and frequency (R&F) channels, the additional monetary unit of spend is allocated by scaling up the reach while holding the average frequency fixed.

For R&F channels, the mROI (by reach) is equal to the ROI because media effects are linear in reach under the Meridian model. Meridian's mROI prior is applied to the mROI by reach; therefore, choosing between an ROI and mROI prior has no impact on the prior itself for these channels. However, the choice matters if you are using default distributions because the default distributions for ROI and mROI priors are different.

Use mROI priors for budget regularization

You can use mROI priors to regularize budget optimization recommendations by shrinking them toward the historical budget allocation. This is useful if you believe historical budgets were already close to optimal.

This is accomplished by setting a common mROI prior mean across all channels and using a small standard deviation. A stronger prior (smaller standard deviation) pulls the optimal allocation closer to the historical allocation, resulting in smaller recommended budget shifts. For example, setting the mROI mean to 1.0 suggests that, at historical spend levels, an additional dollar of spend would yield a dollar in return, implying that the channel is near its optimal budget.

import tensorflow_probability as tfp
from meridian.model import spec, prior_distribution

# Assume 2 paid media channels.
# Set a common mROI prior mean of 1.0, suggesting budgets are near optimal.
# Use a very small standard deviation to create a strong prior.
mean_mroi = [1.0, 1.0]
std_mroi = [0.1, 0.1]  # A small std dev creates a strong prior.

lognormal_mroi_regularizing = prior_distribution.PriorDistribution.lognormal_dist_from_mean_std(
    mean_mroi, std_mroi
)

prior_mroi_regularizing = prior_distribution.PriorDistribution(
    mroi_m=lognormal_mroi_regularizing
)

# This ModelSpec will produce more conservative budget recommendations.
model_spec_regularized = spec.ModelSpec(
    prior=prior_mroi_regularizing,
    media_prior_type='mroi'
)

The amount of media execution, and therefore saturation, of a channel can change across different time windows. Thus, mROI values can change across different time windows. If your goal is to use mROI priors to regularize budget optimization, ensure the time window for the prior aligns with the optimization window. Otherwise, the regularization may not work as intended.