<br />

When an impression occurs, Google Mobile Ads Unity Plugin provides ad revenue data
associated with that impression. You can use the data to calculate a user's
lifetime value, or forward the data downstream to other relevant systems.

This guide is intended to help you implement the impression-level ad revenue
data capture in your Unity project.

## Prerequisites

- Make sure you have [turned on the impression-level ad revenue
  feature](https://support.google.com/admob/answer/11322405) in the AdMob UI.
- Unity plugin 5.0.0 or higher.
- Complete [Get Started](https://developers.google.com/admob/unity/quick-start.md.txt). Your Unity app should already have the Google Mobile Ads Unity plugin imported.
- Before you can receive any impression-level ad revenue data, you need to
  implement at least one ad format:

  - [Banner](https://developers.google.com/admob/unity/banner.md.txt)
  - [Interstitial](https://developers.google.com/admob/unity/interstitial.md.txt)
  - [Rewarded](https://developers.google.com/admob/unity/rewarded.md.txt)
  - [Rewarded interstitial](https://developers.google.com/admob/unity/rewarded-interstitial.md.txt)
  - [Native](https://developers.google.com/admob/unity/native-overlay.md.txt)

## Implementing a paid event handler

Each ad format has an `OnAdPaid` event. During the lifecycle of an ad event,
Google Mobile Ads Unity Plugin monitors impression events and invokes the handler
with a `AdValue` representing the earned value.

The following example handles paid events for a rewarded ad:

```c#
private void LoadRewardedAd()
{
   // Send the request to load the ad.
   AdRequest adRequest = new AdRequest();
   RewardedAd.Load("AD_UNIT_ID", adRequest, (RewardedAd rewardedAd, LoadAdError error) =>
   {
      // If the operation failed with a reason.
      if (error != null)
      {
         Debug.LogError("Rewarded ad failed to load an ad with error : " + error);
         return;
      }

      rewardedAd.OnAdPaid += this.HandleAdPaidEvent;
   });
}

public void HandleAdPaidEvent(AdValue adValue)
{
// TODO: Send the impression-level ad revenue information to your
// preferred analytics server directly within this callback.
long valueMicros = adValue.Value;
string currencyCode = adValue.CurrencyCode;
PrecisionType precision = adValue.Precision;
ResponseInfo responseInfo = rewardedAd.GetResponseInfo();
string responseId = responseInfo.GetResponseId();
AdapterResponseInfo loadedAdapterResponseInfo = responseInfo.GetLoadedAdapterResponseInfo();
string adSourceId = loadedAdapterResponseInfo.AdSourceId;
string adSourceInstanceId = loadedAdapterResponseInfo.AdSourceInstanceId;
string adSourceInstanceName = loadedAdapterResponseInfo.AdSourceInstanceName;
string adSourceName = loadedAdapterResponseInfo.AdSourceName;
string adapterClassName = loadedAdapterResponseInfo.AdapterClassName;
long latencyMillis = loadedAdapterResponseInfo.LatencyMillis;
Dictionary\<string, string\> credentials = loadedAdapterResponseInfo.AdUnitMapping;
Dictionary\<string, string\> extras = responseInfo.GetResponseExtras();
string mediationGroupName = extras\["mediation_group_name"\];
string mediationABTestName = extras\["mediation_ab_test_name"\];
string mediationABTestVariant = extras\["mediation_ab_test_variant"\];
}
```

> [!IMPORTANT]
> **Important:** To maintain accurate impression level ad revenue tracking, avoid using `MobileAds.RaiseAdEventsOnUnityMainThread` to raise ad events on the Unity main thread. If main thread synchronization is necessary, you must [Manually synchronize ad events](https://developers.google.com/admob/unity/global-settings.md.txt#manually-synchronize-ad-events) .

### Identify a custom event ad source name

For custom event ad sources, `AdSourceName` property gives you the ad source
name `Custom Event`. If you use multiple custom events, the ad source name isn't
granular enough to distinguish between multiple custom events. To locate a
specific custom event, do the following steps:

1. Get the `AdapterClassName` property.
2. Set a unique ad source name.

The following example sets a unique ad source name for a custom event:

```c#
private string GetAdSourceName(AdapterResponseInfo loadedAdapterResponseInfo)
{
    if (loadedAdapterResponseInfo == null)
    {
        return string.Empty;
    }

    string adSourceName = loadedAdapterResponseInfo.AdSourceName;

    if (adSourceName == "Custom Event")
    {

        #if UNITY_ANDROID
            if (loadedAdapterResponseInfo.AdapterClassName ==
                "com.google.ads.mediation.sample.customevent.SampleCustomEvent")
            {
                adSourceName = "Sample Ad Network (Custom Event)";
            }
        #elif UNITY_IPHONE
            if (loadedAdapterResponseInfo.AdapterClassName == "SampleCustomEvent")
            {
                adSourceName = "Sample Ad Network (Custom Event)";
            }
        #endif

    }
    return adSourceName;
}
```

For more information on the winning ad source, see [Retrieve information about
the ad response](https://developers.google.com/admob/unity/response-info).

### Integrate with App Attribution Partners (AAP)

For complete details on forwarding ad revenue data to analytics platforms,
refer to the partner's guide:

| Partner SDK |
|---|
| [Adjust](https://dev.adjust.com/en/sdk/unity/integrations/admob) |
| [AppsFlyer](https://support.appsflyer.com/hc/en-us/articles/4416353506833) |
| [Singular](https://support.singular.net/hc/en-us/articles/360037635452-Unity-SDK-Integration-Guide#42_Adding_Ad_Revenue_Attribution_Support) |
| [Tenjin](https://docs.tenjin.com/en/send-events/unity.html#ilrd) |

### Implementation best practices

- Set the `OnPaidEvent` event immediately once you create or get access to the ad object, and definitely before showing the ad. This makes sure that you don't miss any callbacks.
- Send the impression-level ad revenue information to your preferred analytics server immediately in your `OnPaidEvent` handler. This makes sure that you don't accidentally drop any callbacks and avoids data discrepancies.

## AdValue

`AdValue` is a class that represents the monetary value earned for an ad,
including the value's currency code and its precision type encoded as follows.

> [!IMPORTANT]
> **Key Point:** The value of `AdValue` is a micro value that represents each ad's worth. For example, a value of 5,000 indicates that this ad is estimated to be worth $0.005.

| `AdValue.PrecisionType` | Description |
|---|---|
| `Unknown` | An ad value that's unknown. This gets returned when LTV pingback is enabled but there isn't enough data available. |
| `Estimated` | An ad value estimated from aggregated data. |
| `PublisherProvided` | A publisher provided ad value, such as manual CPMs in a mediation group. |
| `Precise` | The precise value of this ad. |

In case of mediation, AdMob tries to provide an `Estimated`value for ad sources
that are [optimized](https://support.google.com/admob/answer/7374110). For
non-optimized ad sources, or in cases where there aren't enough aggregated data
to report a meaningful estimation, the `PublisherProvided` value is returned.

### Test impressions from bidding ad sources

After an impression-level ad revenue event occurs for
a bidding ad source through a test request, you receive only the following
values:

- `Unknown`: indicates the precision type.

<!-- -->

- `0`: indicates the ad value.

Previously, you might have seen the precision type as a value other than `Unknown` and an ad value more than `0`.

For details on sending a test ad request, see
[Enable test devices](https://developers.google.com/admob/unity/test-ads.md.txt#enable-test-devices).