Meridian defines ROI as incremental outcome divided by spend. When the KPI is
not revenue and `revenue_per_kpi` is not passed to `InputData`,
[outcome](https://developers.google.com/meridian/docs/basics/glossary) is not in terms of
revenue. This can make it difficult to determine a custom ROI prior.

Consider the following options when setting a custom prior when outcome is not
revenue:

- [Custom total paid media contribution prior](https://developers.google.com/meridian/docs/advanced-modeling/unknown-revenue-kpi-custom#set-total-paid-media-contribution-prior)
- [Custom incremental KPI per cost (IKPC) prior](https://developers.google.com/meridian/docs/advanced-modeling/unknown-revenue-kpi-custom#set-ikpc-prior)
- [Channel-level contribution prior](https://developers.google.com/meridian/docs/advanced-modeling/unknown-revenue-kpi-custom#set-channel-contribution-prior)

## Custom total paid media contribution prior

If you have intuition about the total proportion of the KPI that is incremental
due to paid media, you can set a common ROI prior on all channels such that the
total media contribution has a specific prior mean and standard deviation by
doing the following:

    import numpy as np
    import tensorflow_probability.substrates.jax as tfp_jax

    p_mean = 0.5  # prior mean proportion of KPI incremental due to all media
    p_sd = 0.15  # prior std dev proportion of KPI incremental to all media
    roi_mean = p_mean * kpi / np.sum(cost)
    roi_sd = p_sd * kpi / np.sqrt(np.sum(np.power(cost, 2)))
    lognormal_sigma = np.sqrt(np.log(roi_sd**2 / roi_mean**2 + 1))
    lognormal_mu = np.log(roi_mean * np.exp(-lognormal_sigma**2 / 2))
    # Ensure 64-bit float precision to maintain type consistency with JAX
    roi_prior = tfp_jax.distributions.LogNormal(
        lognormal_mu.astype(np.float64),
        lognormal_sigma.astype(np.float64),
    )

Where:

- `kpi` is the sum of the entire KPI across geos and time.
- `cost` is an array of the total cost per channel across geos and time.

In this example, the KPI contribution of all media is centered at 50% with a
standard deviation of 15%. You then get an ROI prior that is consistent for all
channels, such that the implied prior on the total paid media contribution has a
mean at 50% and a standard deviation at 15%. The derived prior, `roi_prior`, can
then be used by setting it in the `PriorDistribution` container for `roi_m` or
`roi_rf`.

The total paid media contribution prior can be advantageous as it doesn't
require intuition on each individual channel. However, if additional knowledge
or intuition about each channel is available, then consider setting an [IKPC
prior](https://developers.google.com/meridian/docs/advanced-modeling/unknown-revenue-kpi-custom#set-ikpc-prior) or
[channel-level contribution
prior](https://developers.google.com/meridian/docs/advanced-modeling/unknown-revenue-kpi-custom#set-channel-contribution-prior).

## Custom incremental KPI per cost (IKPC) prior

If you have intuition about a channel's incremental KPI per cost (IKPC), you can
set an IKPC prior using `roi_m` or `roi_rf` in the `PriorDistribution`
container. When `revenue_per_kpi` is not set, ROI is equivalent to IKPC in
Meridian.

**Example:**

    import numpy as np
    import tensorflow_probability.substrates.jax as tfp_jax

    roi_prior = tfp_jax.distributions.LogNormal(
        np.array([0.5, 0.6, 0.7], dtype=np.float64),
        np.array([0.5, 0.5, 0.5], dtype=np.float64),
    )

However, we only recommend doing this if you are going to set a custom IKPC
prior for every media channel. This is because the default ROI priors with
`revenue_per_kpi=None` likely won't make sense for your data as they are
designed for revenue KPIs where the ROI would be on the unitless scale. If you
only have intuition on the IKPC for some channels, you still must set some
reasonable default IKPC prior for the other channels. Meridian doesn't have a
recommended default IKPC prior because IKPC is strongly dependent on the scale,
for example, a new car or a candy bar.

## Channel-level contribution prior

If you have intuition about the proportion of the KPI that is incremental due to
a given channel, you can set a prior on the contribution of a given
channel by setting `media_prior_type='contribution'` and
`rf_prior_type='contribution'` in the `ModelSpec` and customizing the prior
distributions on `contribution_m` and `contribution_rf` in the
`PriorDistribution`. The following is an example.

    import numpy as np
    import tensorflow_probability.substrates.jax as tfp_jax
    from meridian.model import prior_distribution, spec

    prior = prior_distribution.PriorDistribution(
        contribution_m=tfp_jax.distributions.Beta(
            np.array([1.0, 5.0], dtype=np.float64),
            np.array([99.0, 95.0], dtype=np.float64),
        ),
        contribution_rf=tfp_jax.distributions.Beta(
            np.float64(2.0), np.float64(98.0)
        ),
    )
    model_spec = spec.ModelSpec(
        prior=prior,
        media_prior_type="contribution",
        rf_prior_type="contribution",
    )

In this example, there are two media channels. The first is assigned a Beta(1,
99) contribution prior, which has a mean of 1%. The second is assigned a Beta(5,
95) contribution prior, which has a mean of 5%. The R\&F channels are each
assigned a contribution prior of Beta(2, 98), which has a mean of 2%. (Note that
`tfp_jax.distributions.Beta(np.float64(2.0), np.float64(98.0))` is a scalar distribution, so it is broadcast to
all R\&F channels).