Native ads custom events
Stay organized with collections
Save and categorize content based on your preferences.
AI-generated Key Takeaways
-
Native ad custom events require implementing
GADMediationAdapter
andloadNativeAd:adConfiguration:completionHandler:
, and a separate class forGADMediationNativeAd
. -
The
SampleCustomEventNative
class is responsible for loading the native ad, implementingGADMediationNativeAd
, 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.
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.