Ad Network Mediation Adapter Development

This guide is intended for ad networks looking to build a mediation adapter. If you are a publisher, see the publisher mediation instructions.

A mediation adapter is the layer of communication between your ad network and Google Mobile Ads Mediation. Adapters serve ads from your ad network while forwarding relevant ad events to AdMob. An adapter is responsible for implementing the GADMAdNetworkAdapter protocol to ensure it provides the required capabilities.

Prerequisites

  • Xcode 15.3 or higher
  • Deployment target of 8.0 or higher
  • Additional headers from the Mediation Adapters folder of Google Mobile Ads iOS SDK download

Your ad network must have an established working relationship with Google to create a mediation adapter.

Sample Ad Network

This guide demonstrates how to build an adapter for the Sample Ad Network. The Sample Ad Network SDK contains classes that are representative of the classes offered by most ad networks:

@interface SampleBanner : UILabel

@property(nonatomic, copy) NSString *adUnit;
@property(nonatomic, weak) id<SampleBannerAdDelegate> delegate;
- (void)fetchAd:(SampleAdRequest *)request;

@end

typedef NS_ENUM(NSInteger, SampleErrorCode) {
  SampleErrorCodeBadRequest = 0,
  SampleErrorCodeUnknown = 1,
  SampleErrorCodeNetworkError = 2,
  SampleErrorCodeNoInventory = 3,
};

@interface SampleAdRequest : NSObject

@property(nonatomic, assign) BOOL testMode;
@property(nonatomic, copy) NSArray *keywords;

@end

@interface SampleInterstitial : NSObject

@property(nonatomic, copy) NSString *adUnit;
@property(nonatomic, weak) id<SampleInterstitialAdDelegate> delegate;
@property(nonatomic, assign, getter=isInterstitialLoaded) BOOL interstitialLoaded;
- (void)fetchAd:(SampleAdRequest *)request;
- (void)show;

@end

@protocol SampleBannerAdDelegate
- (void)bannerDidLoad:(SampleBanner *)banner;
- (void)banner:(SampleBanner *)banner didFailToLoadAdWithError:(SampleErrorCode)error;
- (void)bannerWillLeaveApplication:(SampleBanner *)banner;

@end

@protocol SampleInterstitialAdDelegate<NSObject>
- (void)interstitialDidLoad:(SampleInterstitial *)interstitial;
- (void)interstitial:(SampleInterstitial *)interstitial
    didFailToLoadAdWithError:(SampleErrorCode)error;
- (void)interstitialWillPresentScreen:(SampleInterstitial *)interstitial;
- (void)interstitialWillDismissScreen:(SampleInterstitial *)interstitial;
- (void)interstitialDidDismissScreen:(SampleInterstitial *)interstitial;
- (void)interstitialWillLeaveApplication:(SampleInterstitial *)interstitial;

@end

See the complete sample SDK implementation for more information about these classes.

Connector

Mediation adapters interact with the Google Mobile Ads SDK using an object that implements the GADMAdNetworkConnector protocol. From here on, we'll call this object the connector. The connector exposes necessary information for ad requests and provides a means to call back to mediation for ad events and user interactions. The connector is provided to mediation adapters at the time of initialization. Set up your adapter to store the connector in an instance variable:

- (id)initWithGADMAdNetworkConnector:(id<GADMAdNetworkConnector>)c {
  if ((self = [super init])) {
    _connector = c;
  }
  return self;
}

Server parameters

Your ad network likely needs identifier(s) to identify a publisher. The Sample Ad Network, for example, requires an ad unit. These required server parameters are provided to the adapter via the credentials method, which returns an NSDictionary of identifier(s) and corresponding values. The following line of code retrieves the server parameter named ad_unit for the Sample Ad Network from the connector:

self.interstitialAd.adUnit = [[self.connector credentials] objectForKey:@"ad_unit"];

Mediation network setup

Ad networks must inform AdMob of the required server parameters for their network. This enables AdMob to configure your network in the front end.

When enabling your network for mediation in the front end, AdMob requires you to enter values necessary to instantiate your adapter. The screenshot below shows that an Application Placement Identifier (APID) is required for Millennial Media and an App ID is required for InMobi.

Check out this article for more information on configuring mediation ad networks.

Make a mediation ad request

For mediation banner requests, the getBannerWithSize method is called immediately after the adapter is instantiated. This method does not return anything. It signals the adapter to start an asynchronous ad fetch over the network. Have your adapter listen to callbacks for your SDK. If your SDK does not support the given ad size or does not support banner ads, invoke the adapter:didFailAd: method on the connector.

An implementation of getBannerWithSize for the Sample Ad Network looks like this:

