To discuss and provide feedback on our products, join the official AdMob Discord channel in the Google Advertising and Measurement Community server.

Native ads custom events

  • Native ad custom events require implementing GADMediationAdapter and loadNativeAd:adConfiguration:completionHandler:, and a separate class for GADMediationNativeAd.

  • The SampleCustomEventNative class is responsible for loading the native ad, implementing GADMediationNativeAd, and reporting ad event callbacks to Google Mobile Ads SDK.

  • Native ads from different SDKs are "mapped" to match the Google Mobile Ads SDK interface using a class implementing GADMediationNativeAd.

  • Custom events handle impression and click tracking either by having Google Mobile Ads SDK track them or by tracking them directly with the mediated SDK and notifying Google Mobile Ads SDK.

  • Adapters use the GADMediationNativeAdEventDelegate object to forward presentation events from the third-party SDK to Google Mobile Ads SDK.

Select platform: Android iOS

Prerequisites

Complete the custom events setup.

Request a native ad

When the custom event line item is reached in the waterfall mediation chain, the loadNativeAd:adConfiguration:completionHandler: method is called on the class name you provided when creating a custom event. In this case, that method is in SampleCustomEvent, which then calls the loadNativeAd:adConfiguration:completionHandler: method in SampleCustomEventNative.

To request a native ad, create or modify a class that implements GADMediationAdapter and loadNativeAd:adConfiguration:completionHandler:. If a class that extends GADMediationAdapter already exists, implement loadNativeAd:adConfiguration:completionHandler: there. Additionally, create a new class to implement GADMediationNativeAd.

In our custom event example, SampleCustomEvent implements the GADMediationAdapter interface and then delegates to SampleCustomEventNative.

Swift

importGoogleMobileAds
classSampleCustomEvent:NSObject,MediationAdapter{
fileprivatevarnativeAd:SampleCustomEventNativeAd?
funcloadNativeAd(
foradConfiguration:MediationNativeAdConfiguration,
completionHandler:@escapingGADMediationNativeAdLoadCompletionHandler
){
self.nativeAd=SampleCustomEventNativeAd()
self.nativeAd?.loadNativeAd(
for:adConfiguration,completionHandler:completionHandler)
}
}

Objective-C

#import "SampleCustomEvent.h"
@implementation SampleCustomEvent
SampleCustomEventNativeAd*sampleNativeAd;
- (void)loadNativeAdForAdConfiguration:
(GADMediationNativeAdConfiguration*)adConfiguration
completionHandler:
(GADMediationNativeAdLoadCompletionHandler)
 completionHandler{
sampleNative=[[SampleCustomEventNativeAdalloc]init];
[sampleNativeloadNativeAdForAdConfiguration:adConfiguration
completionHandler:completionHandler];
}

