ネイティブ カスタム イベント

このガイドは、AdMob メディエーションを使って、AdMob のサポート対象広告ネットワーク以外のネットワークからネイティブ広告を読み込んで表示したいと考えているパブリッシャー様を対象としています。AdMob メディエーションを使ってバナー広告、インタースティシャル広告、ディスプレイ リワード広告を読み込んで表示する方法については、カスタム イベントの説明をご覧ください。

カスタム イベントは、別のネットワークに広告をリクエストできるメディエーション アダプタクラスです。これらのクラスのいずれかの名前を広告ユニットのメディエーション設定に追加すると、SDK はそれをインスタンス化して使用し、広告を取得します。ネイティブ カスタム イベント クラスでは、次のタスクを処理する必要があります。

  • メディエーション対象ネットワークにネイティブ広告をリクエストする。
  • メディエーション対象ネットワークの SDK から Google Mobile Ads SDK にイベントを転送する。
  • GADMediatedUnifiedNativeAd を使用して、メディエーション対象のネイティブ広告オブジェクトを AdMob のネイティブ広告インターフェースにマッピングする。

それぞれのタスクについては、以下で説明します。GitHub リポジトリでは、サンプル カスタム イベント プロジェクトのソース全文も確認できます。

前提条件

AdMob のカスタム イベントを実装するには、まずプロジェクトに Mobile Ads SDK を組み込む必要があります。また、広告リクエストの方法とメディエーションの仕組みについてもぜひご確認ください。

サンプル SDK

このガイドで使用されているコードはサンプル カスタム イベント プロジェクトから引用したもので、その中には「サンプル SDK」も含まれています。このプロジェクトでは、別の広告ネットワークの SDK との間を仲介するカスタム イベントの作成方法を説明するために、演習用の「サンプル SDK」を作成しました。

このサンプル SDK には、広告ネットワークの本稼働環境 SDK に備わっているものと同様のクラスがあります。SampleNativeAdRequest などのリクエスト オブジェクト、SampleNativeAdLoader などの広告ローダをはじめ、実際のネットワークの SDK をシミュレーションするために使われるクラスや定数、プロトコルがあります。ただし、この SDK が生成する広告は演習用であり、ネットワーク トラフィックが発生することはありません。

ネイティブ広告をリクエストする

requestNativeAdWithParameter: メソッド

カスタム イベント クラスは GADCustomEventNativeAd プロトコルを実装する必要があります。このプロトコルには、Google Mobile Ads SDK がカスタム イベントにネイティブ広告をリクエストするために使うメソッドが含まれています。

Swift

func request(withParameter serverParameter: String,
                                   request: GADCustomEventRequest,
                                   adTypes: [Any],
                                   options: [Any],
                        rootViewController: UIViewController)

Objective-C

- (void)requestNativeAdWithParameter:(NSString *)serverParameter
                             request:(GADCustomEventRequest *)request
                             adTypes:(NSArray *)adTypes
                             options:(NSArray *)options
                  rootViewController:(UIViewController *)rootViewController;

このメソッドが呼び出されると、カスタム イベントがネイティブ広告を非同期的にリクエストします。requestNativeAdWithParameter: の 4 つのパラメータは、カスタム イベントがリクエストを行う際に使用できる情報を伝えます。

  • serverParameter - 広告ユニットのメディエーション設定にカスタム イベントを追加する際に、個々のリクエストと一緒に渡す文字列の値を入力できますが、このパラメータはその値(通常はメディエーション対象ネットワークが発行した別の広告ユニット ID)を保持します。
  • request - GADCustomEventRequest オブジェクトの一種で、ある 1 つのリクエストに固有のプロパティ(リクエストされたネイティブ フォーマットの種類など)が含まれます。また GADCustomEventRequest には、リクエストの際にパブリッシャーが指定したターゲット情報に関するプロパティも含まれます。
  • adTypes - 定数値を含む NSArray です。この定数値は、リクエストされたネイティブ フォーマットの種類を示します。GADUnifiedNativeAd オブジェクトの場合、この値は kGADAdLoaderAdTypeUnifiedNative になります。
  • options - GADAdLoaderOptions オブジェクトを含む NSArray です。このオブジェクトは、広告の読み込みに関するパブリッシャーの設定を示します。

リクエスト情報を伝えるパラメータのほか、rootViewController パラメータは広告の表示先となる UIViewController への参照を提供します。

