Native Ads - Custom Rendering

This feature is currently in a limited beta release. If you are interested in participating, reach out to your account manager to discuss the possibility. This feature will be made available to all publishers at the conclusion of the beta.

This guide will show you how to use the Google Mobile Ads SDK to implement DoubleClick Ad Exchange native ads in an iOS application, as well as some important things to consider along the way.

Prerequisites

This guide assumes some working knowledge of the Google Mobile Ads SDK. If you haven't already done so, consider running through our Get Started guide.

What's a native ad?

Native ads are advertisements presented to users via UI components that are native to the platform. They're shown using the same classes you already use in your storyboards, and can be formatted to match your app's visual design. When a native ad loads, your app receives a native ad object that contains its assets, and the app (rather than the SDK) is then responsible for displaying them.

There are two system-defined formats for native ads: app install and content. App install ads are represented by GADNativeAppInstallAd, and content ads are represented by GADNativeContentAd. Instances of the classes contain the assets for the native ad.

Load system-defined native ad formats

Native ads are loaded via GADAdLoader objects, which send messages to their delegates according to the GADAdLoaderDelegate protocol.

Initialize a GADAdLoader

The following code demonstrates how to initialize a GADAdLoader for an app install ad:

Swift

// Specify the ad's "unit identifier". This is your publisher ID.
adLoader = GADAdLoader(adUnitID: MY_AD_UNIT_ID,
    rootViewController: self,
    adTypes: [ ... ad type constants ... ],
    options: [ ... ad loader options objects ... ])
adLoader.delegate = self

Objective-C

// Specify the ad's "unit identifier". This is your publisher ID.
self.adLoader = [[GADAdLoader alloc]
      initWithAdUnitID:MY_AD_UNIT_ID
    rootViewController:rootViewController
               adTypes:@[ ... ad type constants ... ]
               options:@[ ... ad loader options objects ... ]];
self.adLoader.delegate = self;

The adTypes array parameter allows your app to pass in constants that specify which native formats it wants to request. The array should contain one or both of the following constants:

  • kGADAdLoaderAdTypeNativeAppInstall
  • kGADAdLoaderAdTypeNativeContent

Request the native ad

Once your GADAdLoader is initialized, call its loadRequest: method to request an ad:

Swift

adLoader.load(GADRequest())

Objective-C

[self.adLoader loadRequest:[GADRequest request]];

The loadRequest: method in GADAdLoader accepts the same GADRequest objects as banners and interstitials. You can use request objects to add targeting information just as you would with other ad types.

GADAdLoaderDelegate protocols

For each native ad format you request, the ad loader delegate needs to implement a corresponding protocol:

GADNativeAppInstallAdLoaderDelegate

This protocol includes a message that's sent to the delegate when an app install ad has loaded:

Swift

public func adLoader(_ adLoader: GADAdLoader,
    didReceive nativeAppInstallAd: GADNativeAppInstallAd)

Objective-C

- (void)adLoader:(GADAdLoader *)adLoader
    didReceiveNativeAppInstallAd:(GADNativeAppInstallAd *)nativeAppInstallAd;

GADNativeContentAdLoaderDelegate

This one defines a message sent when a content ad has loaded:

Swift

public func adLoader(_ adLoader: GADAdLoader,
    didReceive nativeContentAd: GADNativeContentAd)

Objective-C

- (void)adLoader:(GADAdLoader *)adLoader
    didReceiveNativeContentAd:(GADNativeContentAd *)nativeContentAd;

Handle a failed request

The above protocols extend the GADAdLoaderDelegate protocol, which defines a message sent when ads fail to load:

Swift

public func adLoader(_ adLoader: GADAdLoader,
    didFailToReceiveAdWithError error: GADRequestError)

Objective-C

- (void)adLoader:(GADAdLoader *)adLoader
    didFailToReceiveAdWithError:(GADRequestError *)error;

You can use the GADRequestError object to determine the cause of the error.

Native ad options

The last parameter included in the creation of the GADAdLoader above is an optional array of objects:

Swift

adLoader =
    GADAdLoader(adUnitID: "/6499/example/native",
    rootViewController: self,
    adTypes: [ ... ad type constants ... ],
    options: [ ... ad loader options objects ... ])

Objective-C

self.adLoader = [[GADAdLoader alloc]
      initWithAdUnitID:@"/6499/example/native"
    rootViewController:rootViewController
               adTypes:@[ ... ad type constants ... ]
               options:@[ ... ad loader options objects ... ]];

GADNativeAdImageAdLoaderOptions contains properties relating to images in native ads. Apps can control how a GADAdLoader handles native ad image assets by creating a GADNativeAdImageAdLoaderOptions object, setting its properties, and passing it in during initialization.