- (void)getBannerWithSize:(GADAdSize)adSize {
  //The adapter should fail immediately if the adSize is not supported
  if (!GADAdSizeEqualToSize(adSize, GADAdSizeBanner) &&
      !GADAdSizeEqualToSize(adSize, GADAdSizeMediumRectangle) &&
      !GADAdSizeEqualToSize(adSize, GADAdSizeFullBanner) &&
      !GADAdSizeEqualToSize(adSize, GADAdSizeLeaderboard)) {
    NSString *errorDesc =
        [NSString stringWithFormat:@"Invalid ad type %@, not going to get ad.",
                                   NSStringFromGADAdSize(adSize)];
    NSDictionary *errorInfo = [NSDictionary
        dictionaryWithObjectsAndKeys:errorDesc, NSLocalizedDescriptionKey, nil];
    NSError *error = [NSError errorWithDomain:GADErrorDomain
                                         code:GADErrorMediationInvalidAdSize
                                     userInfo:errorInfo];
    [self.connector adapter:self didFailAd:error];
    return;
  }
  self.bannerAd = [[SampleBanner alloc]
      initWithFrame:CGRectMake(0, 0, adSize.size.width, adSize.size.height)];

  self.bannerAd.delegate = self;
  self.bannerAd.adUnit = [[self.connector credentials] objectForKey:@"ad_unit"];

  // Setup request parameters.
  SampleAdRequest *request = [[SampleAdRequest alloc] init];
  request.testMode = self.connector.testMode;
  request.keywords = self.connector.userKeywords;
  [self.bannerAd fetchAd:request];
  NSLog(@"Requesting banner from Sample Ad Network");
}

Additional targeting parameters

The connector contains some common targeting information that you can reference for ad targeting:

  • userKeywords
  • testMode
  • childDirectedTreatment

Mediation extras

Mediation extras allow your ad network to support extra targeting parameters or inputs that are not covered by the additional request parameters provided by the connector. This functionality can be provided through a class that implements the GADAdNetworkExtras protocol. The SampleAdNetworkExtras class is shown below as an example:

@interface SampleAdNetworkExtras : NSObject <GADAdNetworkExtras>
/// Should ad volume audio be muted.
@property(nonatomic, assign) BOOL muteAudio;

@end

Publishers must pass an instance of your GADAdNetworkExtras subclass when making an ad request. This instance of your GADAdNetworkExtras subclass can be accessed through the connector. Here is how you can use mediation extras when building an ad request for your network:

SampleAdRequest *request = [[SampleAdRequest alloc] init];
SampleAdNetworkExtras *myAdNetworkExtras = [self.connector networkExtras];
request.muteAudio = myAdNetworkExtras.muteAudio;
[self.bannerAd fetchAd:request];

To ensure your GADAdNetworkExtras subclass can be accessed through the connector, implement networkExtrasClass and return your GADAdNetworkExtras subclass:

+ (Class<GADAdNetworkExtras>)networkExtrasClass {
  return [SampleAdNetworkExtras class];
}

If your adapter doesn't use mediation extras, the networkExtrasClass method returns Nil.

Notify mediation

Have your adapter implement the ad listener for your network and forward the relevant ad event callbacks through the connector. The table below explains when to call each delegate method:

Method When to call
adapter:didReceiveAdView: The banner request succeeded.
adapter:didFailAd: The banner request failed.
adapterDidGetAdClick: The banner was clicked.
adapterWillPresentFullScreenModal: The banner will present an in-app overlay.
adapterWillDismissFullScreenModal: The in-app overlay will close.
adapterDidDismissFullScreenModal: The in-app overlay has been closed.
adapterWillLeaveApplication: The application will be placed in the background or terminate because the user clicked on an ad that will launch another application.

The following example implements the SampleBannerAdDelegate interface from the Sample Ad Network to forward error and status messages:

- (void)bannerDidLoad:(SampleBanner *)banner {
  [self.connector adapter:self didReceiveAdView:banner];
}

- (void)banner:(SampleBanner *)banner didFailWithError:(SampleErrorCode)error {
  [self.connector adapter:self
                didFailAd:[NSError errorWithDomain:@"Ad request failed"
                                              code:error
                                          userInfo:nil]];
}

- (void)bannerWillLeaveApplication:(SampleBanner *)banner {
  [self.connector adapterDidGetAdClick:self];
  [self.connector adapterWillLeaveApplication:self];
}

Launch in-app overlay versus external application

When a banner is clicked, the ad may open a full-screen overlay or an external application (such as Safari or the app store). The connector callbacks to invoke in these two cases are different.

If a banner click opens a full-screen overlay, call adapterWillPresentFullScreenModal: when presenting the overlay. When the overlay is closed, call both adapterWillDismissFullScreenModal: and adapterDidDismissFullScreenModal:.