次のサンプル カスタム イベント プロジェクトのコード スニペットで、requestNativeAdWithParameter: メソッドの実装例を示します。

SampleCustomEventNativeAd(抜粋)

Swift

func request(withParameter serverParameter: String, request: GADCustomEventRequest, adTypes: [Any], options: [Any], rootViewController: UIViewController) {

  let adLoader = SampleNativeAdLoader()
  let sampleRequest = SampleNativeAdRequest()

  if let options = options as? [GADAdLoaderOptions] {
    for loaderOptions: GADAdLoaderOptions in options {
      if let imageOptions = loaderOptions as? GADNativeAdImageAdLoaderOptions {

        sampleRequest.shouldRequestPortraitImages =
        imageOptions.preferredImageOrientation = .portrait;
        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 options = loaderOptions as? GADNativeAdViewAdOptions {
        nativeAdViewAdOptions = options
      }
    }
  }
  // This custom event uses the server parameter to carry an ad unit ID,
  // which is the most common use case.
  adLoader.adUnitID = serverParameter
  adLoader.delegate = self
  adLoader.fetchAd(sampleRequest)
}

Objective-C

- (void)requestNativeAdWithParameter:(NSString *)serverParameter
                             request:(GADCustomEventRequest *)request
                             adTypes:(NSArray *)adTypes
                             options:(NSArray *)options
                  rootViewController:(UIViewController *)rootViewController {
  SampleNativeAdLoader *adLoader = [[SampleNativeAdLoader alloc] init];
  SampleNativeAdRequest *sampleRequest = [[SampleNativeAdRequest alloc] init];

  for (GADNativeAdImageAdLoaderOptions *imageOptions in options) {
    if (![imageOptions isKindOfClass:[GADNativeAdImageAdLoaderOptions class]]) {
      continue;
    }

    sampleRequest.shouldRequestPortraitImages =
        imageOptions.preferredImageOrientation ==
        GADNativeAdImageAdLoaderOptionsOrientationPortrait;
    sampleRequest.shouldDownloadImages = !imageOptions.disableImageLoading;
    sampleRequest.shouldRequestMultipleImages = imageOptions.shouldRequestMultipleImages;
  }

  // This custom event uses the server parameter to carry an ad unit ID,
  // which is the most common use case.
  adLoader.adUnitID = serverParameter;
  adLoader.delegate = self;

  [adLoader fetchAd:sampleRequest];
}

これは、演習用の「サンプル SDK」経由で架空の広告ネットワークとの間を仲介するサンプル カスタム イベントです。このカスタム イベントは、requestNativeAdWithParameter: パラメータで提供される情報を使って、サンプル SDK の SampleNativeAdLoader に広告をリクエストします。また、このイベントはそれ自身を SampleNativeAdLoader のデリゲートとしても割り当てているため、サンプル SDK から Google Mobile Ads SDK にイベントを送り返すことができます。そのプロセスが次のセクションのトピックです。

GADAdLoaderOptions

ネイティブ広告をリクエストする際は、GADAdLoaderOptions オブジェクトの配列でそのリクエストに関する優先設定(画像アセットの返し方など)を指定します。これらの優先設定は、requestNativeAdWithParameter: メソッドのパラメータの 1 つとしてカスタム イベントに渡されます。そしてカスタム イベントが options 配列を反復処理し、そこに含まれる優先設定に沿って処理が行われます。

たとえば、options 配列に含まれている GADNativeAdImageAdLoaderOptions オブジェクトの shouldDownloadImages の値が true の場合、このカスタム イベントは URL だけでなく実際の画像アセットも返す必要があります。その際、対応している SDK が画像の URL しか提供しない場合には、カスタム イベント側で URL を使用して画像ファイルをダウンロードし、そのデータをパブリッシャーが使えるようにする必要があります。

Mobile Ads SDK にイベントを転送する

カスタム イベントがメディエーション対象ネットワークからネイティブ広告を読み込む際、結果としていくつかのケースが考えられます。SDK がネイティブ広告を正常に返すケース、エラーを返すケース、配信できる広告がないことを伝えるだけのケースです。こうしたイベントを Google Mobile Ads SDK で認識できるように、GADCustomEventNativeAd プロトコルに GADCustomEventNativeAdDelegate の種類のデリゲートを含め、それを使ってカスタム イベントが上記の 3 ケースのイベントを転送できるようにすることが重要です。

カスタム イベントは「仲介者」としての役割も担い、メディエーション対象ネットワークの SDK のイベントをリッスンし、対応する GADCustomEventNativeAdDelegate プロトコル メッセージを適宜デリゲートに送信します。したがって、カスタム イベントでは次のメッセージを認識する必要があります。

  • customEventNativeAd:didReceiveMediatedUnifiedNativeAd: - このメッセージは、カスタム イベントがネイティブ広告を正常に読み込んだときに送られます。カスタム イベントは、このメッセージが受け取る GADMediatedUnifiedNativeAd タイプの単独パラメータを使って、読み込んだネイティブ広告の「適用済み」バージョンを渡します(GADMediatedUnifiedNativeAd クラスについては、次のセクションをご覧ください)。
  • customEventNativeAd:didFailToLoadWithError: - カスタム イベントがネイティブ広告を読み込もうとして失敗した場合は、このメソッドを使って失敗を伝えます。このメソッドは、その失敗に関する情報を含む単独の NSError パラメータを受け取ります。

次に、サンプル カスタム イベント プロジェクトの具体的な働きについて例を示します。

SampleCustomEventNativeAd(抜粋)

Swift

extension SampleCustomEventNativeAdSwift: SampleNativeAdLoaderDelegate {

  func adLoader(_ adLoader: SampleNativeAdLoader, didReceive nativeAd: SampleNativeAd) {
    let mediatedAd = SampleMediatedNativeAdSwift(
    sampleNativeAd:nativeAd,nativeAdViewAdOptions: nativeAdViewAdOptions)
    delegate?.customEventNativeAd(self, didReceive: mediatedAd)
  }

  func adLoader(_ adLoader: SampleNativeAdLoader, didFailToLoadAdWith errorCode: SampleErrorCode) {
    let error = NSError(domain: customEventErrorDomain, code: errorCode.rawValue, userInfo: nil)
    delegate?.customEventNativeAd(self, didFailToLoadWithError: error)
  }

}

Objective-C

@interface SampleCustomEventNativeAd () <SampleNativeAdLoaderDelegate>
@end

@implementation SampleCustomEventNativeAd

@synthesize delegate;

...

#pragma mark SampleNativeAdLoaderDelegate implementation

- (void)adLoader:(SampleNativeAdLoader *)adLoader didReceiveNativeAd:(SampleNativeAd *)nativeAd {
  SampleMediatedNativeAd *mediatedAd =
      [[SampleMediatedNativeAd alloc] initWithSampleNativeAd:nativeAd
                                       nativeAdViewAdOptions:_nativeAdViewAdOptions];
  [self.delegate customEventNativeAd:self didReceiveMediatedUnifiedNativeAd:mediatedAd];
}

- (void)adLoader:(SampleNativeAdLoader *)adLoader
    didFailToLoadAdWithErrorCode:(SampleErrorCode)errorCode {
  NSError *error = [NSError errorWithDomain:customEventErrorDomain code:errorCode userInfo:nil];
  [self.delegate customEventNativeAd:self didFailToLoadWithError:error];
}

...

@end

このクラスは、サンプル SDK の SampleNativeAdLoaderDelegate プロトコルを実装しています。SampleCustomEventNativeAd.m(抜粋)において、カスタム イベント クラスはそれ自体がデリゲートとして SampleNativeAdLoader に割り当てられています。

Swift

adLoader.delegate = self

Objective-C

adLoader.delegate = self;

これにより、成功か失敗を伝えるときにサンプル SDK がカスタム イベントにメッセージを確実に送り返すようにします。カスタム イベントは、この適切なメッセージを自身のデリゲートに送信したうえで、イベントを Google Mobile Ads SDK に転送します。つまり、Google Mobile Ads SDK でリッスンするカスタム イベントで、メディエーション対象ネットワークの SDK をリッスンしています。

上記の adLoader:didFailToLoadAdWithErrorCode メソッドは、この仕組みを示す好例です。サンプル SDK は広告の読み込みに失敗すると、adLoader:didFailToLoadAdWithErrorCode: メッセージをカスタム イベントに送信します。カスタム イベントは、サンプル SDK から送られた SampleErrorCode を使って新しい NSError オブジェクトを作成し、customEventNativeAd:didFailToLoadWithError: メッセージを介して自身のデリゲートにそのオブジェクトを送信します。こうした方法で、サンプル SDK のイベントが Google Mobile Ads SDK のイベントに変換されます。

ネイティブ広告をマッピングする

どの SDK にもネイティブ広告向けの独自のフォーマットがあります。たとえば、ある SDK が返すオブジェクトには「title」フィールドが含まれ、別の SDK が返すものには「headline」フィールドが含まれるなどです。また、インプレッションの測定とクリックの処理に使われるメソッドが SDK によって異なることもあります。こうした SDK による違いを解消するため、カスタム イベントは、メディエーション対象ネットワークの SDK からネイティブ広告オブジェクトを受け取る際に GADMediatedNativeAd のサブクラスを使用して、そのメディエーション対象ネットワーク SDK のネイティブ広告オブジェクトと Google Mobile Ads SDK の仕様が合うようインターフェースを「マッピング」する必要があります。

AdMob のシステム定義の統合型ネイティブ広告フォーマットには、対応する GADMediatedUnifiedNativeAd クラスがあります。カスタム イベントはこのクラスのサブクラスを作成し、メディエーション対象ネットワークの SDK から渡されるネイティブ広告オブジェクトをマッピングします。

次に示すのは、サンプル カスタム イベント プロジェクトのマッパークラスの一例です。

Swift

class SampleMediatedUnifiedNativeAdSwift : NSObject {

    var sampleAd : SampleNativeAd
    var mappedImages = [GADNativeAdImage]()
    var mappedIcon: GADNativeAdImage?
    var extras = [String:Any]()
    var nativeAdViewAdOptions: GADNativeAdViewAdOptions?
    let adInfoView = SampleAdInfoView()
    var sampleMediaView : SampleMediaView?

    init(sampleNativeAd : SampleNativeAd, nativeAdViewAdOptions : GADNativeAdViewAdOptions?) {
      sampleAd = sampleNativeAd
      super.init()
      extras = [SampleCustomEventConstantsSwift.awesomenessKey: sampleAd.degreeOfAwesomeness ?? ""]
      if let image = sampleAd.image {
         mappedImages = [GADNativeAdImage(image : image)]
      }
      else {
         let imageUrl = URL(fileURLWithPath : sampleAd.imageURL)
         mappedImages = [GADNativeAdImage(url : imageUrl, scale : sampleAd.imageScale)]
      }
      if let icon = sampleAd.icon {
        mappedIcon = GADNativeAdImage(image : icon)
      }
      else {
       let iconURL = URL(fileURLWithPath : sampleNativeAd.iconURL)
       mappedIcon = GADNativeAdImage(url : iconURL, scale : sampleAd.iconScale)
      }
      self.nativeAdViewAdOptions = nativeAdViewAdOptions
      self.sampleMediaView = self.sampleAd.mediaView
    }
}

extension SampleMediatedUnifiedNativeAdSwift : GADMediatedUnifiedNativeAd {
    var advertiser : String? {
        return sampleAd.advertiser
    }

    var headline : String? {
      return sampleAd.headline
    }

    var images : [GADNativeAdImage]? {
      return mappedImages
    }

    var body : String? {
      return sampleAd.body
    }

    var icon : GADNativeAdImage? {
      return mappedIcon
    }

    var callToAction : String? {
      return sampleAd.callToAction
    }

    var starRating : NSDecimalNumber? {
      return sampleAd.starRating
    }

    var store : String? {
      return sampleAd.store
    }

    var price : String? {
      return sampleAd.price
    }

    var adChoicesView : UIView? {
      return adInfoView
    }

    var extraAssets : [String : Any]? {
      return extras
    }

    var mediaView : UIView?{
      return self.sampleMediaView!
    }

    var hasVideoContent : Bool {
      return self.sampleAd.mediaView != nil
    }

    func didRecordImpression() {
      sampleAd.recordImpression()
    }

    func didRender(in view: UIView, clickableAssetViews: [GADUnifiedNativeAssetIdentifier : UIView],
                       nonclickableAssetViews: [GADUnifiedNativeAssetIdentifier : 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.sampleAd.mediaView.playMedia()
    }

    func didRecordClickOnAsset(withName assetName: GADUnifiedNativeAssetIdentifier, view: UIView, viewController: UIViewController) {
       sampleAd.handleClick(on: view)
    }

    func didUntrackView(_ view: UIView?) {
        // This method is called when the mediatedNativeAd is no longer
        // rendered in the provided view. Here you would remove any
        // tracking from the view that has mediated native ad.
    }

}

Objective-C

    @interface SampleMediatedNativeAd ()
    @property(nonatomic, strong) SampleNativeAd *sampleAd;
    @property(nonatomic, copy) NSArray *mappedImages;
    @property(nonatomic, strong) GADNativeAdImage *mappedIcon;
    @property(nonatomic, copy) NSDictionary *extras;
    @property(nonatomic, strong) GADNativeAdViewAdOptions *nativeAdViewAdOptions;
    @property(nonatomic, strong) SampleAdInfoView *adInfoView;
    @property(nonatomic, strong) SampleMediaView *mediaView;

    @end

    @implementation SampleMediatedNativeAd

    - (instancetype)initWithSampleNativeAd:(SampleNativeAd *)sampleNativeAd
                     nativeAdViewAdOptions:(nullable GADNativeAdViewAdOptions *)nativeAdViewAdOptions {
      if (!sampleNativeAd) {
        return nil;
      }

      self = [super init];
      if (self) {
        _sampleAd = sampleNativeAd;
        _extras = @{SampleCustomEventExtraKeyAwesomeness : _sampleAd.degreeOfAwesomeness};

        if (_sampleAd.image) {
          _mappedImages = @[ [[GADNativeAdImage alloc] initWithImage:_sampleAd.image] ];
        } else {
          NSURL *imageURL = [[NSURL alloc] initFileURLWithPath:_sampleAd.imageURL];
          _mappedImages =
              @[ [[GADNativeAdImage alloc] initWithURL:imageURL scale:_sampleAd.imageScale] ];
        }

        if (_sampleAd.icon) {
          _mappedIcon = [[GADNativeAdImage alloc] initWithImage:_sampleAd.icon];
        } else {
          NSURL *iconURL = [[NSURL alloc] initFileURLWithPath:_sampleAd.iconURL];
          _mappedIcon = [[GADNativeAdImage alloc] initWithURL:iconURL scale:_sampleAd.iconScale];
        }
        _mediaView = _sampleAd.mediaView;
        _nativeAdViewAdOptions = nativeAdViewAdOptions;

        // The sample SDK provides an AdChoices view (SampleAdInfoView).
        // If your SDK provides image and clickthrough 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.
        _adInfoView = [[SampleAdInfoView alloc] init];
      }
      return self;
    }

    - (BOOL)hasVideoContent {
      return self.sampleAd.mediaView != nil;
    }

    - (UIView *)mediaView {
      return _mediaView;
    }

    - (NSString *)advertiser {
      return self.sampleAd.advertiser;
    }

    - (NSString *)headline {
      return self.sampleAd.headline;
    }

    - (NSArray *)images {
      return self.mappedImages;
    }

    - (NSString *)body {
      return self.sampleAd.body;
    }

    - (GADNativeAdImage *)icon {
      return self.mappedIcon;
    }

    - (NSString *)callToAction {
      return self.sampleAd.callToAction;
    }

    - (NSDecimalNumber *)starRating {
      return self.sampleAd.starRating;
    }

    - (NSString *)store {
      return self.sampleAd.store;
    }

    - (NSString *)price {
      return self.sampleAd.price;
    }

    - (NSDictionary *)extraAssets {
      return self.extras;
    }

    - (UIView *)adChoicesView {
      return self.adInfoView;
    }

    // Because the Sample SDK has click and impression tracking via
    // methods on its native ad object which the developer is required
    // to call, there's no need to pass it a reference to the UIView
    // being used to display the native ad. So there's no need to
    // implement mediatedNativeAd:didRenderInView:viewController:clickableAssetViews:nonClickableAssetViews
    // here. If your mediated network does need a reference to the view,
    // this method can be used to provide one. You can also access the
    // clickable and non-clickable views by asset key if the mediation
    // network needs this information.
    - (void)didRenderInView:(UIView *)view
           clickableAssetViews:
               (NSDictionary<GADUnifiedNativeAssetIdentifier, UIView *> *)clickableAssetViews
        nonclickableAssetViews:
            (NSDictionary<GADUnifiedNativeAssetIdentifier, 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
      [_sampleAd playVideo];
    }

    - (void)didUntrackView:(UIView *)view {
      // This method is called when the mediatedNativeAd is no longer
      // rendered in the provided view. Here you would remove any
      // tracking from the view that has mediated native ad.
    }

    - (void)didRecordImpression {
      if (self.sampleAd) {
        [self.sampleAd recordImpression];
      }
    }

    - (void)didRecordClickOnAssetWithName:(GADUnifiedNativeAssetIdentifier)assetName
                                     view:(UIView *)view
                           viewController:(UIViewController *)viewController {
      if (self.sampleAd) {
        [self.sampleAd handleClickOnView:view];
      }
    }

    @end

まず、イニシャライザとその動作の一部を見ていきましょう。

メディエーション対象ネイティブ広告オブジェクトへの参照を保持する

イニシャライザは、その最初のパラメータとして SampleNativeAd のインスタンスを受け取ります。これは、サンプル SDK がネイティブ広告で使用するネイティブ広告クラスです。クリック イベントとインプレッション イベントを渡すため、マッパーはメディエーション対象広告オブジェクトを参照する必要があり、これを sampleAd として保存します。また、イニシャライザは、GADNativeAdViewAdOptions のインスタンスも受け取ります。

NSDictionary を作成して追加アセットを保持する

メディエーション対象ネットワークの中には、AdMob ネイティブ広告フォーマットにない追加アセットを渡すものもあります。こうした「追加」アセットは、GADMediatedUnifiedNativeAd プロトコルに含まれる extraAssets というメソッド(Google Mobile Ads SDK が使うメソッド)がマッパーから取得します。

上記のイニシャライザは NSDictionary を作成し、サンプル SDK から渡される追加アセット(以下の例では、degreeOfAwesomeness と呼ばれる 1 つの NSString 値)を格納します。この NSDictionary は、後で extraAssets メソッドによる戻り値として使用されます。

Swift

extras = [SampleCustomEventExtraKeyAwesomeness : sampleAd.degreeOfAwesomeness]

Objective-C

_extras = @{SampleCustomEventExtraKeyAwesomeness : _sampleAd.degreeOfAwesomeness};

画像アセットをマッピングする

画像アセットのマッピングは、NSStringdouble などの単純なデータ型のマッピングに比べると少し複雑です。画像がある場合は自動的にダウンロードされるか、単に URL 値として返されます。また、画像のピクセル密度もさまざまです。こうした細かい部分をカスタム イベント デベロッパーが管理しやすいように、Google Mobile Ads SDK には GADNativeAdImage クラスが用意されています。画像アセットの情報は(実際の UIImage オブジェクトの場合でも、単なる NSURL 値の場合でも)、このクラスを使用して Google Mobile Ads SDK に返す必要があります。

次の例では、マッパークラスで GADNativeAdImageを処理してアイコン画像を保持する方法を示します。

Swift

if let icon = sampleAd.icon {
    mappedIcon = GADNativeAdImage(image : icon)
}
else {
    let iconURL = URL(fileURLWithPath : sampleNativeAd.iconURL)
    mappedIcon = GADNativeAdImage(url : iconURL, scale : sampleAd.iconScale)
}

Objective-C

if (_sampleAd.icon) {
   _mappedIcon = [[GADNativeAdImage alloc] initWithImage:_sampleAd.icon];
} else {
   NSURL *iconURL = [[NSURL alloc] initFileURLWithPath:_sampleAd.iconURL];
   _mappedIcon = [[GADNativeAdImage alloc] initWithURL:iconURL scale:_sampleAd.iconScale];
}

リクエストの実施に関するセクションで説明したように、GADNativeAdImageAdLoaderOptions オブジェクトを使用すると、ネイティブ広告の画像を自動ダウンロードしないように指定できます。そのうえでマッパーは、画像がダウンロードされたかどうかを確認し、適切な情報(UIImage か、NSURL 値とスケール値の一致するペア)を使用して GADNativeAdImage を作成します。

イニシャライザの説明は以上です。次に、このクラス内のその他の働きについて見ていきましょう。

マッピングされたアセットを返す

このマッパークラスは、ネイティブ広告で求められるアセットに対応する GADMediatedUnifiedNativeAd からメソッドを継承します。Google Mobile Ads SDK はこれらのメソッドを呼び出してアセットを取得するため、マッパークラスは適切な値を返す必要があります。ほとんどのアセットの場合、この処理はとても簡単です。

Swift

var headline : String? {
  return sampleAd.headline
}

Objective-C

- (NSString *)headline {
  return self.sampleAd.headline;
}

ただし、一部のアセットでは、データ型が一致しない場合や別の型への変換が必要になる場合があります。こうした細かい部分を処理するのはマッパーの役割であり、その処理を行う場所としてアセット メソッドは最適です。

AdChoices

アダプタを使用して、AdChoices アイコンを提供します。adChoicesView メソッドは、GADMediatedUnifiedNativeAd プロトコルのオプションのメソッドです。このメソッドを実装すると、提供された Ad Choices ビューを SDK が取得してネイティブ広告内に表示します。

AdChoices アイコンの提供方法について、実装サンプルを以下に示します。

Swift

class SampleMediatedUnifiedNativeAd: NSObject, GADMediatedUnifiedNativeAd {
  /// Ad networks should provide their own AdChoices view.
  private var adChoicesView: SampleAdChoicesView?

  var adChoicesView : UIView? {
      return adChoicesView
  }

Objective-C

@interface SampleMediatedNativeAd ()<GADMediatedUnifiedNativeAd> {

  /// Ad networks should provide their own AdChoices view.
  SampleAdChoicesView *_adChoicesView;

}

@implementation SampleMediatedNativeAd

- (UIView *)adChoicesView {
  return _adInfoView;
}

インプレッション イベントとクリック イベント

インプレッションまたはクリックが発生したときは、必ずメディエーション対象ネットワークの SDK に通知することが重要です。そのため、マッパークラスは次のいずれかの役割を担う必要があります。メディエーション対象ネットワークの SDK に、インプレッションとクリックの測定を独自で処理するために必要な情報を提供する、またはインプレッションとクリックが発生したときに、メディエーション対象ネットワークの SDK に明示的に通知する。

メディエーション対象ネイティブ広告オブジェクトに、クリックとインプレッションを記録するメソッドが用意されている場合、カスタム イベントのマッパークラスはそのメソッドを使用できます。これは最も一般的な手法です。GADMediatedUnifiedNativeAd に含まれている didRecordImpression:didRecordClickOnAssetWithName:view:viewController: の 2 つのメソッドをマッパーでオーバーライドし、メディエーション対象ネイティブ広告オブジェクトの対応するメソッドを呼び出すために使います。

これに関する SampleMediatedNativeAd での処理方法を次に示します。

Swift

func didRecordImpression() {
  sampleAd.recordImpression()
}

func didRecordClickOnAsset(withName assetName: GADUnifiedNativeAssetIdentifier,
                                    view: UIView,
                                    viewController: UIViewController) {
  sampleAd.handleClick(on: view)
}

Objective-C

- (void)didRecordImpression {
  if (self.sampleAd) {
    [self.sampleAd recordImpression];
  }
}

- (void)didRecordClickOnAssetWithName:(GADUnifiedNativeAssetIdentifier)assetName
                                 view:(UIView *)view
                       viewController:(UIViewController *)viewController {
  if (self.sampleAd) {
    [self.sampleAd handleClickOnView:view];
  }
}

SampleMediatedNativeAd は、サンプル SDK のネイティブ広告オブジェクトへの参照を保持しているため、そのオブジェクトの適切なメソッドを呼び出すだけで、クリックとインプレッションを伝えることができます。

メディエーション対象ネットワークの SDK でクリックとインプレッションを測定する

クリックとインプレッションを独自に測定する必要がある広告ネットワークのために、GADCustomEventNativeAd プロトコルには handlesUserClickshandlesUserImpressions の 2 つのオプション メッセージが用意されています。これらのメッセージの 1 つで YES が返された場合は、その種のイベントの発生をカスタム イベントが独自に測定していることを示します。NO が返されるか何も返されない場合は、そのカスタム イベントに代わって Google Mobile Ads SDK でクリックとインプレッションを測定し、GADMediatedUnifiedNativeAddidRecordImpression:didRecordClickOnAssetWithName: を使ってそれらを伝える必要があることを示します。

クリックとインプレッションを独自に測定しているカスタム イベント トラッキングでは、GADMediatedUnifiedNativeAd プロトコルの didRenderInView: メッセージを使用して、ネイティブ広告のビューをメディエーション対象ネットワーク SDK のネイティブ広告オブジェクトに渡すことができ、そのメディエーション対象ネットワーク SDK はそのビューを使って実際の測定を行えます。このガイドのサンプルコードで紹介してきたサンプル SDK では、クリックとインプレッションの処理にこの手法を使っていませんが、仮に使用した場合、適切な didRenderInView: メソッドは次のようになります。

Swift

func didRender(in view: UIView,
                  clickableAssetViews: [GADUnifiedNativeAssetIdentifier : UIView],
                  nonclickableAssetViews: [GADUnifiedNativeAssetIdentifier : UIView],
                  viewController: UIViewController) {
  sampleAd?.setNativeAdView(view)
}

Objective-C

- (void)didRenderInView:(UIView *)view
       clickableAssetViews:
           (NSDictionary<GADUnifiedNativeAssetIdentifier, UIView *> *)clickableAssetViews
    nonclickableAssetViews:
        (NSDictionary<GADUnifiedNativeAssetIdentifier, UIView *> *)nonclickableAssetViews
            viewController:(UIViewController *)viewController {
  [self.sampleAd setNativeAdView:view];
}

GADMediatedUnifiedNativeAd には didUntrackView: も含まれます。これは逆の用途に使われます。カスタム イベントでビューへの参照を解放し、可能であればネイティブ広告オブジェクトとの関連付けを解除する場合には、カスタム イベントにこのメソッドを実装します。

GADMediatedNativeAdNotificationSource

メディエーション対象ネイティブ広告が画面の表示やクリックの記録などのイベントを報告できるように、Google Mobile Ads SDK には GADMediatedNativeAdNotificationSource クラスが用意されています。このクラスには、メディエーション対象ネイティブ広告のライフタイムに発生するさまざまなイベントに対応する 6 個のクラスメソッドがあり、それぞれのメソッドが対応する広告オブジェクトへの参照を取ります。具体的には、次のメソッドです。

  • mediatedNativeAdDidRecordImpression: - このメソッドは、独自にインプレッションを測定しているカスタム イベントが Google Mobile Ads SDK にインプレッションの発生を報告する際に、メディエーション対象ネイティブ広告で呼び出します。これは、報告のために必須のメソッドです。
  • mediatedNativeAdDidRecordClick: - このメソッドも上記の場合と同様に、独自にクリックを測定しているカスタム イベントがクリックの発生を報告する際に、メディエーション対象ネイティブ広告で呼び出します。
  • mediatedNativeAdWillPresentScreen: - メディエーション対象ネイティブ広告によってアプリ内のモーダル画面が開かれる直前に呼び出す必要があります。
  • mediatedNativeAdWillDismissScreen: - メディエーション対象ネイティブ広告によって開かれたアプリ内のモーダル画面が閉じられる直前に呼び出す必要があります。
  • mediatedNativeAdDidDismissScreen: - メディエーション対象ネイティブ広告によって開かれたアプリ内のモーダル画面が閉じられた後で呼び出す必要があります。
  • mediatedNativeAdWillLeaveApplication: - Safari でリンク先 URL を開く場合など、メディエーション対象ネイティブ広告によってアプリからフォーカスが移動する直前に呼び出す必要があります。

カスタム イベントを使用する

カスタム イベントを使用するには、広告ユニットのメディエーション設定にカスタム イベントを追加する必要があります。この処理は、AdMob 管理画面で行います(広告ユニットのメディエーション設定の詳しい編集手順については、カスタム イベントの作成の記事をご覧ください)。

カスタム イベントを広告ユニットのメディエーション設定に追加する際は、次の 3 つの情報が求められます。

  • Class Name - カスタム イベントのクラス名です。
  • Label - AdMob の管理画面に広告ユニットのメディエーション ソースが表示される際に、そのカスタム イベントを表すのに使うラベルです(ご自身で指定できます)。このラベルは自分専用で、AdMob 管理画面にしか表示されません。
  • Parameter - この広告ユニットがリクエストされたときにカスタム イベントに渡される文字列値です。通常は、メディエーション対象ネットワークの広告ユニット ID が値として設定されます。

カスタム イベントのエントリ例のスクリーンショットを次に示します。

このガイドの説明は以上です。AdMob 向けの独自の iOS カスタム イベントを記述するために必要な知識は、これですべてです。