必要條件
完成自訂事件設定。
請求原生廣告
當刊登序列中介服務鏈執行到自訂事件委刊項,系統會以您在建立自訂事件時指定的類別名稱,呼叫 loadNativeAd:adConfiguration:completionHandler:
方法。在本例中,該方法位於 SampleCustomEvent
,會接著呼叫 SampleCustomEventNative
中的 loadNativeAd:adConfiguration:completionHandler:
方法。
如要請求原生廣告,請建立或修改導入 GADMediationAdapter
和 loadNativeAd:adConfiguration:completionHandler:
的類別。如果已有擴充 GADMediationAdapter
的類別,請在該處實作 loadNativeAd:adConfiguration:completionHandler:
。此外,請建立新類別來導入 GADMediationNativeAd
。
在我們的自訂事件範例中,SampleCustomEvent
會實作 GADMediationAdapter
介面,然後委派給 SampleCustomEventNative
。
Swift
import GoogleMobileAds class SampleCustomEvent: NSObject, MediationAdapter { fileprivate var nativeAd: SampleCustomEventNativeAd? func loadNativeAd( for adConfiguration: MediationNativeAdConfiguration, completionHandler: @escaping GADMediationNativeAdLoadCompletionHandler ) { 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 = [[SampleCustomEventNativeAd alloc] init]; [sampleNative loadNativeAdForAdConfiguration:adConfiguration completionHandler:completionHandler]; }
`SampleCustomEventNative` 負責下列工作:
載入原生廣告
導入
GADMediationNativeAd
通訊協定。接收廣告事件回呼,並回報給 Google Mobile Ads SDK。
在 Ad Manager UI 中定義的選用參數會包含在廣告設定。
使用 adConfiguration.credentials.settings[@"parameter"]
即可存取。這項參數通常是廣告單元 ID,廣告聯播網 SDK 在例項化廣告物件時會用到。
Swift
class SampleCustomEventNativeAd: NSObject, MediationNativeAd { /// The Sample Ad Network native ad. var nativeAd: SampleNativeAd? /// The ad event delegate to forward ad rendering events to the Google Mobile /// Ads SDK. var delegate: MediationNativeAdEventDelegate? /// Completion handler called after ad load var completionHandler: GADMediationNativeLoadCompletionHandler? func loadNativeAd( for adConfiguration: MediationNativeAdConfiguration, completionHandler: @escaping GADMediationNativeLoadCompletionHandler ) { let adLoader = SampleNativeAdLoader() let sampleRequest = 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 let options = adConfiguration.options for loaderOptions: AdLoaderOptions in options { if let imageOptions = loaderOptions as? 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 } else if let mediaOptions = loaderOptions as? NativeAdMediaAdLoaderOptions { switch mediaOptions.mediaAspectRatio { case MediaAspectRatio.landscape: sampleRequest.preferredImageOrientation = NativeAdImageOrientation.landscape case MediaAspectRatio.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 { __block atomic_flag completionHandlerCalled = ATOMIC_FLAG_INIT; __block GADMediationNativeLoadCompletionHandler originalCompletionHandler = [completionHandler copy]; _loadCompletionHandler = ^id<GADMediationNativeAdEventDelegate>( _Nullable id<GADMediationNativeAd> ad, NSError *_Nullable error) { // Only allow completion handler to be called once. if (atomic_flag_test_and_set(&completionHandlerCalled)) { return nil; } 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; return delegate; }; SampleNativeAdLoader *adLoader = [[SampleNativeAdLoader alloc] init]; SampleNativeAdRequest *sampleRequest = [[SampleNativeAdRequest alloc] 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 *loaderOptions in adConfiguration.options) { if ([loaderOptions isKindOfClass:[GADNativeAdImageAdLoaderOptions class]]) { 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; } else if ([loaderOptions isKindOfClass:[GADNativeAdMediaAdLoaderOptions class]]) { GADNativeAdMediaAdLoaderOptions *mediaOptions = (GADNativeAdMediaAdLoaderOptions *)loaderOptions; switch (mediaOptions.mediaAspectRatio) { case GADMediaAspectRatioLandscape: sampleRequest.preferredImageOrientation = NativeAdImageOrientationLandscape; break; case GADMediaAspectRatioPortrait: sampleRequest.preferredImageOrientation = NativeAdImageOrientationPortrait; break; default: sampleRequest.preferredImageOrientation = NativeAdImageOrientationAny; break; } } else if ([loaderOptions isKindOfClass:[GADNativeAdViewAdOptions class]]) { _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; [adLoader fetchAd:sampleRequest]; }
無論廣告擷取成功或發生錯誤,您都會呼叫 GADMediationNativeAdLoadCompletionHandler
。如果成功,請透過實作 GADMediationNativeAd
的類別,為錯誤參數傳遞 nil
值;如果失敗,請傳遞您遇到的錯誤。
這些方法通常是在轉接程式導入的第三方 SDK 回呼中執行。以本例來說,範例 SDK 的 SampleNativeAdDelegate
含有相關回呼:
Swift
func adLoader( _ adLoader: SampleNativeAdLoader, didReceive nativeAd: SampleNativeAd ) { extraAssets = [ SampleCustomEventConstantsSwift.awesomenessKey: nativeAd.degreeOfAwesomeness ?? "" ] if let image = nativeAd.image { images = [NativeAdImage(image: image)] } else { let imageUrl = URL(fileURLWithPath: nativeAd.imageURL) images = [NativeAdImage(url: imageUrl, scale: nativeAd.imageScale)] } if let mappedIcon = nativeAd.icon { icon = NativeAdImage(image: mappedIcon) } else { let iconURL = URL(fileURLWithPath: nativeAd.iconURL) icon = NativeAdImage(url: iconURL, scale: nativeAd.iconScale) } adChoicesView = SampleAdInfoView() self.nativeAd = nativeAd if let handler = completionHandler { delegate = handler(self, nil) } } func adLoader( _ adLoader: SampleNativeAdLoader, didFailToLoadAdWith errorCode: SampleErrorCode ) { let error = SampleCustomEventUtilsSwift.SampleCustomEventErrorWithCodeAndDescription( code: SampleCustomEventErrorCodeSwift .SampleCustomEventErrorAdLoadFailureCallback, description: "Sample SDK returned an ad load failure callback with error code: \(errorCode)" ) if let handler = completionHandler { delegate = handler(nil, error) } }
Objective-C
- (void)adLoader:(SampleNativeAdLoader *)adLoader didReceiveNativeAd:(SampleNativeAd *)nativeAd { if (nativeAd.image) { _images = @[ [[GADNativeAdImage alloc] initWithImage:nativeAd.image] ]; } else { NSURL *imageURL = [[NSURL alloc] initFileURLWithPath:nativeAd.imageURL]; _images = @[ [[GADNativeAdImage alloc] initWithURL:imageURL scale:nativeAd.imageScale] ]; } if (nativeAd.icon) { _icon = [[GADNativeAdImage alloc] initWithImage:nativeAd.icon]; } else { NSURL *iconURL = [[NSURL alloc] initFileURLWithPath:nativeAd.iconURL]; _icon = [[GADNativeAdImage alloc] 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 = [[SampleAdInfoView alloc] init]; _nativeAd = nativeAd; _adEventDelegate = _loadCompletionHandler(self, nil); } - (void)adLoader:(SampleNativeAdLoader *)adLoader didFailToLoadAdWithErrorCode:(SampleErrorCode)errorCode { NSError *error = SampleCustomEventErrorWithCodeAndDescription( SampleCustomEventErrorAdLoadFailureCallback, [NSString stringWithFormat:@"Sample SDK returned an ad load failure " @"callback with error code: %@", errorCode]); _adEventDelegate = _loadCompletionHandler(nil, error); }
地圖原生廣告
不同 SDK 的原生廣告格式各不相同。舉例來說,有的可能會傳回含有「title」欄位的物件,有的則可能含有「headline」欄位。此外,追蹤曝光和處理點擊的方法也因 SDK 而異。
為解決這些問題,自訂事件從中介服務 SDK 收到原生廣告物件時,應使用實作 GADMediationNativeAd
的類別 (例如 SampleCustomEventNativeAd
)「對應」中介服務 SDK 的原生廣告物件,確保符合 Google Mobile Ads SDK 預期的介面。
我們現在要深入瞭解 SampleCustomEventNativeAd
的實作詳細資料。
儲存對應
GADMediationNativeAd
應實作某些屬性,這些屬性會對應至其他 SDK 的屬性:
Swift
var nativeAd: SampleNativeAd? var headline: String? { return nativeAd?.headline } var images: [NativeAdImage]? var body: String? { return nativeAd?.body } var icon: NativeAdImage? var callToAction: String? { return nativeAd?.callToAction } var starRating: NSDecimalNumber? { return nativeAd?.starRating } var store: String? { return nativeAd?.store } var price: String? { return nativeAd?.price } var advertiser: String? { return nativeAd?.advertiser } var extraAssets: [String: Any]? { return [ SampleCustomEventConstantsSwift.awesomenessKey: nativeAd?.degreeOfAwesomeness ?? "" ] } var adChoicesView: UIView? var mediaView: UIView? { return nativeAd?.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; - (nullable NSString *)headline { return _nativeAd.headline; } - (nullable NSArray<GADNativeAdImage *> *)images { return _images; } - (nullable NSString *)body { return _nativeAd.body; } - (nullable GADNativeAdImage *)icon { return _icon; } - (nullable NSString *)callToAction { return _nativeAd.callToAction; } - (nullable NSDecimalNumber *)starRating { return _nativeAd.starRating; } - (nullable NSString *)store { return _nativeAd.store; } - (nullable NSString *)price { return _nativeAd.price; } - (nullable NSString *)advertiser { return _nativeAd.advertiser; } - (nullable NSDictionary<NSString *, id> *)extraAssets { return @{SampleCustomEventExtraKeyAwesomeness : _nativeAd.degreeOfAwesomeness}; } - (nullable UIView *)adChoicesView { return _adChoicesView; } - (nullable UIView *)mediaView { return _nativeAd.mediaView; } - (BOOL)hasVideoContent { return self.mediaView != nil; }
某些中介服務聯播網除了有 Google Mobile Ads SDK 定義的素材資源,還會提供其他素材資源。GADMediationNativeAd
通訊協定包含名為 extraAssets
的方法,Google Mobile Ads SDK 會透過這個方法,從對應器擷取這類「額外」的素材資源。
對應圖片素材資源
相較於對應 NSString
或 double
等較簡單的資料類型,對應圖片素材資源會比較複雜。圖片可能會自動下載,或以網址值形式傳回,像素密度可能也有所差異。
為協助您管理這些詳細資料,Google Mobile Ads SDK 提供 GADNativeAdImage
類別。圖片素材資源資訊 (無論是實際的 UIImage
物件,或只是 NSURL
值) 應透過這個類別,傳回給 Google Mobile Ads SDK。
以下說明對應器類別如何建立 GADNativeAdImage
,保留圖示圖片:
Swift
if let image = nativeAd.image { images = [NativeAdImage(image: image)] } else { let imageUrl = URL(fileURLWithPath: nativeAd.imageURL) images = [NativeAdImage(url: imageUrl, scale: nativeAd.imageScale)] }
Objective-C
if (nativeAd.image) { _images = @[ [[GADNativeAdImage alloc] initWithImage:nativeAd.image] ]; } else { NSURL *imageURL = [[NSURL alloc] initFileURLWithPath:nativeAd.imageURL]; _images = @[ [[GADNativeAdImage alloc] initWithURL:imageURL scale:nativeAd.imageScale] ]; }
曝光和點擊事件
Google Mobile Ads SDK 和中介 SDK 都需要知道何時發生曝光或點擊,但只有一個 SDK 需要追蹤這些事件。自訂事件有兩種方法可使用,具體取決於中介服務 SDK 是否支援自行追蹤曝光和點擊。
使用 Google Mobile Ads SDK 追蹤點擊和曝光
如果中介服務 SDK 不會自行追蹤曝光和點擊,但支援記錄點擊和曝光的方法,Google Mobile Ads SDK 就能追蹤這些事件並通知轉接程式。GADMediationNativeAd
協定包含兩種方法:didRecordImpression:
和 didRecordClickOnAssetWithName:view:viewController:
,自訂事件可實作這些方法,以便呼叫中介服務原生廣告物件的對應方法:
Swift
func didRecordImpression() { nativeAd?.recordImpression() } func didRecordClickOnAsset( withName assetName: GADUnifiedNativeAssetIdentifier, view: UIView, wController: UIViewController ) { nativeAd?.handleClick(on: view) }
Objective-C
- (void)didRecordImpression { if (self.nativeAd) { [self.nativeAd recordImpression]; } } - (void)didRecordClickOnAssetWithName:(GADUnifiedNativeAssetIdentifier)assetName view:(UIView *)view viewController:(UIViewController *)viewController { if (self.nativeAd) { [self.nativeAd handleClickOnView:view]; } }
由於實作 GADMediationNativeAd
通訊協定的類別會保留範例 SDK 原生廣告物件的參照,因此能呼叫該物件的適當方法,回報點擊或曝光事件。請注意,didRecordClickOnAssetWithName:view:viewController:
方法只有一個參數,也就是 View
物件 (與收到點擊的原生廣告素材相對應)。
使用中介服務 SDK 追蹤點擊和曝光
部分中介服務 SDK 可能偏好自行追蹤點擊和曝光次數。在這種情況下,您應實作 handlesUserClicks
和 handlesUserImpressions
方法,如下列程式碼片段所示。傳回 YES
,表示自訂事件會負責追蹤這些事件,並在發生這些事件時通知 Google Mobile Ads SDK。
如果自訂事件會覆寫點擊和曝光追蹤功能,可使用 didRenderInView:
訊息將原生廣告的檢視區塊傳遞給中介 SDK 的原生廣告物件,以利該 SDK 用於實際追蹤。在自訂事件範例專案 (即本指南擷取的程式碼片段) 中,範例 SDK 不是採用這種做法,如果採用的話,自訂事件程式碼會呼叫 setNativeAdView:view:
方法,如下列程式碼片段所示:
Swift
func handlesUserClicks() -> Bool { return true } func handlesUserImpressions() -> Bool { return true } func didRender( in view: 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 { return YES; } - (BOOL)handlesUserImpressions { return YES; } - (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 [_nativeAd setNativeAdView:view]; }
將中介服務事件轉送至 Google Mobile Ads SDK
使用已載入的廣告呼叫 GADMediationNativeLoadCompletionHandler
後,轉接程式可使用傳回的 GADMediationNativeAdEventDelegate
委派代表物件,將呈現事件從第三方 SDK 轉送至 Google Mobile Ads SDK。
自訂事件應盡量將這些回呼轉送至 Google Mobile Ads SDK,這樣應用程式才能收到相應的事件通知。以下是回呼使用範例:
到這裡就完成原生廣告的自訂事件導入設定!如需完整範例,請前往 GitHub。