Custom Native Ad Formats

Custom native ad formats

In addition to the system-defined native formats, Ad Manager publishers have the option of creating their own native ad formats by defining custom lists of assets. These are called custom native ad formats, and can be used with reserved ads. This enables publishers to pass arbitrary structured data to their apps. These ads are represented by the NativeCustomTemplateAd object.

Load custom native ad formats

This guide explains how to load and display custom native ad formats.

Build an AdLoader

Like unified native ads, custom native ad formats are loaded using the AdLoader class:

Java

AdLoader adLoader = new AdLoader.Builder(context, "/6499/example/native")
    .forCustomTemplateAd("10063170",
      new NativeCustomTemplateAd.OnCustomTemplateAdLoadedListener() {
          @Override
          public void onCustomTemplateAdLoaded(NativeCustomTemplateAd ad) {
              // Show the custom template and record an impression.
          }
      },
      new NativeCustomTemplateAd.OnCustomClickListener() {
          @Override
          public void onCustomClick(NativeCustomTemplateAd ad, String s) {
              // Handle the click action
          }
      })
    .withAdListener( ... )
    .withNativeAdOptions( ... )
    .build();

Kotlin

val adLoader = AdLoader.Builder(this, "/6499/example/native")
        .forCustomTemplateAd("10063170",
            { ad ->
                // Show the custom template and record an impression.
            },
            { ad, s ->
            // Handle the click action
            })
        .withAdListener( ... )
        .withNativeAdOptions( ... )
        .build()

Much like the forUnifiedNativeAd method configures the AdLoader to request an app install ad, the forCustomTemplateAd method sets it to handle custom template ads. There are three parameters passed into the method:

  • The template ID of the custom template the AdLoader should request. Each custom native ad format has a template ID value associated with it. This parameter indicates which template your app wants the AdLoader to request.
  • An OnCustomTemplateAdLoadedListener to be invoked when an ad has loaded successfully.
  • An optional OnCustomClickListener to be invoked when the user taps or clicks on the ad. For more on this listener, see the "Handling clicks and impressions" section below.

Because a single ad unit can be set up to serve more than one creative template, forCustomTemplateAd can be called multiple times with unique template IDs in order to prepare the ad loader for more than one possible custom native ad format.

Template IDs

The template IDs used to uniquely refer to native custom ad formats can be found in the Ad Manager UI under the Creatives > Native Ad Formats section of the Delivery tab:

Each custom native ad format's template ID appears beneath its name. Clicking on one of the names brings you to a details screen showing information about the template's fields:

From here, individual fields can be added, edited, and removed. Note the Variable ID column to the right. These IDs are used to access the individual assets, and are discussed more in the next section.

Display custom native ad formats

Custom native ad formats differ from system-defined ones in that publishers have the power to define their own "templates," or lists of assets, that make up an ad. Therefore, the process for displaying one differs from system-defined formats in a few ways:

  1. Because the NativeCustomTemplateAd class is meant to handle any of the custom native ad formats you define in Ad Manager, it doesn't have named "getters" for assets. Instead, it offers methods like getText and getImage that take the Variable ID of a template field as a parameter.
  2. There is no dedicated ad view class like NativeContentAdView to use with NativeCustomTemplateAd. You are free to use a FrameLayout, RelativeLayout, or whatever makes sense for your user experience.
  3. Because there is no dedicated ViewGroup class, you do not need to register any of the views you use to display the ad's assets. This saves a few lines of code when displaying the ad, but also means you'll need to do a little extra work to handle clicks later on.

Here's an example function that displays a NativeCustomTemplateAd:

Java

public void displayCustomTemplateAd (ViewGroup parent,
                                     NativeCustomTemplateAd customTemplateAd) {
    // Inflate a layout and add it to the parent ViewGroup.
    LayoutInflater inflater = (LayoutInflater) parent.getContext()
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View adView = inflater.inflate(R.layout.custom_template_ad, parent);

    // Locate the TextView that will hold the value for "Headline" and
    // set its text.
    TextView myHeadlineView = (TextView) adView.findViewById(R.id.headline);
    myHeadlineView.setText(customTemplateAd.getText("Headline"));

    // Locate the ImageView that will hold the value for "MainImage" and
    // set its drawable.
    Button myMainImageView = (ImageView) adView.findViewById(R.id.main_image);
    myMainImageView.setImageDrawable(
            nativeCustomTemplateAd.getImage("MainImage").getDrawable());

    ...
    // Continue locating views and displaying assets until finished.
    ...
}

Kotlin

