AFS for Mobile Apps (AFSMA) Implementation for iOS

Prerequisites

This implementation guide assumes you are familiar with the following:

Overview

This document outlines the process to integrate AFS for Mobile Apps (AFSMA) ads in your iOS mobile app. AFSMA ads are also sometimes referred to as dynamic height search ads. To request and render AFSMA ads on iOS, you will need to implement the following:

GADSearchBannerView

  • This class inherits from the iOS UIView class and displays the AFSMA ads. The GADSearchBannerView makes the request for an ad with a GADDynamicHeightSearchRequest and renders the returned ads. The GADSearchBannerView should be added to any of the app's existing views; typically it's the parent view controller that holds the view that the GADSearchBannerView is added to. The appropriate delegates should be set on the GADSearchBannerView.
  • The GADSearchBannerView must be instantiated with initWithAdSize:kGADAdSizeFluid to request AFSMA ads. Instantiating GADSearchBannerView with initWithAdSize:kGADAdSizeBanner requests legacy AFSMA ads.
  • The adUnitID property on this object needs to be set to your property code.

GADDynamicHeightSearchRequest

  • This object encapsulates the ad request parameters. This is analogous to setting parameters in the JavaScript ad request objects (page options, unit options) for AFS desktop and mobile web.

(void)adView:(GADBannerView *)bannerView willChangeAdSizeTo:(GADAdSize)size

  • This callback is called when the ad request returns. Since the returned ad unit could contain a number of ads with different extensions, the exact size of the ad unit is unknown when the ad request is made. Once the ad is returned, the banner view needs to be updated to accommodate the new size of the ad unit. Code to resize the GADSearchBannerView in its parent view should be implemented here.

Example implementation

The example below demonstrates using a GBannerViewController to create a GADSearchBannerView as a subview of a UIScrollView. To properly request AFSMA ads, the GADSearchBannerView object must be instantiated with initWithAdSize:kGADAdSizeFluid.

// GBannerViewController.m implementation

@interface GBannerViewController () <GADAdSizeDelegate,
                                     GADBannerViewDelegate>

@property(nonatomic, strong) GADSearchBannerView *searchBannerView;

@property(nonatomic, strong) UIScrollView *scrollView;

@end

@implementation GBannerViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  // Create the scroll view.
  ....
  ....

  // Create the banner.
  self.searchBannerView = [[GADSearchBannerView alloc] initWithAdSize:kGADAdSizeFluid];

  // Replace with your pub ID (e.g. ms-app-pub-9616389000213823).
  self.searchBannerView.adUnitID = @"ms-app-pub-################";

  // Set the initial location and size of the banner. The initial height
  // is set to 0 since we might not get an ad back.
  self.searchBannerView.frame = CGRectMake(0,
                                           0,
                                           CGRectGetWidth(self.view.bounds),
                                           0);
  self.searchBannerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;

  // Set the delegate properties.
  self.searchBannerView.adSizeDelegate = self;
  self.searchBannerView.delegate = self;

  // Add the new search banner into the parent scrollView.
  [self.scrollView addSubview:self.searchBannerView];
  }

Within the same GBannerViewController, create a GADDynamicHeightSearchRequest that dictates the parameters of the ad that will be rendered in the GADSearchView.

// Create a search request and load the banner.
GADDynamicHeightSearchRequest *searchRequest = [[GADDynamicHeightSearchRequest alloc] init];

// Ad request options (set using GADDynamicHeightSearchRequest properties).
searchRequest.query = @"flowers";
searchRequest.numberOfAds = 2;
searchRequest.CSSWidth = @"300";     // Equivalent to "width" CSA parameter
searchRequest.siteLinksExtensionEnabled = YES;
searchRequest.sellerRatingsExtensionEnabled = YES;
searchRequest.clickToCallExtensionEnabled = YES;

Other customization options are possible by setting additional properties on the GADDynamicHeightSearchRequest object.

To make an ad request, call loadRequest with the GADDynamicHeightSearchRequest object from the GADSearchBannerView object:

[self.searchBannerView loadRequest:searchRequest];

To have the parent view properly accommodate the GADSearchBannerView once the ads return, the following callback must be implemented.

// Callback to update the parent view height.
- (void)adView:(GADBannerView *)bannerView willChangeAdSizeTo:(GADAdSize)size {
  // Update the banner view based on the ad size.
  CGRect newFrame = self.searchBannerView.frame;
  newFrame.size.height = size.size.height;
  self.searchBannerView.frame = newFrame;

  // Perform any additional logic needed due to banner view size change.
  ...
}

Advanced options

Most of the ad request parameters can be set via properties on the GADDynamicHeightSearchRequest object (searchRequest above). Other parameters will need to be set using key-value pairs with the setAdvancedOptionValue method:

// Advanced customization options (set using key-value pair).

// Set a parameter (parameter_name) and its value (parameter_value).
[searchRequest setAdvancedOptionValue:@"parameter_value"
                               forKey:@"parameter_name"];

// Example: Show visible URL below description (domainLinkAboveDescription: false).
[searchRequest setAdvancedOptionValue:@"false"
                               forKey:@"domainLinkAboveDescription"];

See the complete list of available parameters.

Investigating errors

The GADBannerViewDelegate contains a callback to help you investigate errors:

- (void)adView:(GADBannerView *)bannerView didFailToReceiveAdWithError:(GADRequestError *)error {

  // This callback is triggered when the ad request fails.
  // Add code here to debug the error object to discover causes of failure
  NSLog(@"Ad call failed due to %@", error.userInfo[@"NSUnderlyingError"]);
}

If an ad request fails, you can use this callback to properly handle the error and investigate the error through the error object.