Native Ads Advanced (Unified)

Native Ads Advanced is currently in a limited beta release. If you are interested in participating, reach out to your account manager.

Native ads are ad assets that are 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 an ad loads, your app receives an ad object that contains its assets, and the app (rather than the SDK) is then responsible for displaying them.

This guide will show you how to use the Google Mobile Ads SDK to implement 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, so if you haven't already, consider running through our Get Started guide.

Always test with test ads

Before you begin, remember that when building and testing your apps, you should be sure that you're using test ads rather than live, production ads. Testing with production ads could lead to suspension of your account.

The easiest way to load test ads is to use our dedicated test ad unit ID for all native advanced ads on iOS:

ca-app-pub-3940256099942544/3986624511

It's been specially configured to return test ads for every request, and you're free to use it in your own apps while coding, testing, and debugging. Just make sure you replace it with your own ad unit ID before publishing your app.

For more information about how the Mobile Ads SDK's test ads work, see Test Ads.

Loading ads

There are two system-defined formats for native ads: app install and content.

Both types of ads are represented by one class: GADUnifiedNativeAd. An instance of this class contains the assets for the native ad. Note that depending on the type of ad represented by the GADUnifiedNativeAd, some fields will not be populated (i.e., they will be nil).

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

Initialize the ad loader

Before you can load an ad, you have to initialize the ad loader. The following code demonstrates how to initialize a GADAdLoader:

Swift

adLoader = GADAdLoader(adUnitID: "ca-app-pub-3940256099942544/3986624511",
    rootViewController: self,
    adTypes: [ kGADAdLoaderAdTypeUnifiedNative ],
    options: [ ... ad loader options objects ... ])
adLoader.delegate = self

Objective-C

self.adLoader = [[GADAdLoader alloc]
      initWithAdUnitID:@"ca-app-pub-3940256099942544/3986624511"
    rootViewController:rootViewController
               adTypes:@[ ... ad type constants ... ]
               options:@[ ... ad loader options objects ... ]];
self.adLoader.delegate = self;

You'll need an ad unit ID (you can use the test ID), constants to pass in the adTypes array to specify which native formats you want to request, and any options you wish to set in the options parameter. The list of possible values for the options parameter can be found below in the Setting native ad options section.

The adTypes array should contain the following constant:

Implement the ad loader delegate

The ad loader delegate needs to implement protocols specific your ad type. For unified native ads:

  • GADUnifiedNativeAdLoaderDelegate This protocol includes a message that's sent to the delegate when a unified native ad has loaded:

    Swift

    public func adLoader(_ adLoader: GADAdLoader,
        didReceive nativeAd: GADUnifiedNativeAd)
    

    Objective-C

    - (void)adLoader:(GADAdLoader *)adLoader
        didReceiveNativeAd:(GADUnifiedNativeAd *)nativeAd;
    

Request the 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.

When to request ads

Apps 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.

While prefetching ads is a great technique, it's important that you don't keep old ads around forever without displaying them. Any native ad objects that have been held without display for longer than an hour should be discarded and replaced with new ads from a new request.

Determining when loading has finished

After an app calls loadRequest:, it can get the results of the request via calls to:

A request for a single ad will result in one call to one of those methods.

A request for multiple ads will result in at least one callback to the above methods, but no more than the maximum number of ads requested.

In addition, GADAdLoaderDelegate offers the adLoaderDidFinishLoading callback. This delegate method indicates that an ad loader has finished loading ads and no other ads or errors will be reported for the request. Here's an example of how to use it when loading several native ads at one time:

Swift

class ViewController: UIViewController, GADUnifiedNativeAdLoaderDelegate {

  var adLoader: GADAdLoader!

  override func viewDidLoad() {
    super.viewDidLoad()

    let multipleAdsOptions = GADMultipleAdsAdLoaderOptions()
    multipleAdsOptions.numberOfAds = 5

    adLoader = GADAdLoader(adUnitID: YOUR_AD_UNIT_ID, rootViewController: self,
        adTypes: [GADAdLoaderAdType.unifiedNative],
        options: [multipleAdsOptions])
    adLoader.delegate = self
    adLoader.load(GADRequest())
  }
 
