原生廣告自訂事件

必要條件

完成自訂事件設定

請求原生廣告

在瀑布式中介鏈中到達自訂事件明細時,系統會根據您在建立自訂事件時提供的類別名稱,呼叫 loadNativeAd:adConfiguration:completionHandler: 方法。在本例中 位於 SampleCustomEvent 中該方法,然後 中的 loadNativeAd:adConfiguration:completionHandler: 方法 SampleCustomEventNative

如要要求原生廣告,請建立或修改實作 GADMediationAdapterloadNativeAd:adConfiguration:completionHandler: 的類別。如果 已有擴充 GADMediationAdapter 的類別 有loadNativeAd:adConfiguration:completionHandler:。此外,請建立 用於實作 GADMediationNativeAd 的新類別。

在自訂事件範例中,SampleCustomEvent 會實作 GADMediationAdapter 介面,然後將委派作業交給 SampleCustomEventNative

Swift

import GoogleMobileAds

class SampleCustomEvent: NSObject, GADMediationAdapter {

  fileprivate var nativeAd: SampleCustomEventNativeAd?

  func loadNativeAd(
    for adConfiguration: GADMediationNativeAdConfiguration,
    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 的廣告事件回呼

AdMob UI 中定義的選用參數是 加進廣告設定中 您可以透過 adConfiguration.credentials.settings[@"parameter"] 存取此參數。這個參數通常是廣告聯播網 SDK 在例項化廣告物件時所需的廣告單元 ID。

Swift

class SampleCustomEventNativeAd: NSObject, GADMediationNativeAd {
  /// 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: GADMediationNativeAdEventDelegate?

  /// Completion handler called after ad load
  var completionHandler: GADMediationNativeLoadCompletionHandler?

  func loadNativeAd(
    for adConfiguration: GADMediationNativeAdConfiguration,
    completionHandler: @escaping GADMediationNativeLoadCompletionHandler
  ) {
    let adLoader = SampleNativeAdLoader()
    let sampleRequest = SampleNativeAdRequest()

    // The 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: GADAdLoaderOptions in options {
      if let imageOptions = loaderOptions as? GADNativeAdImageAdLoaderOptions {
        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? GADNativeAdMediaAdLoaderOptions
      {
        switch mediaOptions.mediaAspectRatio {
        case GADMediaAspectRatio.landscape:
          sampleRequest.preferredImageOrientation =
            NativeAdImageOrientation.landscape
        case GADMediaAspectRatio.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];

  // The 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。在這個範例中 具有包含相關回呼的 SampleNativeAdDelegate

Swift

func adLoader(
  _ adLoader: SampleNativeAdLoader, didReceive nativeAd: SampleNativeAd
) {
  extraAssets = [
    SampleCustomEventConstantsSwift.awesomenessKey: nativeAd.degreeOfAwesomeness
      ?? ""
  ]

  if let image = nativeAd.image {
    images = [GADNativeAdImage(image: image)]
  } else {
    let imageUrl = URL(fileURLWithPath: nativeAd.imageURL)
    images = [GADNativeAdImage(url: imageUrl, scale: nativeAd.imageScale)]
  }
  if let mappedIcon = nativeAd.icon {
    icon = GADNativeAdImage(image: mappedIcon)
  } else {
    let iconURL = URL(fileURLWithPath: nativeAd.iconURL)
    icon = GADNativeAdImage(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: [GADNativeAdImage]?

var body: String? {
  return nativeAd?.body
}

var icon: GADNativeAdImage?

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 會使用這項方法,從對應器中擷取任何「額外」資產。

地圖圖片素材資源

比起對應 NSStringdouble 等較簡單的資料類型,對應圖片素材資源的程序更為複雜。Google 可能會自動下載圖片,或 以網址值的形式傳回螢幕的像素密度也可能不同。

為協助您管理這些詳細資料,Google Mobile Ads SDK 提供 GADNativeAdImage 類別。圖片素材資源資訊 (無論是實際的 UIImage 物件或僅為 NSURL 值) 都應使用此類別傳回至 Google Mobile Ads SDK。

以下為對應工具類別處理建立 GADNativeAdImage 來存放 圖示圖片:

Swift

if let image = nativeAd.image {
  images = [GADNativeAdImage(image: image)]
} else {
  let imageUrl = URL(fileURLWithPath: nativeAd.imageURL)
  images = [GADNativeAdImage(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 的類別 通訊協定會保留 Sample SDK 的原生廣告物件參照,然後呼叫 傳回點擊或曝光的適當方法。請注意, didRecordClickOnAssetWithName:view:viewController: 方法採用單一 參數:與收到原生廣告素材資源相對應的 View 物件

使用中介服務 SDK 追蹤點擊和曝光

部分中介 SDK 可能會自行追蹤點擊和曝光。於 此時,您應導入 handlesUserClickshandlesUserImpressions 方法,如以下程式碼片段所示。傳回 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 Play 遊戲收到這些對等事件 Mobile Ads SDK以下是使用回呼的範例:

如此就能完成原生廣告的自訂事件導入。完整範例 會在 GitHub