public fun displayCustomTemplateAd (parent: ViewGroup,
                                customTemplateAd: NativeCustomTemplateAd) {
    val adView = layoutInflater
            .inflate(R.layout.ad_simple_custom_template, null)

    val myHeadlineView = adView.findViewById<TextView>(R.id.headline)
    myHeadlineView.setText(customTemplateAd.getText("Headline"));

    // Locate the ImageView that will hold the value for "MainImage" and
    // set its drawable.
    val myMainImageView = adView.findViewById(R.id.main_image);
    myMainImageView.setImageDrawable(
            customTemplateAd.getImage("MainImage").drawable;

    ...
    // Continue locating views and displaying assets until finished.
    ...
}

Native video for custom native ad formats

When creating a new native ad format, you have the option to make the format eligible for video.

Simply check the box to make your format video eligible, and when you make a new creative for this format, you'll have an option to provide a video asset.

In your app implementation, you can use NativeCustomTemplateAd.getVideoMediaView() to get the video's view. Then add this view to your view hierarchy. If the ad doesn't have video content, make alternate plans to show the ad without a video.

The example below checks if the ad has video content, and displays an image in its place if a video is not available:

Java

// Called when a custom native ad loads.
@Override
public void onCustomTemplateAdLoaded(NativeCustomTemplateAd ad) {
    VideoController videoController = ad.getVideoController();
    // Assumes you have a FrameLayout in your view hierarchy with the id media_placeholder.
    FrameLayout mediaPlaceholder = (FrameLayout) findViewById(R.id.media_placeholder);
    if (videoController.hasVideoContent()) {
        mediaPlaceholder.addView(ad.getVideoMediaView());
    } else {
        ImageView mainImage = new ImageView(this);
        mainImage.setAdjustViewBounds(true);
        // Assumes your native format has an image asset with the name MainImage.
        mainImage.setImageDrawable(ad.getImage("MainImage").getDrawable());
        mediaPlaceholder.addView(mainImage);
    }
}

Kotlin

NativeCustomTemplateAd.OnCustomTemplateAdLoadedListener { ad ->
    val videoController = ad.videoController
    // Assumes you have a FrameLayout in your view hierarchy with the id media_placeholder.
    val mediaPlaceholder = adView.findViewById<FrameLayout>(R.id.media_placeholder)
    if (videoController.hasVideoContent())
    {
        mediaPlaceholder.addView(ad.videoMediaView)
    }
    else
    {
        val mainImage = ImageView(this)
        mainImage.adjustViewBounds = true
        // Assumes your native format has an image asset with the name MainImage.
        mainImage.setImageDrawable(ad.getImage("MainImage").drawable)
        mediaPlaceholder.addView(mainImage)
    }
}

See VideoController for more information on how you can customize a custom native ad's video experience.

Download the Ad Manager Custom Rendering example for a working example of native video in action.

Custom native ad format clicks and impressions

With custom native ad formats, your app is responsible for recording impressions and reporting click events to the SDK.

Record impressions

To record an impression for a custom template ad, call the recordImpression method on the corresponding NativeCustomTemplateAd:

myCustomTemplateAd.recordImpression();

If your app accidentally calls the method twice for the same ad, the SDK automatically prevents a duplicate impression from being recorded for a single request.

Report clicks

To report to the SDK that a click has occurred on an asset view, call the performClick method on the corresponding NativeCustomTemplateAd and pass in the name of the asset that was clicked. For example, if you had an asset in your custom template called "MainImage" and wanted to report a click on the ImageView that corresponded to that asset, your code would look like this:

myCustomTemplateAd.performClick("MainImage");

Note that you don't need to call this method for every view associated with your ad. If you had another field called "Caption" that was meant to be displayed but not clicked or tapped on by the user, your app would not need to call performClick for that asset's view.

Respond to custom click actions

When a click is performed on a custom template ad, there are three possible responses from the SDK, attempted in this order:

  1. Invoke the OnCustomClickListener from AdLoader, if one was provided.
  2. For each of the ad's deep link URLs, attempt to locate a content resolver and start the first one that resolves.
  3. Open a browser and navigate to the ad's traditional Destination URL.

The forCustomTemplateAd method accepts an OnCustomClickListener. If you pass a listener object in, the SDK instead invokes its onCustomClick method and takes no further action. If you pass a null value as the listener, however, the SDK falls back to the deeplink and/or destination URLs registered with the ad.

Custom Click listeners allow your app to decide the best action to take in response to a click, whether it's updating the UI, launching a new activity, or merely logging the click. Here's an example that simply logs that a click took place:

Java

AdLoader adLoader = new AdLoader.Builder(context, "/6499/example/native")
    .forCustomTemplateAd("10063170",
      new NativeCustomTemplateAd.OnCustomTemplateAdLoadedListener() {
        // Display the ad.
      },
      new NativeCustomTemplateAd.OnCustomClickListener() {
          @Override
          public void onCustomClick(NativeCustomTemplateAd ad, String assetName) {
            Log.i("MyApp", "A custom click just happened for " + assetName + "!");
          }
      }).build();

Kotlin

val adLoader = AdLoader.Builder(this, "/6499/example/native")
    .forCustomTemplateAd("10063170",
        { ad ->
            // Display the ad.
        },
        { ad, assetName ->
                Log.i("MyApp", "A custom click just happened for $assetName!")
    }).build()

At first, it might seem strange that custom click listeners exist. After all, your app just told the SDK that a click happened, so why should the SDK turn around and report that to the app?

This flow of information is useful for a few reasons, but most importantly it allows the SDK to remain in control of the response to the click. It can automatically ping third-party tracking URLs that have been set for the creative, for example, and handle other tasks behind the scenes, without any additional code.

Send feedback about...

Mobile Ads SDK for Android
Mobile Ads SDK for Android
Need help? Visit our support page.