This guide explains how to integrate custom native ad formats with open
measurement.

## Prerequisites

Before you continue, do the following:

- Read [Open Measurement with the Mobile Ads
  SDK](https://developers.google.com/ad-manager/mobile-ads-sdk/android/open-measurement).
- Integrate [custom native ad
  formats](https://developers.google.com/ad-manager/mobile-ads-sdk/android/native/custom-formats).
- [Configure a viewability
  provider](https://support.google.com/admanager/answer/9025968#configure-a-viewability-provider) and assign it to your line item.
- Enter your partner name when [creating a custom
  format](https://support.google.com/admanager/answer/7661908) in the Ad Manager UI.

## Integration

If you plan to use open measurement with custom native ad formats that
don't contain a video asset, you'll be responsible for calling the Open
Measurement APIs yourself.

If you're using custom native ad formats with a video asset, you don't need to
follow this guide; the Mobile Ads SDK tracks viewability of the video asset on
your behalf.

> [!IMPORTANT]
> **Key Point:** In order for your display-type native custom ad measurement results to be certified by the IAB, you must be certified as a Measurement Provider with the [IAB Tech Lab](https://iabtechlab.com/compliance-programs/faq-om-sdk-compliance/).

### Load an ad

Loading an ad is the same whether you're using open measurement or not. Here is
a method that demonstrates how to request a custom native ad:

### Java

```java
private void loadCustomNativeAd(Context context, ViewGroup nativeCustomFormatAdContainer) {

  AdLoader adLoader =
      new AdLoader.Builder(context, "AD_UNIT_ID")
          .forCustomFormatAd(
              "CUSTOM_TEMPLATE_ID",
              new NativeCustomFormatAd.OnCustomFormatAdLoadedListener() {
                @Override
                public void onCustomFormatAdLoaded(@NonNull NativeCustomFormatAd ad) {
                  // Show the ad first and then register your view and begin open measurement.
                  // Make sure to do this on the main thread.

                  // ...
                  // Show ad
                  // ...

                  startOpenMeasurement(ad, nativeCustomFormatAdContainer);
                }
              },
              new NativeCustomFormatAd.OnCustomClickListener() {
                @Override
                public void onCustomClick(NativeCustomFormatAd ad, String assetName) {
                  // Handle the click action
                }
              })
          .build();
  adLoader.loadAd(new AdRequest.Builder().build());
}
```

### Kotlin

```kotlin
private fun loadCustomNativeAd(context: Context, nativeCustomFormatAdContainer: ViewGroup) {
  val adLoader =
    AdLoader.Builder(context, "AD_UNIT_ID")
      .forCustomFormatAd(
        "CUSTOM_TEMPLATE_ID",
        NativeCustomFormatAd.OnCustomFormatAdLoadedListener { ad ->
          // Show the ad first and then register your view and begin open measurement. Make sure
          // to do this on the main thread.

          // ...
          // Show ad
          // ...

          startOpenMeasurement(ad, nativeCustomFormatAdContainer)
        },
        NativeCustomFormatAd.OnCustomClickListener { ad, assetName ->
          // Handle the click action.
        },
      )
      .build()

  adLoader.loadAd(AdRequest.Builder().build())
}
```

Replace <var translate="no">AD_UNIT_ID</var> and <var translate="no">CUSTOM_TEMPLATE_ID</var> with your ad unit ID and custom template ID.

### Register your view and begin measuring

To enable open measurement on a custom native ad, display the ad first, and then
register your custom ad view with the `DisplayOpenMeasurement` object associated
with the custom native ad. The `DisplayOpenMeasurement` object provides the
`setView()` method to register your container view with open measurement.

You also need to explicitly tell the SDK to begin measuring your ad. To do this
call the `start()` method on the `DisplayOpenMeasurement` object of your
custom native ad. The `start()` method must be called from the main
thread, and subsequent calls have no effect.

Here's what it looks like:

### Java

```java
private void startOpenMeasurement(
    NativeCustomFormatAd ad, ViewGroup nativeCustomFormatAdContainer) {
  DisplayOpenMeasurement displayOpenMeasurement = ad.getDisplayOpenMeasurement();
  if (displayOpenMeasurement != null) {
    displayOpenMeasurement.setView(nativeCustomFormatAdContainer);
    displayOpenMeasurement.start();
  }
}
```

### Kotlin

```kotlin
private fun startOpenMeasurement(
  ad: NativeCustomFormatAd,
  nativeCustomFormatAdContainer: ViewGroup,
) {
  ad.getDisplayOpenMeasurement()?.let { displayOpenMeasurement ->
    displayOpenMeasurement.setView(nativeCustomFormatAdContainer)
    displayOpenMeasurement.start()
  }
}
```

<br />

Note that you should display your ad before registering your view. Displaying
your ad is covered in [Custom Native Ad
Formats](https://developers.google.com/ad-manager/mobile-ads-sdk/android/native/custom-formats#display_custom_native_ad_formats).

The `customTemplateAdFrame`
layout is the ad container for the custom native ad and must contain all
assets within the bounding box of the view.

> [!IMPORTANT]
> **Important:** Make sure you call `destroy()` on the custom native ad when you're done with the ad, for example, after dereferencing the object or destroying the activity. This makes sure that the IAB `sessionFinish` event is fired.

### Certify with IAB

Once you release your app, you will begin receiving measurement data; however,
your data won't be certified until you complete the
[IAB certification process](https://iabtechlab.com/compliance-programs/faq-om-sdk-compliance/).