  func adLoader(_ adLoader: GADAdLoader,
                didReceive nativeAd: GADUnifiedNativeAd) {
    // A unified native ad has loaded, and can be displayed.
  }
 
  func adLoaderDidFinishLoading(_ adLoader: GADAdLoader) {
      // The adLoader has finished loading ads, and a new request can be sent.
  }

}

Objective-C

@interface ViewController () <GADUnifiedNativeAdLoaderDelegate, GADVideoControllerDelegate>
@property(nonatomic, strong) GADAdLoader *adLoader;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  GADMultipleAdsAdLoaderOptions *multipleAdsOptions =
      [[GADMultipleAdsAdLoaderOptions alloc] init];
  multipleAdsOptions.numberOfAds = 5;

  self.adLoader = [[GADAdLoader alloc] initWithAdUnitID:YOUR_AD_UNIT_ID
          rootViewController:self
                     adTypes:@[kGADAdLoaderAdTypeUnifiedNative]
                     options:@[multipleAdsOptions]];
  self.adLoader.delegate = self;
  [self.adLoader loadRequest:[GADRequest request]];
}

 
- (void)adLoader:(GADAdLoader *)adLoader
    didReceiveUnifiedNativeAd:(GADUnifiedNativeAd *)nativeAd {
   // A unified native ad has loaded, and can be displayed.
}
 
- (void)adLoaderDidFinishLoading:(GADAdLoader *) adLoader {
  // The adLoader has finished loading ads, and a new request can be sent.
}

@end

Handling failed requests

The above protocols extend the GADAdLoaderDelegate protocol, which defines a message sent when ads fail to load. You can use the GADRequestError object to determine the cause of the error.

Swift

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

Objective-C

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

Get notified of native ad events

To be notified of events related to the native ad interactions, set the delegate property of the native ad:

Swift

nativeAd.delegate = self

Objective-C

nativeAd.delegate = self;

Then implement GADUnifiedNativeAdDelegate to receive the following delegate calls:

Swift

func nativeAdDidRecordImpression(_ nativeAd: GADUnifiedNativeAd) {
  // The native ad was shown.
}

func nativeAdDidRecordClick(_ nativeAd: GADUnifiedNativeAd) {
  // The native ad was clicked on.
}

func nativeAdWillPresentScreen(_ nativeAd: GADUnifiedNativeAd) {
  // The native ad will present a full screen view.
}

func nativeAdWillDismissScreen(_ nativeAd: GADUnifiedNativeAd) {
  // The native ad will dismiss a full screen view.
}

func nativeAdDidDismissScreen(_ nativeAd: GADUnifiedNativeAd) {
  // The native ad did dismiss a full screen view.
}

func nativeAdWillLeaveApplication(_ nativeAd: GADUnifiedNativeAd) {
  // The native ad will cause the application to become inactive and
  // open a new application.
}

Objective-C

- (void)nativeAdDidRecordImpression:(GADUnifiedNativeAd *)nativeAd {
  // The native ad was shown.
}

- (void)nativeAdDidRecordClick:(GADUnifiedNativeAd *)nativeAd {
  // The native ad was clicked on.
}

- (void)nativeAdWillPresentScreen:(GADUnifiedNativeAd *)nativeAd {
  // The native ad will present a full screen view.
}

- (void)nativeAdWillDismissScreen:(GADUnifiedNativeAd *)nativeAd {
  // The native ad will dismiss a full screen view.
}

- (void)nativeAdDidDismissScreen:(GADUnifiedNativeAd *)nativeAd {
  // The native ad did dismiss a full screen view.
}

- (void)nativeAdWillLeaveApplication:(GADUnifiedNativeAd *)nativeAd {
  // The native ad will cause the application to become inactive and
  // open a new application.
}

Native ad options

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

Swift