GADNativeAdImageAdLoaderOptions has the following properties:

disableImageLoading
Image assets for native ads are returned via instances of GADNativeAdImage, which contains image and imageURL properties. If disableImageLoading is set to false (default), the SDK will fetch image assets automatically and populate both the image and the imageURL properties for you. If it's set to true, however, the SDK will only populate imageURL, allowing you to download the actual images at your discretion.
preferredImageOrientation

Some creatives have multiple available images to match different device orientations. Apps can request images for a particular orientation by setting this property to one of the orientation constants:

  • GADNativeAdImageAdLoaderOptionsOrientationAny
  • GADNativeAdImageAdLoaderOptionsOrientationLandscape
  • GADNativeAdImageAdLoaderOptionsOrientationPortrait

If you use preferredImageOrientation to specify a preference for landscape or portrait image orientation, the SDK will place images matching that orientation first in image asset arrays and place non-matching images after them. Since some ads will only have one orientation available, publishers should make sure that their apps can handle both landscape and portrait images.

If this method is not called, the default value of GADNativeAdImageAdLoaderOptionsOrientationAny will be used.

shouldRequestMultipleImages

Some image assets will contain a series of images rather than just one. By setting this value to true, your app indicates that it's prepared to display all the images for any assets that have more than one. By setting it to false (default) your app instructs the SDK to provide just the first image for any assets that contain a series.

If no GADAdLoaderOptions objects are passed in when initializing a GADAdLoader, the default value for each option will be used.

When to request ads

Applications displaying native ads are free to request them in advance of when they'll actually be displayed. In many cases, this is the recommended practice. An app displaying a list of items with native ads mixed in, for example, can load native ads for the whole list, knowing that some will be shown only after the user scrolls the view and some may not be displayed at all.

Display a system-defined native ad format