SampleCustomEventNative` is responsible for the following tasks:

  • Loading the native ad

  • Implementing the GADMediationNativeAd protocol.

  • Receiving and reporting ad event callbacks to Google Mobile Ads SDK.

The optional parameter defined in the AdMob UI is included in the ad configuration. The parameter can be accessed through adConfiguration.credentials.settings[@"parameter"]. This parameter is typically an ad unit identifier that an ad network SDK requires when instantiating an ad object.

Swift

classSampleCustomEventNativeAd:NSObject,MediationNativeAd{
/// The Sample Ad Network native ad.
varnativeAd:SampleNativeAd?
/// The ad event delegate to forward ad rendering events to the Google Mobile
/// Ads SDK.
vardelegate:MediationNativeAdEventDelegate?
/// Completion handler called after ad load
varcompletionHandler:GADMediationNativeLoadCompletionHandler?
funcloadNativeAd(
foradConfiguration:MediationNativeAdConfiguration,
completionHandler:@escapingGADMediationNativeLoadCompletionHandler
){
letadLoader=SampleNativeAdLoader()
letsampleRequest=SampleNativeAdRequest()
// Google Mobile Ads SDK requires the image assets to be downloaded
// automatically unless the publisher specifies otherwise by using the
// GADNativeAdImageAdLoaderOptions object's disableImageLoading property. If
// your network doesn't have an option like this and instead only ever
// returns URLs for images (rather than the images themselves), your adapter
// should download image assets on behalf of the publisher. This should be
// done after receiving the native ad object from your network's SDK, and
// before calling the connector's adapter:didReceiveMediatedNativeAd: method.
sampleRequest.shouldDownloadImages=true
sampleRequest.preferredImageOrientation=NativeAdImageOrientation.any
sampleRequest.shouldRequestMultipleImages=false
letoptions=adConfiguration.options
forloaderOptions:AdLoaderOptionsinoptions{
ifletimageOptions=loaderOptionsas?NativeAdImageAdLoaderOptions{
sampleRequest.shouldRequestMultipleImages=
imageOptions.shouldRequestMultipleImages
// If the GADNativeAdImageAdLoaderOptions' disableImageLoading property is
// YES, the adapter should send just the URLs for the images.
sampleRequest.shouldDownloadImages=!imageOptions.disableImageLoading
}elseifletmediaOptions=loaderOptions
as?NativeAdMediaAdLoaderOptions
{
switchmediaOptions.mediaAspectRatio{
caseMediaAspectRatio.landscape:
sampleRequest.preferredImageOrientation=
NativeAdImageOrientation.landscape
caseMediaAspectRatio.portrait:
sampleRequest.preferredImageOrientation=
NativeAdImageOrientation.portrait
default:
sampleRequest.preferredImageOrientation=NativeAdImageOrientation.any
}
}
}
// This custom event uses the server parameter to carry an ad unit ID, which
// is the most common use case.
adLoader.delegate=self
adLoader.adUnitID=
adConfiguration.credentials.settings["parameter"]as?String
self.completionHandler=completionHandler
adLoader.fetchAd(sampleRequest)
}
}

Objective-C

#import "SampleCustomEventNativeAd.h"
@interface SampleCustomEventNativeAd()<SampleNativeAdDelegate,
GADMediationNativeAd>{
/// The sample native ad.
SampleNativeAd*_nativeAd;
/// The completion handler to call when the ad loading succeeds or fails.
GADMediationNativeLoadCompletionHandler_loadCompletionHandler;
/// The ad event delegate to forward ad rendering events to the Google Mobile
/// Ads SDK.
id<GADMediationNativeAdEventDelegate>_adEventDelegate;
}
@end
-(void)loadNativeAdForAdConfiguration:
(GADMediationNativeAdConfiguration*)adConfiguration
completionHandler:(GADMediationNativeLoadCompletionHandler)
completionHandler{
__blockatomic_flagcompletionHandlerCalled=ATOMIC_FLAG_INIT;
__blockGADMediationNativeLoadCompletionHandleroriginalCompletionHandler=
[completionHandlercopy];
_loadCompletionHandler=^id<GADMediationNativeAdEventDelegate>(
_Nullableid<GADMediationNativeAd>ad,NSError*_Nullableerror){
// Only allow completion handler to be called once.
if(atomic_flag_test_and_set(&completionHandlerCalled)){
returnnil;
}
id<GADMediationNativeAdEventDelegate>delegate=nil;
if(originalCompletionHandler){
// Call original handler and hold on to its return value.
delegate=originalCompletionHandler(ad,error);
}
// Release reference to handler. Objects retained by the handler will also
// be released.
originalCompletionHandler=nil;
returndelegate;
};
SampleNativeAdLoader*adLoader=[[SampleNativeAdLoaderalloc]init];
SampleNativeAdRequest*sampleRequest=[[SampleNativeAdRequestalloc]init];
// Google Mobile Ads SDK requires the image assets to be downloaded
// automatically unless the publisher specifies otherwise by using the
// GADNativeAdImageAdLoaderOptions object's disableImageLoading property. If
// your network doesn't have an option like this and instead only ever returns
// URLs for images (rather than the images themselves), your adapter should
// download image assets on behalf of the publisher. This should be done after
// receiving the native ad object from your network's SDK, and before calling
// the connector's adapter:didReceiveMediatedNativeAd: method.
sampleRequest.shouldDownloadImages=YES;
sampleRequest.preferredImageOrientation=NativeAdImageOrientationAny;
sampleRequest.shouldRequestMultipleImages=NO;
sampleRequest.testMode=adConfiguration.isTestRequest;
for(GADAdLoaderOptions*loaderOptionsinadConfiguration.options){
if([loaderOptionsisKindOfClass:[GADNativeAdImageAdLoaderOptionsclass]]){
GADNativeAdImageAdLoaderOptions*imageOptions=
(GADNativeAdImageAdLoaderOptions*)loaderOptions;
sampleRequest.shouldRequestMultipleImages=
imageOptions.shouldRequestMultipleImages;
// If the GADNativeAdImageAdLoaderOptions' disableImageLoading property is
// YES, the adapter should send just the URLs for the images.
sampleRequest.shouldDownloadImages=!imageOptions.disableImageLoading;
}elseif([loaderOptions
isKindOfClass:[GADNativeAdMediaAdLoaderOptionsclass]]){
GADNativeAdMediaAdLoaderOptions*mediaOptions=
(GADNativeAdMediaAdLoaderOptions*)loaderOptions;
switch(mediaOptions.mediaAspectRatio){
caseGADMediaAspectRatioLandscape:
sampleRequest.preferredImageOrientation=
NativeAdImageOrientationLandscape;
break;
caseGADMediaAspectRatioPortrait:
sampleRequest.preferredImageOrientation=
NativeAdImageOrientationPortrait;
break;
default:
sampleRequest.preferredImageOrientation=NativeAdImageOrientationAny;
break;
}
}elseif([loaderOptionsisKindOfClass:[GADNativeAdViewAdOptionsclass]]){
_nativeAdViewAdOptions=(GADNativeAdViewAdOptions*)loaderOptions;
}
}
// This custom event uses the server parameter to carry an ad unit ID, which
// is the most common use case.
NSString*adUnit=adConfiguration.credentials.settings[@"parameter"];
adLoader.adUnitID=adUnit;
adLoader.delegate=self;
[adLoaderfetchAd:sampleRequest];
}

Whether the ad is successfully fetched or encounters an error, you would call GADMediationNativeAdLoadCompletionHandler. In the event of success, pass through the class that implements GADMediationNativeAd with a nil value for the error parameter; in the event of failure, pass through the error you encountered.

Typically, these methods are implemented inside callbacks from the third-party SDK your adapter implements. For this example, the Sample SDK has a SampleNativeAdDelegate with relevant callbacks:

Swift

funcadLoader(
_adLoader:SampleNativeAdLoader,didReceivenativeAd:SampleNativeAd
){
extraAssets=[
SampleCustomEventConstantsSwift.awesomenessKey:nativeAd.degreeOfAwesomeness
??""
]
ifletimage=nativeAd.image{
images=[NativeAdImage(image:image)]
}else{
letimageUrl=URL(fileURLWithPath:nativeAd.imageURL)
images=[NativeAdImage(url:imageUrl,scale:nativeAd.imageScale)]
}
ifletmappedIcon=nativeAd.icon{
icon=NativeAdImage(image:mappedIcon)
}else{
leticonURL=URL(fileURLWithPath:nativeAd.iconURL)
icon=NativeAdImage(url:iconURL,scale:nativeAd.iconScale)
}
adChoicesView=SampleAdInfoView()
self.nativeAd=nativeAd
iflethandler=completionHandler{
delegate=handler(self,nil)
}
}
funcadLoader(
_adLoader:SampleNativeAdLoader,
didFailToLoadAdWitherrorCode:SampleErrorCode
){
leterror=
SampleCustomEventUtilsSwift.SampleCustomEventErrorWithCodeAndDescription(
code:SampleCustomEventErrorCodeSwift
.SampleCustomEventErrorAdLoadFailureCallback,
description:
"Sample SDK returned an ad load failure callback with error code: \(errorCode)"
)
iflethandler=completionHandler{
delegate=handler(nil,error)
}
}

Objective-C

- (void)adLoader:(SampleNativeAdLoader*)adLoader
didReceiveNativeAd:(SampleNativeAd*)nativeAd{
if(nativeAd.image){
_images=@[[[GADNativeAdImagealloc]initWithImage:nativeAd.image]];
}else{
NSURL*imageURL=[[NSURLalloc]initFileURLWithPath:nativeAd.imageURL];
_images=@[[[GADNativeAdImagealloc]initWithURL:imageURL
scale:nativeAd.imageScale]];
}
if(nativeAd.icon){
_icon=[[GADNativeAdImagealloc]initWithImage:nativeAd.icon];
}else{
NSURL*iconURL=[[NSURLalloc]initFileURLWithPath:nativeAd.iconURL];
_icon=[[GADNativeAdImagealloc]initWithURL:iconURL
scale:nativeAd.iconScale];
}
// The sample SDK provides an AdChoices view (SampleAdInfoView). If your SDK
// provides image and click through URLs for its AdChoices icon instead of an
// actual UIView, the adapter is responsible for downloading the icon image
// and creating the AdChoices icon view.
_adChoicesView=[[SampleAdInfoViewalloc]init];
_nativeAd=nativeAd;
_adEventDelegate=_loadCompletionHandler(self,nil);
}
- (void)adLoader:(SampleNativeAdLoader*)adLoader
didFailToLoadAdWithErrorCode:(SampleErrorCode)errorCode{
NSError*error=SampleCustomEventErrorWithCodeAndDescription(
SampleCustomEventErrorAdLoadFailureCallback,
[NSStringstringWithFormat:@"Sample SDK returned an ad load failure "
@"callback with error code: %@",
errorCode]);
_adEventDelegate=_loadCompletionHandler(nil,error);
}

Map native ads

Different SDKs have their own unique formats for native ads. One might return objects that contain a "title" field, for instance, while another might have "headline". Additionally, the methods used to track impressions and process clicks can vary from one SDK to another.

To address these issues, when a custom event receives a native ad object from its mediated SDK, it should use a class that implements GADMediationNativeAd, like SampleCustomEventNativeAd, to "map" the mediated SDK's native ad object so it matches the interface expected by Google Mobile Ads SDK.

We now take a closer look at the implementation details for SampleCustomEventNativeAd.

Store your mappings

GADMediationNativeAd is expected to implement certain properties that are mapped to from other SDK’s properties:

Swift

varnativeAd:SampleNativeAd?
varheadline:String?{
returnnativeAd?.headline
}
varimages:[NativeAdImage]?
varbody:String?{
returnnativeAd?.body
}
varicon:NativeAdImage?
varcallToAction:String?{
returnnativeAd?.callToAction
}
varstarRating:NSDecimalNumber?{
returnnativeAd?.starRating
}
varstore:String?{
returnnativeAd?.store
}
varprice:String?{
returnnativeAd?.price
}
varadvertiser:String?{
returnnativeAd?.advertiser
}
varextraAssets:[String:Any]?{
return[
SampleCustomEventConstantsSwift.awesomenessKey:
nativeAd?.degreeOfAwesomeness
??""
]
}
varadChoicesView:UIView?
varmediaView:UIView?{
returnnativeAd?.mediaView
}

Objective-C

/// Used to store the ad's images. In order to implement the
/// GADMediationNativeAd protocol, we use this class to return the images
/// property.
NSArray<GADNativeAdImage*>*_images;
/// Used to store the ad's icon. In order to implement the GADMediationNativeAd
/// protocol, we use this class to return the icon property.
GADNativeAdImage*_icon;
/// Used to store the ad's ad choices view. In order to implement the
/// GADMediationNativeAd protocol, we use this class to return the adChoicesView
/// property.
UIView*_adChoicesView;
- (nullableNSString*)headline{
return_nativeAd.headline;
}
- (nullableNSArray<GADNativeAdImage*>*)images{
return_images;
}
- (nullableNSString*)body{
return_nativeAd.body;
}
- (nullableGADNativeAdImage*)icon{
return_icon;
}
- (nullableNSString*)callToAction{
return_nativeAd.callToAction;
}
- (nullableNSDecimalNumber*)starRating{
return_nativeAd.starRating;
}
- (nullableNSString*)store{
return_nativeAd.store;
}
- (nullableNSString*)price{
return_nativeAd.price;
}
- (nullableNSString*)advertiser{
return_nativeAd.advertiser;
}
- (nullableNSDictionary<NSString*,id>*)extraAssets{
return
@{SampleCustomEventExtraKeyAwesomeness:_nativeAd.degreeOfAwesomeness};
}
- (nullableUIView*)adChoicesView{
return_adChoicesView;
}
- (nullableUIView*)mediaView{
return_nativeAd.mediaView;
}
- (BOOL)hasVideoContent{
returnself.mediaView!=nil;
}

Some mediated networks can provide additional assets beyond those defined by Google Mobile Ads SDK. The GADMediationNativeAd protocol includes a method called extraAssets that Google Mobile Ads SDK uses to retrieve any of these "extra" assets from your mapper.

Map image assets

Mapping image assets is more complicated than mapping simpler data types like NSString or double. Images might be downloaded automatically or returned as URL values. Their pixel density can also vary.

To help you manage these details, Google Mobile Ads SDK provides the GADNativeAdImage class. Image asset information (whether it's actual UIImage objects or just NSURL values) should be returned to Google Mobile Ads SDK using this class.

Here's how the mapper class handles creating a GADNativeAdImage to hold the icon image:

Swift

ifletimage=nativeAd.image{
images=[NativeAdImage(image:image)]
}else{
letimageUrl=URL(fileURLWithPath:nativeAd.imageURL)
images=[NativeAdImage(url:imageUrl,scale:nativeAd.imageScale)]
}

Objective-C

if(nativeAd.image){
_images=@[[[GADNativeAdImagealloc]initWithImage:nativeAd.image]];
}else{
NSURL*imageURL=[[NSURLalloc]initFileURLWithPath:nativeAd.imageURL];
_images=@[[[GADNativeAdImagealloc]initWithURL:imageURL
scale:nativeAd.imageScale]];
}

Impression and click events

Both Google Mobile Ads SDK and the mediated SDK need to know when an impression or click occurs, but only one SDK needs to track these events. There are two different approaches custom events can use, depending on whether the mediated SDK supports tracking impressions and clicks on its own.

Track clicks and impressions with Google Mobile Ads SDK

If the mediated SDK doesn't perform its own impression and click tracking but provides methods to record clicks and impressions, Google Mobile Ads SDK can track these events and notify the adapter. The GADMediationNativeAd protocol includes two methods: didRecordImpression: and didRecordClickOnAssetWithName:view:viewController: that custom events can implement to call the corresponding method on the mediated native ad object:

Swift

funcdidRecordImpression(){
nativeAd?.recordImpression()
}
funcdidRecordClickOnAsset(
withNameassetName:GADUnifiedNativeAssetIdentifier,
view:UIView,
wController:UIViewController
){
nativeAd?.handleClick(on:view)
}

Objective-C

- (void)didRecordImpression{
if(self.nativeAd){
[self.nativeAdrecordImpression];
}
}
- (void)didRecordClickOnAssetWithName:(GADUnifiedNativeAssetIdentifier)assetName
view:(UIView*)view
viewController:(UIViewController*)viewController{
if(self.nativeAd){
[self.nativeAdhandleClickOnView:view];
}
}

Because the class that implements the GADMediationNativeAd protocol holds a reference to the Sample SDK's native ad object, it can call the appropriate method on that object to report a click or impression. Note that the didRecordClickOnAssetWithName:view:viewController: method takes a single parameter: the View object corresponding to the native ad asset that received the click.

Track clicks and impressions with the mediated SDK

Some mediated SDKs might prefer to track clicks and impressions on their own. In that case, you should implement the handlesUserClicks and handlesUserImpressions methods as shown in the snippet below. By returning YES, you indicate that the custom event takes responsibility for tracking these events and will notify Google Mobile Ads SDK when these events occur.

Custom events that override click and impression tracking can use the didRenderInView: message to pass the native ad's view to the mediated SDK's native ad object to allow the mediated SDK to do the actual tracking. The sample SDK from our custom event example project (from which this guide's code snippets have been taken) doesn't use this approach' but if it did, the custom event code would call the setNativeAdView:view: method as shown in the snippet below:

Swift

funchandlesUserClicks()->Bool{
returntrue
}
funchandlesUserImpressions()->Bool{
returntrue
}
funcdidRender(
inview:UIView,clickableAssetViews:[GADNativeAssetIdentifier:UIView],
nonclickableAssetViews:[GADNativeAssetIdentifier:UIView],
viewController:UIViewController
){
// This method is called when the native ad view is rendered. Here you would pass the UIView
// back to the mediated network's SDK.
self.nativeAd?.setNativeAdView(view)
}

Objective-C

- (BOOL)handlesUserClicks{
returnYES;
}
- (BOOL)handlesUserImpressions{
returnYES;
}
- (void)didRenderInView:(UIView*)view
clickableAssetViews:(NSDictionary<GADNativeAssetIdentifier,UIView*>*)
 clickableAssetViews
nonclickableAssetViews:(NSDictionary<GADNativeAssetIdentifier,UIView*>*)
 nonclickableAssetViews
viewController:(UIViewController*)viewController{
// This method is called when the native ad view is rendered. Here you would
// pass the UIView back to the mediated network's SDK. Playing video using
// SampleNativeAd's playVideo method
[_nativeAdsetNativeAdView:view];
}

Forward mediation events to Google Mobile Ads SDK

Once you've called GADMediationNativeLoadCompletionHandler with a loaded ad, the returned GADMediationNativeAdEventDelegate delegate object can then be used by the adapter to forward presentation events from the third-party SDK to Google Mobile Ads SDK.

It's important that your custom event forwards as many of these callbacks as possible, so that your app receives these equivalent events from Google Mobile Ads SDK. Here's an example of using callbacks:

This completes the custom events implementation for native ads. The full example is available on GitHub.

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025年10月17日 UTC.