adLoader = GADAdLoader(adUnitID: "ca-app-pub-3940256099942544/3986624511",
    rootViewController: self,
    adTypes: [ ... ad type constants ... ],
    options: [ ... ad loader options objects ... ])

Objective-C

self.adLoader = [[GADAdLoader alloc]
      initWithAdUnitID:@"ca-app-pub-3940256099942544/3986624511"
    rootViewController:rootViewController
               adTypes:@[ ... ad type constants ... ]
               options:@[ ... ad loader options objects ... ]];

This optional array holds one or more instances of a GADAdLoaderOptions subclass (GADNativeAdImageAdLoaderOptions), which are objects that an app can use to indicate its preferences for how native ads should be loaded and behave.

GADNativeAdImageAdLoaderOptions contains properties relating to images in Native Advanced ads. Apps can control how a GADAdLoader handles Native Ads Advanced image assets by creating a GADNativeAdImageAdLoaderOptions object, setting its properties (disableImageLoading, preferredImageOrientation, and shouldRequestMultipleImages), 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, which is the default (NO in Objective-C), the SDK will fetch image assets automatically and populate both the image and the imageURL properties for you. If it's set to true (or YES in Objective-C), the SDK will only populate imageURL, allowing you to download the actual images at your discretion.
preferredImageOrientation