When a native ad loads, your app will receive a native ad object via one of the GADAdLoaderDelegate protocol messages. Your app is then responsible for displaying the ad (though it doesn't necessarily have to do so immediately). To make displaying system-defined ad formats easier, the SDK offers some useful resources.

The ad view classes

For each of the system-defined formats, there is a corresponding "ad view" class: GADNativeAppInstallAdView for app install ads, and GADNativeContentAdView for content ads. These ad view classes are UIViews that publishers should use to display native ads of the corresponding format. A single GADNativeAppInstallAdView, for example, can display a single instance of a GADNativeAppInstallAd. Each of the UIViews used to display that ad's assets should be children of that GADNativeAppInstallAdView object.

If you were displaying an app install ad in a UITableView, for example, the view hierarchy for one of the cells might look like this:

The ad view classes also provide IBOutlets used to register the view used for each individual asset, and a method to register the GADNativeAd object itself. Registering the views in this way allows the SDK to automatically handle tasks such as:

  • recording clicks
  • recording impressions (when the first pixel is visible on the screen)
  • displaying the AdChoices overlay for native backfill creatives

The AdChoices overlay

An AdChoices overlay is added to each ad view by the SDK. Please leave space in the upper right corner of your native ad view for the automatically inserted AdChoices logo. Also, it's important that the AdChoices overlay be easily seen, so choose background colors and images appropriately. For more information on the overlay's appearance and function, see the native backfill implementation guidelines.

Code example

Let's take a look at how to display native ads using views loaded dynamically from xib files. This can be a very useful approach when using GADAdLoaders configured to request multiple formats.

Lay out UIViews in the xib file

The first step is to lay out the UIViews that will display native ad assets. You can do this in the Interface Builder as you would when creating any other xib file. Here's how the layout for an app install ad might look:

And here's how the layout for a content ad might look:

Note the Custom Class value in the top right of both of the images. It's set to GADNativeAppInstallAdView and GADNativeContentAdView. These are the ad view classes that are used to display a GADNativeAppInstallAd and GADNativeContentAd. For system-defined formats, you'll need to use the ad view class that matches the ad format you intend the layout to show.

Once the views are in place and you've assigned the correct ad view class to the layout, you need to link the ad view's asset outlets to the UIViews you've created. Here's how you might link the ad view's asset outlets to the UIViews created for an app install ad:

And here's how you might link the ad view's asset outlets to the UIViews created for a content ad:

In the outlet panel, the outlets in GADNativeAppInstallAdView and GADNativeContentAdView have been linked to the UIViews laid out in the Interface Builder. This lets the SDK know which UIView displays which asset. It's also important to remember that these outlets represent the views that are clickable in the ad.

Display the ad

Once the layout is complete and the outlets are linked, the last step is to add code to your app that displays an ad once it has loaded. Here's a method to display an app install ad in the view defined above:

Swift

// Mark: - GADNativeAppInstallAdLoaderDelegate

func adLoader(_ adLoader: GADAdLoader,
    didReceive nativeAppInstallAd: GADNativeAppInstallAd) {
  // Create and place the ad in the view hierarchy.
  let appInstallAdView = Bundle.main.loadNibNamed("NativeAppInstallAdView", owner: nil,
      options: nil)?.first as! GADNativeAppInstallAdView
  // TODO: Make sure to add the GADNativeAppInstallAdView to the view hierarchy.

  // Associate the app install ad view with the app install ad object. This is required to make
  // the ad clickable.
  appInstallAdView.nativeAppInstallAd = nativeAppInstallAd

  // Populate the app install ad view with the app install ad assets.
  // Some assets are guaranteed to be present in every app install ad.
  (appInstallAdView.headlineView as! UILabel).text = nativeAppInstallAd.headline
  (appInstallAdView.iconView as! UIImageView).image = nativeAppInstallAd.icon?.image
  (appInstallAdView.bodyView as! UILabel).text = nativeAppInstallAd.body
  (appInstallAdView.imageView as! UIImageView).image =
      (nativeAppInstallAd.images?.first as! GADNativeAdImage).image
  (appInstallAdView.callToActionView as! UIButton).setTitle(
      nativeAppInstallAd.callToAction, for: UIControlState.normal)

  // Other assets are not, however, and should be checked first.
  let starRatingView = appInstallAdView.starRatingView
  if let starRating = nativeAppInstallAd.starRating {
    (starRatingView as! UIImageView).image = imageOfStarsFromStarRating(starRating)
    starRatingView?.isHidden = false
  } else {
    starRatingView?.isHidden = true
  }

  let storeView = appInstallAdView.storeView
  if let store = nativeAppInstallAd.store {
    (storeView as! UILabel).text = store
    storeView?.isHidden = false
  } else {
    storeView?.isHidden = true
  }

  let priceView = appInstallAdView.priceView
  if let price = nativeAppInstallAd.price {
    (priceView as! UILabel).text = price
    priceView?.isHidden = false
  } else {
    priceView?.isHidden = true
  }

  // In order for the SDK to process touch events properly, user interaction should be disabled on
  // all views associated with the GADNativeAppInstallAdView. Since UIButton has
  // userInteractionEnabled set to true by default, views of this type must explicitly set
  // userInteractionEnabled to false.
  (appInstallAdView.callToActionView as! UIButton).isUserInteractionEnabled = false
}

Objective-C

#pragma mark GADNativeAppInstallAdLoaderDelegate implementation

- (void)adLoader:(GADAdLoader *)adLoader
    didReceiveNativeAppInstallAd:(GADNativeAppInstallAd *)nativeAppInstallAd {
  // Create and place ad in view hierarchy.
  GADNativeAppInstallAdView *appInstallAdView =
      [[[NSBundle mainBundle] loadNibNamed:@"NativeAppInstallAdView"
                                     owner:nil
                                   options:nil] firstObject];
  // TODO: Make sure to add the GADNativeAppInstallAdView to the view hierarchy.

  // Associate the app install ad view with the app install ad object. This is required to make the
  // ad clickable.
  appInstallAdView.nativeAppInstallAd = nativeAppInstallAd;

  // Populate the app install ad view with the app install ad assets.
  // Some assets are guaranteed to be present in every app install ad.
  ((UILabel *)appInstallAdView.headlineView).text = nativeAppInstallAd.headline;
  ((UIImageView *)appInstallAdView.iconView).image = nativeAppInstallAd.icon.image;
  ((UILabel *)appInstallAdView.bodyView).text = nativeAppInstallAd.body;
  ((UIImageView *)appInstallAdView.imageView).image =
      ((GADNativeAdImage *)[nativeAppInstallAd.images firstObject]).image;
  [((UIButton *)appInstallAdView.callToActionView)setTitle:nativeAppInstallAd.callToAction
                                                  forState:UIControlStateNormal];

  // Other assets are not, however, and should be checked first.
  if (nativeAppInstallAd.starRating) {
    ((UIImageView *)appInstallAdView.starRatingView).image =
        [self imageForStars:nativeAppInstallAd.starRating];
    appInstallAdView.starRatingView.hidden = NO;
  } else {
    appInstallAdView.starRatingView.hidden = YES;
  }

  if (nativeAppInstallAd.store) {
    ((UILabel *)appInstallAdView.storeView).text = nativeAppInstallAd.store;
    appInstallAdView.storeView.hidden = NO;
  } else {
    appInstallAdView.storeView.hidden = YES;
  }

  if (nativeAppInstallAd.price) {
    ((UILabel *)appInstallAdView.priceView).text = nativeAppInstallAd.price;
    appInstallAdView.priceView.hidden = NO;
  } else {
    appInstallAdView.priceView.hidden = YES;
  }

  // In order for the SDK to process touch events properly, user interaction should be disabled on
  // all views associated with the GADNativeAppInstallAdView. Since UIButton has
  // userInteractionEnabled set to YES by default, views of this type must explicitly set
  // userInteractionEnabled to NO.
  appInstallAdView.callToActionView.userInteractionEnabled = NO;
}

And here's a method to display a content ad in the view defined above:

Swift

// Mark: - GADNativeContentAdLoaderDelegate

func adLoader(_ adLoader: GADAdLoader,
    didReceive nativeContentAd: GADNativeContentAd) {
  // Create and place the ad in the view hierarchy.
  let contentAdView = Bundle.main.loadNibNamed(
      "NativeContentAdView", owner: nil, options: nil)?.first as! GADNativeContentAdView
  // TODO: Make sure to add the GADNativeContentAdView to the view hierarchy.

  // Associate the content ad view with the content ad object. This is required to make the ad
  // clickable.
  contentAdView.nativeContentAd = nativeContentAd

  // Populate the content ad view with the content ad assets.
  // Some assets are guaranteed to be present in every content ad.
  (contentAdView.headlineView as! UILabel).text = nativeContentAd.headline
  (contentAdView.bodyView as! UILabel).text = nativeContentAd.body
  (contentAdView.imageView as! UIImageView).image =
      (nativeContentAd.images?.first as! GADNativeAdImage).image
  (contentAdView.advertiserView as! UILabel).text = nativeContentAd.advertiser
  (contentAdView.callToActionView as! UIButton).setTitle(
      nativeContentAd.callToAction, for: UIControlState.normal)

  // Other assets are not, however, and should be checked first.
  let logoView = contentAdView.logoView
  if let logoImage = nativeContentAd.logo?.image {
    (logoView as! UIImageView).image = logoImage
    logoView?.isHidden = false
  } else {
    logoView?.isHidden = true
  }

  // In order for the SDK to process touch events properly, user interaction should be disabled on
  // all views associated with the GADNativeContentAdView. Since UIButton has userInteractionEnabled
  // set to true by default, views of this type must explicitly set userInteractionEnabled to false.
  (contentAdView.callToActionView as! UIButton).isUserInteractionEnabled = false
}

Objective-C

#pragma mark GADNativeContentAdLoaderDelegate implementation

- (void)adLoader:(GADAdLoader *)adLoader
    didReceiveNativeContentAd:(GADNativeContentAd *)nativeContentAd {
  // Create and place ad in view hierarchy.
  GADNativeContentAdView *contentAdView =
      [[[NSBundle mainBundle] loadNibNamed:@"NativeContentAdView"
                                     owner:nil
                                   options:nil] firstObject];
  // TODO: Make sure to add the GADNativeContentAdView to the view hierarchy.

  // Associate the content ad view with the content ad object. This is required to make the ad
  // clickable.
  contentAdView.nativeContentAd = nativeContentAd;

  // Populate the content ad view with the content ad assets.
  // Some assets are guaranteed to be present in every content ad.
  ((UILabel *)contentAdView.headlineView).text = nativeContentAd.headline;
  ((UILabel *)contentAdView.bodyView).text = nativeContentAd.body;
  ((UIImageView *)contentAdView.imageView).image =
      ((GADNativeAdImage *)[nativeContentAd.images firstObject]).image;
  ((UILabel *)contentAdView.advertiserView).text = nativeContentAd.advertiser;
  [((UIButton *)contentAdView.callToActionView)setTitle:nativeContentAd.callToAction
                                               forState:UIControlStateNormal];

  // Other assets are not, however, and should be checked first.
  if (nativeContentAd.logo && nativeContentAd.logo.image) {
    ((UIImageView *)contentAdView.logoView).image = nativeContentAd.logo.image;
    contentAdView.logoView.hidden = NO;
  } else {
    contentAdView.logoView.hidden = YES;
  }

  // In order for the SDK to process touch events properly, user interaction should be disabled on
  // all views associated with the GADNativeContentAdView. Since UIButton has userInteractionEnabled
  // set to YES by default, views of this type must explicitly set userInteractionEnabled to NO.
  contentAdView.callToActionView.userInteractionEnabled = NO;
}

Our GitHub repository has the complete implementations for Native custom rendering app install ads and content ads written in both Swift and Objective-C.

Download DFP Custom Rendering Example

Test native ad code

Please note that at the current time, publishers should not use the testDevices property with native ad requests. Using your test ad unit ID with no devices registered via the testDevices property is the current best practice for testing.

Send feedback about...

SDK for AdX Users on iOS
Need help? Visit our support page.