If a banner click (or a full-screen overlay click) causes the user to leave the application, invoke the adapterWillLeaveApplication: callback.

You now have a working mediation adapter for banners. For reference, a complete implementation of the SampleAdapter can be found on GitHub.

Implement an interstitial adapter

The adapter implementation for interstitial ads is similar to banner ads. The getInterstitial method is called immediately after the adapter is instantiated. This method doesn't return anything. The adapter is expected to start an asynchronous ad fetch over the network. Make your adapter act as a delegate to your SDK for listening to callbacks. If your SDK does not support interstitial ads, invoke the adapter:didFailAd: method of the connector as follows:

- (void)getInterstitial {
  self.interstitialAd = [[SampleInterstitial alloc] init];
  self.interstitialAd.delegate = self;
  self.interstitialAd.adUnit =
      [[self.connector credentials] objectForKey:@"ad_unit"];

  SampleAdRequest *request = [[SampleAdRequest alloc] init];
  // Setup request parameters.
  request.testMode = self.connector.testMode;
  request.keywords = self.connector.userKeywords;

  [self.interstitialAd fetchAd:request];
  NSLog(@"Requesting interstitial from Sample Ad Network");
}

Just as with MediationBannerAdapter, you can receive publisher identification and ad targeting information from the connector.

Notify mediation

Have your adapter implement the ad delegate for your network and forward the relevant ad event callbacks through the connector. The table below explains when to call each delegate method:

Method When to call
adapterDidReceiveInterstitial: The interstitial request succeeded.
adapter:didFailInterstitial: The interstitial request failed.
adapterDidGetAdClick: The interstitial was clicked.
adapterWillPresentInterstitial: The interstitial will be shown.
adapterWillDismissInterstitial: The interstitial is going to be dismissed.
adapterDidDismissInterstitial: The interstitial has been dismissed.
adapterWillLeaveApplication: The application will background or terminate because the user clicked on an ad that will launch another application.

The following example implements the SampleInterstitialAdDelegate interface of the Sample Ad Network to forward error and status messages:

- (void)interstitialDidLoad:(SampleInterstitial *)interstitial {
  [self.connector adapterDidReceiveInterstitial:self];
}

- (void)interstitial:(SampleInterstitial *)interstitial
    didFailWithError:(SampleErrorCode)error {
  [self.connector adapter:self
      didFailInterstitial:[NSError errorWithDomain:@"Ad request failed"
                                              code:error
                                          userInfo:nil]];
}

- (void)interstitialWillPresentScreen:(SampleInterstitial *)interstitial {
  [self.connector adapterWillPresentInterstitial:self];
}

- (void)interstitialWillDismissScreen:(SampleInterstitial *)interstitial {
  [self.connector adapterWillDismissInterstitial:self];
}

- (void)interstitialDidDismissScreen:(SampleInterstitial *)interstitial {
  [self.connector adapterDidDismissInterstitial:self];
}

Present an interstitial

Once the adapter calls adapterDidReceiveInterstitial, make it wait to show the interstitial until presentInterstitialFromRootViewController is called. The app developer decides when to show the interstitial, which could be several minutes after it was received.

Here is an implementation of presentInterstitialFromRootViewController: for the Sample Ad Network:

- (void)presentInterstitialFromRootViewController:
    (UIViewController *)rootViewController {
  if ([self.interstitialAd isLoaded]) {
    [self.interstitialAd show];
  }
}

Your mediation adapter is ready to handle interstitial ads. For reference, a complete implementation of the SampleAdapter can be found on GitHub.

FAQ

Should I include the adapter as part of my SDK library or as a separate library?
We recommend including the adapter as part of your SDK library so that developers have to reference only one library to incorporate your network.
What do I do if my adapter only supports banner ads?

If your adapter only supports banners, have it forward an error event to mediation for interstitial requests:

- (void)getInterstitial {
  NSDictionary *errorInfo = @{ NSLocalizedDescriptionKey : @"Some error" };
  NSError *error = [NSError errorWithDomain:GADErrorDomain
                                       code:GADErrorInvalidRequest
                                   userInfo:errorInfo];
  [self.connector adapter:self didFailInterstitial:error];
  return;
}
What do I do if my adapter only supports interstitial ads?

If your adapter only supports interstitials, have it forward an error event to mediation for banner requests:

- (void)getBannerWithSize:(GADAdSize)adSize {
  NSDictionary *errorInfo = @{ NSLocalizedDescriptionKey : @"Some error" };
  NSError *error =
      [NSError errorWithDomain:GADErrorDomain
                          code:GADErrorInvalidRequest
                      userInfo:errorInfo];
  [self.connector adapter:self didFailAd:error];
  return;
}