Some creatives have multiple images available 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 (the 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.

GADNativeAdViewOptions

GADNativeAdViewAdOptions objects are used to indicate preferences for how native ad views should represent ads. They have a single property: preferredAdChoicesPosition, which you can use to specify the location where the AdChoices icon should be placed. The icon can appear at any corner of the ad, and defaults to GADAdChoicesPositionTopRightCorner. The possible values for this property are:

  • GADAdChoicesPositionTopRightCorner
  • GADAdChoicesPositionTopLeftCorner
  • GADAdChoicesPositionBottomRightCorner
  • GADAdChoicesPositionBottomLeftCorner

Here's an example showing how to place the AdChoices icon in the top left corner of an ad:

Swift

let adViewOptions = GADNativeAdViewAdOptions()
adViewOptions.preferredAdChoicesPosition = .topLeftCorner
adLoader = GADAdLoader(adUnitID: "ca-app-pub-3940256099942544/3986624511",
    rootViewController: self,
    adTypes: [ ... ad type constants ... ],
    options: [ ... ad loader options objects ... ])

Objective-C

GADNativeAdViewAdOptions *adViewOptions = [[GADNativeAdViewAdOptions alloc] init];
adViewOptions.preferredAdChoicesPosition = GADAdChoicesPositionTopLeftCorner;
self.adLoader = [[GADAdLoader alloc]
      initWithAdUnitID:@"ca-app-pub-3940256099942544/3986624511"
    rootViewController:self
               adTypes:@[ ... ad type constants ...  ]
               options:@[ ... ad loader options objects ... ]];

GADVideoOptions

GADVideoOptions objects are used to indicate how native video assets should be displayed. They offer a single property: startMuted.

This boolean indicates whether video assets should begin playback in a muted state. The default value is true.

GADMultipleAdsAdLoaderOptions

GADMultipleAdsAdLoaderOptions objects allow publishers to instruct an ad loader to load multiple ads in a single request. Ads loaded in this way are guaranteed to be unique. GADMultipleAdsAdLoaderOptions has a single property, numberOfAds, which represents the number of ads the ad loader should attempt to return for the request. By default this value is one, and it's capped at a maximum of five (even if an app requests more ads, at most five will be returned). The actual number of ads returned is not guaranteed, but will be between zero and numberOfAds.

Displaying 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.

GADUnifiedNativeAdView

For the GADUnifiedNativeAd, there is a corresponding "ad view" class: GADUnifiedNativeAdView. This ad view class is a UIView that publishers should use to display the ad. A single GADUnifiedNativeAdView, for example, can display a single instance of a GADUnifiedNativeAd. Each of the UIView objects used to display that ad's assets should be subviews of that GADUnifiedNativeAdView object.

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

The GADUnifiedNativeAdView class also provides IBOutlets used to register the view used for each individual asset, and a method to register the GADUnifiedNativeAd 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.

The AdChoices overlay

For indirect native ads (delivered via AdMob backfill or through Ad Exchange or AdSense), an AdChoices overlay is added by the SDK. Please leave space in your preferred corner of your native ad view for the automatically inserted AdChoices logo. Also, make sure the AdChoices overlay is placed on content that allows the icon to be easily seen. For more information on the overlay's appearance and function, aee the programmatic native ads implementation guidelines.

Ad attribution

When displaying programmatic native ads, you must display an ad attribution to denote that the view is an advertisement.

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.

Laying out the UIViews

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 a native ad might look:

Note the Custom Class value in the top right of the image. It's set to GADUnifiedNativeAdView. This is the ad view class that is used to display a GADUnifiedNativeAd.

For system-defined formats, you'll need to use the ad view class that matches the ad format you intend the layout to show.

When adding the imageView, be sure to change the contentMode to Aspect Fit to ensure that the images are displayed at the correct aspect ratio.

Linking outlets to views

Once the views are in place and you've assigned the correct ad view class to the layout, 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 ad: In the outlet panel, the outlets in GADUnifiedNativeAdView 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.

Displaying 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 ad in the view defined above:

Swift

// Mark: - GADUnifiedNativeAdLoaderDelegate
func adLoader(_ adLoader: GADAdLoader, didReceive nativeAd: GADUnifiedNativeAd) {
  print("Received unified native ad: \(nativeAd)")
  refreshAdButton.isEnabled = true
  // Create and place ad in view hierarchy.
  let nibView = Bundle.main.loadNibNamed("UnifiedNativeAdView", owner: nil, options: nil)?.first
  guard let nativeAdView = nibView as? GADUnifiedNativeAdView else {
    return
  }
  setAdView(nativeAdView)

  nativeAdView.nativeAd = nativeAd
  // Populate the native ad view with the native ad assets.
  // Some assets are guaranteed to be present in every native ad.
  (nativeAdView.headlineView as? UILabel)?.text = nativeAd.headline
  (nativeAdView.bodyView as? UILabel)?.text = nativeAd.body
  (nativeAdView.callToActionView as? UIButton)?.setTitle(nativeAd.callToAction, for: .normal)

  // Some native ads include a video asset, while others do not. Apps can
  // use the GADVideoController's hasVideoContent property to determine if one
  // is present, and adjust their UI accordingly.
  // The UI for this controller constrains the image view's height to match the
  //  media view's height, so by changing the one here, the height of both views
  // are being adjusted.
  if let controller = nativeAd.videoController, controller.hasVideoContent() {
    // The video controller has content. Show the media view.
    if let mediaView = nativeAdView.mediaView {
      mediaView.isHidden = false
      nativeAdView.imageView?.isHidden = true
      // This app uses a fixed width for the GADMediaView and changes its height
      // to match the aspect ratio of the video it displays.
      let heightConstraint = NSLayoutConstraint(item: mediaView,
                                                attribute: .height,
                                                relatedBy: .equal,
                                                toItem: mediaView,
                                                attribute: .width,
                                                multiplier: CGFloat(1 / controller.aspectRatio()),
                                                constant: 0)
      heightConstraint.isActive = true
    }
    // By acting as the delegate to the GADVideoController, this ViewController
    // receives messages about events in the video lifecycle.
    controller.delegate = self
    videoStatusLabel.text = "Ad contains a video asset."
  }
  else {
    // If the ad doesn't contain a video asset, the first image asset is shown
    // in the image view. The existing lower priority height constraint is used.
    nativeAdView.mediaView?.isHidden = true
    nativeAdView.imageView?.isHidden = false
    let firstImage: GADNativeAdImage? = nativeAd.images?.first
    (nativeAdView.imageView as? UIImageView)?.image = firstImage?.image
    videoStatusLabel.text = "Ad does not contain a video."
  }
  // These assets are not guaranteed to be present. Check that they are before
  // showing or hiding them.
  (nativeAdView.iconView as? UIImageView)?.image = nativeAd.icon?.image
  if let _ = nativeAd.icon {
    nativeAdView.iconView?.isHidden = false
  } else {
    nativeAdView.iconView?.isHidden = true
  }
  (nativeAdView.starRatingView as? UIImageView)?.image = imageOfStars(fromStarRating:nativeAd.starRating)
  if let _ = nativeAd.starRating {
    nativeAdView.starRatingView?.isHidden = false
  }
  else {
    nativeAdView.starRatingView?.isHidden = true
  }
  (nativeAdView.storeView as? UILabel)?.text = nativeAd.store
  if let _ = nativeAd.store {
    nativeAdView.storeView?.isHidden = false
  }
  else {
    nativeAdView.storeView?.isHidden = true
  }
  (nativeAdView.priceView as? UILabel)?.text = nativeAd.price
  if let _ = nativeAd.price {
    nativeAdView.priceView?.isHidden = false
  }
  else {
    nativeAdView.priceView?.isHidden = true
  }
  (nativeAdView.advertiserView as? UILabel)?.text = nativeAd.advertiser
  if let _ = nativeAd.advertiser {
    nativeAdView.advertiserView?.isHidden = false
  }
  else {
    nativeAdView.advertiserView?.isHidden = true
  }
  // In order for the SDK to process touch events properly, user interaction
  // should be disabled.
  nativeAdView.callToActionView?.isUserInteractionEnabled = false
}

Objective-C

#pragma mark GADUnifiedNativeAdLoaderDelegate implementation

- (void)adLoader:(GADAdLoader *)adLoader didReceiveUnifiedNativeAd:(GADUnifiedNativeAd *)nativeAd {
  NSLog(@"Received unified native ad: %@", nativeAd);
  self.refreshButton.enabled = YES;

  // Create and place ad in view hierarchy.
  GADUnifiedNativeAdView *nativeAdView =
      [[NSBundle mainBundle] loadNibNamed:@"UnifiedNativeAdView" owner:nil options:nil].firstObject;
  [self setAdView:nativeAdView];

  // Populate the native ad view with the native ad assets.
  // Some assets are guaranteed to be present in every native ad.
  ((UILabel *)nativeAdView.headlineView).text = nativeAd.headline;
  ((UILabel *)nativeAdView.bodyView).text = nativeAd.body;
  [((UIButton *)nativeAdView.callToActionView)setTitle:nativeAd.callToAction
                                              forState:UIControlStateNormal];

  // Some native ads include a video asset, while others do not. Apps can
  // use the GADVideoController's hasVideoContent property to determine if one
  // is present, and adjust their UI accordingly.

  // The UI for this controller constrains the image view's height to match the
  // media view's height, so by changing the one here, the height of both views
  // are being adjusted.
  if (nativeAd.videoController.hasVideoContent) {
    // The video controller has content. Show the media view.
    nativeAdView.mediaView.hidden = NO;
    nativeAdView.imageView.hidden = YES;

    // This app uses a fixed width for the GADMediaView and changes its height
    // to match the aspect ratio of the video it displays.
    NSLayoutConstraint *heightConstraint =
        [NSLayoutConstraint constraintWithItem:nativeAdView.mediaView
                                     attribute:NSLayoutAttributeHeight
                                     relatedBy:NSLayoutRelationEqual
                                        toItem:nativeAdView.mediaView
                                     attribute:NSLayoutAttributeWidth
                                    multiplier:(1 / nativeAd.videoController.aspectRatio)
                                      constant:0];
    heightConstraint.active = YES;

    // By acting as the delegate to the GADVideoController, this ViewController
    // receives messages about events in the video lifecycle.
    nativeAd.videoController.delegate = self;

    self.videoStatusLabel.text = @"Ad contains a video asset.";
  } else {
    // If the ad doesn't contain a video asset, the first image asset is shown
    // in the image view. The existing lower priority height constraint is used.
    nativeAdView.mediaView.hidden = YES;
    nativeAdView.imageView.hidden = NO;

    GADNativeAdImage *firstImage = nativeAd.images.firstObject;
    ((UIImageView *)nativeAdView.imageView).image = firstImage.image;

    self.videoStatusLabel.text = @"Ad does not contain a video.";
  }

  // These assets are not guaranteed to be present. Check that they are before
  // showing or hiding them.
  ((UIImageView *)nativeAdView.iconView).image = nativeAd.icon.image;
  if (nativeAd.icon != nil) {
    nativeAdView.iconView.hidden = NO;
  } else {
    nativeAdView.iconView.hidden = YES;
  }

  ((UIImageView *)nativeAdView.starRatingView).image = [self imageForStars:nativeAd.starRating];
  if (nativeAd.starRating) {
    nativeAdView.starRatingView.hidden = NO;
  } else {
    nativeAdView.starRatingView.hidden = YES;
  }

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

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

  ((UILabel *)nativeAdView.advertiserView).text = nativeAd.advertiser;
  if (nativeAd.advertiser) {
    nativeAdView.advertiserView.hidden = NO;
  } else {
    nativeAdView.advertiserView.hidden = YES;
  }

  // In order for the SDK to process touch events properly, user interaction
  // should be disabled.
  nativeAdView.callToActionView.userInteractionEnabled = NO;
}

Native video

In addition to images, text, and numbers, some native ads contain video assets. Not every ad will have one and apps are not required to display videos when they're included with an ad.

GADMediaView

Video assets are displayed to users via GADMediaView. This is a UIView that can be defined in a xib file or constructed dynamically. It should be placed within the view hierarchy of a GADNativeAdView, as with any other asset view.

Unlike other asset views, however, apps do not need to manually populate a GADMediaView with its asset. The SDK handles this automatically as follows:

  • If a video asset is available, it's buffered and starts playing inside the GADMediaView.
  • If the ad does not contain a video asset, the first image asset is downloaded and placed inside the GADMediaView instead.

This autopopulation of the GADMediaView with an available image asset does not always work when you're using mediation. Because not all mediation adapters guarantee that they'll create a media view for every ad, it's possible for a blank one to be returned for mediated ads. If you're using mediation, you should check the hasVideoContent property of an ad's GADVideoController to see if it contains a video asset, before displaying theGADMediaView. If there is no video content, you should display an image view that you populate manually with a relevant image.

Here's a snippet from the Native Advanced example: (Swift | Objective-C) that checks hasVideoContent and uses a UIImageView instead of GADMedaView when no video asset is present in the ad:

Swift

// The UI for this controller constrains the image view's height to match the
// media view's height, so by changing the one here, the height of both views
// are being adjusted.
if let controller = nativeAd.videoController, controller.hasVideoContent() {
  // The video controller has content. Show the media view.
  if let mediaView = nativeAdView.mediaView {
    mediaView.isHidden = false
    nativeAdView.imageView?.isHidden = true
    // This app uses a fixed width for the GADMediaView and changes its height
    // to match the aspect ratio of the video it displays.
    if controller.aspectRatio() > 0 {
      heightConstraint = NSLayoutConstraint(item: mediaView,
                                       attribute: .height,
                                       relatedBy: .equal,
                                          toItem: mediaView,
                                       attribute: .width,
                                      multiplier: CGFloat(1 / controller.aspectRatio()),
                                                constant: 0)
      heightConstraint?.isActive = true
    }
  }


  // By acting as the delegate to the GADVideoController, this ViewController
  // receives messages about events in the video lifecycle.
  controller.delegate = self
  videoStatusLabel.text = "Ad contains a video asset."

}
else {
  // If the ad doesn't contain a video asset, the first image asset is shown in
  // the image view. The existing lower priority height constraint is used.
  nativeAdView.mediaView?.isHidden = true
  nativeAdView.imageView?.isHidden = false
  let firstImage: GADNativeAdImage? = nativeAd.images?.first
  (nativeAdView.imageView as? UIImageView)?.image = firstImage?.image
  videoStatusLabel.text = "Ad does not contain a video."
}

Objective-C

// The UI for this controller constrains the image view's height to match the
// media view's height, so by changing the one here, the height of both views
// are being adjusted.
if (nativeAd.videoController.hasVideoContent) {
  // The video controller has content. Show the media view.
  nativeAdView.mediaView.hidden = NO;
  nativeAdView.imageView.hidden = YES;

  // This app uses a fixed width for the GADMediaView and changes its height
  // to match the aspect ratio of the video it displays.

  if (nativeAd.videoController.aspectRatio > 0) {
    self.heightConstraint =
        [NSLayoutConstraint constraintWithItem:nativeAdView.mediaView
                                     attribute:NSLayoutAttributeHeight
                                     relatedBy:NSLayoutRelationEqual
                                        toItem:nativeAdView.mediaView
                                     attribute:NSLayoutAttributeWidth
                                    multiplier:(1 / nativeAd.videoController.aspectRatio)
                                      constant:0];
    self.heightConstraint.active = YES;
  }

  // By acting as the delegate to the GADVideoController, this ViewController
  // receives messages about events in the video lifecycle.
  nativeAd.videoController.delegate = self;
  self.videoStatusLabel.text = @"Ad contains a video asset.";
}
else {
  // If the ad doesn't contain a video asset, the first image asset is shown
  // in the image view. The existing lower priority height constraint is used.
  nativeAdView.mediaView.hidden = YES;
  nativeAdView.imageView.hidden = NO;

  GADNativeAdImage *firstImage = nativeAd.images.firstObject;
  ((UIImageView *)nativeAdView.imageView).image = firstImage.image;

  self.videoStatusLabel.text = @"Ad does not contain a video.";
}

While you aren't required to include a GADMediaView in your app's layout if don't intend to display video assets, it's recommended that you do.

GADVideoController

The GADVideoController class is used to retrieve information about video assets. GADUnifiedNativeAd offers a videoController property that exposes the GADVideoController for each ad:

Swift

let videoController = myUnifiedNativeAd.videoController

Objective-C

GADVideoController *videoController = myUnifiedNativeAd.videoController

This property is never nil, even when the ad doesn't contain a video asset.

GADVideoController offers the following methods for querying video state:

  • hasVideoContent - True if the ad includes a video asset, false otherwise.
  • aspectRatio - The aspect ratio of the video (width/height) or 0 (zero) (if no video asset is present).

Apps can also set a GADViewControllerDelegate for the GADViewController to be notified of events in the lifecycle of a video asset. GADViewControllerDelegate offers a single optional message, videoControllerDidEndVideoPlayback, which is sent when a video completes playback.

Here's an example of GADViewControllerDelegate in action:

Swift

class ViewController: UIViewController, GADUnifiedNativeAdLoaderDelegate,
    GADVideoControllerDelegate {

  func adLoader(_ adLoader: GADAdLoader, didReceive nativeAd:
                GADUnifiedNativeAd) {
    ...
    nativeAd.videoController.delegate = self
    ...
  }

  ...
  func videoControllerDidEndVideoPlayback(_ videoController: Any!) {
    // Here apps can take action knowing video playback is finished.
    // This is handy for things like unmuting audio, and so on.
  }
}

Objective-C

@interface ViewController () <GADUnifiedNativeAdLoaderDelegate,
        GADVideoControllerDelegate>

- (void)adLoader:(GADAdLoader *)adLoader
    didReceiveNativeAd:(GADUnifiedNativeAd) *)nativeAd {
  ...
  nativeAd.videoController.delegate = self;
  ...
}

...

- (void)videoControllerDidEndVideoPlayback:(GADVideoController *)videoController {
  // Here apps can take action knowing video playback is finished.
  // This is handy for things like unmuting audio, and so on.
}

@end

Additional resources

Samples

Codelab

Next steps

Send feedback about...

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