カスタムのネイティブ広告フォーマット

カスタム広告フォーマット

システム定義のネイティブ広告フォーマットと同様に、カスタムのネイティブ広告フォーマットは GADAdLoader オブジェクトで読み込まれます。GADAdLoader を初期化する際に adTypes 配列に GADAdLoaderAdTypeCustomNative 定数値を含めると、広告の読み込み時にカスタムのネイティブ フォーマットをリクエストするよう設定できます。

GADCustomNativeAdLoaderDelegate

カスタム フォーマットを読み込むためのプロトコルには、2 つのメソッドがあります。1 つ目は、どのフォーマット ID をリクエストする必要があるかを特定するため、GADAdLoader で使用されます。

Swift

public func customNativeAdFormatIDs(for adLoader: GADAdLoader) -> [Any]

Objective-C

- (NSArray *)customNativeAdFormatIDsForAdLoader:(GADAdLoader *)adLoader;

すべてのカスタムのネイティブ広告フォーマットには、それぞれ対応するフォーマット ID があり、これによりフォーマットが識別されます。このメソッドを呼び出すと、表示する準備が整った広告のフォーマット ID を含む配列が、アプリによって返されます。

2 つ目は、システム定義フォーマットの場合と同様に、カスタム フォーマット広告が読み込まれたときに送信されます。

Swift

public func adLoader(_ adLoader: GADAdLoader,
    didReceive customNativeAd: GADCustomNativeAd)

Objective-C

- (void)adLoader:(GADAdLoader *)adLoader
    didReceiveCustomNativeAd:(GADCustomNativeAd *)customNativeAd;

形式 ID

カスタムのネイティブ広告フォーマットを一意に参照するために使用されるフォーマット ID は、アド マネージャー管理画面の [配信] プルダウンの [ネイティブ] セクションに表示されます。

各カスタム ネイティブ広告フォーマットのフォーマット ID は、それぞれの名前の横に表示されます。 名前をクリックすると詳細画面が開き、フォーマットのフィールドに関する情報が表示されます。

ここでは、個々のフィールドを追加、編集、削除できます。各アセットの名前をメモします。名前は、カスタムのネイティブ広告フォーマットを表示する際、各アセットのデータを取得するために使用されます。

カスタムのネイティブ広告フォーマットの表示

カスタムのネイティブ広告フォーマットは、広告を構成するアセットの独自のリストをパブリッシャー様が定義できるという点で、システム定義のネイティブ広告フォーマットと異なります。そのため、カスタムのネイティブ広告を表示するプロセスは、システム定義のフォーマットの広告を表示する場合と次の点で異なります。

  1. GADCustomNativeAd は、作成したカスタムのネイティブ広告フォーマットをすべて処理することを目的としているため、アセットに対する名前付きのアクセサーがありません。代わりに、フィールドの名前を引数として使用する imageForKey:stringForKey: などのメソッドが用意されています。
  2. GADNativeAdView で使用する GADCustomNativeAd のような専用の広告ビュークラスはありません。ユーザー エクスペリエンスに適したビューを自由に使用できます。
  3. 専用の広告ビュークラスはないため、広告のアセットの表示に使用するビューを登録する必要はありません。

簡単なカスタム ネイティブ広告を表示できる広告ビューの例を次に示します。

MySimpleNativeAdView.h

Swift

import UIKit
import GoogleMobileAds

/// Custom native ad view class with format ID 10063170.
class MySimpleNativeAdView: UIView {

  /// Weak references to this ad's asset views.
  @IBOutlet weak var headlineView: UILabel!
  @IBOutlet weak var mainImageView: UIImageView!
  @IBOutlet weak var captionView: UILabel!

  ...

  /// Populates the ad view with the custom native ad object.
  func populateWithCustomNativeAd(_ customNativeAd: GADCustomNativeAd) {
    ...
  }
}

Objective-C

@import UIKit;
@import GoogleMobileAds;

/// View representing a custom native ad format with format ID 10063170.
@interface MySimpleNativeAdView : UIView

// Weak references to this ad's asset views.
@property(weak, nonatomic) IBOutlet UILabel *headlineView;
@property(weak, nonatomic) IBOutlet UIImageView *mainImageView;
@property(weak, nonatomic) IBOutlet UILabel *captionView;

/// Populates the ad view with the custom native ad object.
- (void)populateWithCustomNativeAd:(GADCustomNativeAd *)customNativeAd;

@end

MySimpleNativeAdView.m(抜粋)

Swift

...
func populateWithCustomNativeAd(_ customNativeAd: GADCustomNativeAd) {
  self.customNativeAd = customNativeAd

  // Populate the custom native ad assets.
  headlineView.text = self.customNativeAd.stringForKey("Headline")
  mainImageView.image = self.customNativeAd.imageForKey("MainImage")?.image
  captionView.text = self.customNativeAd.stringForKey("Caption")
}
...

Objective-C

...
- (void)populateWithCustomNativeAd:(GADCustomNativeAd *)customNativeAd {
  self.customNativeAd = customNativeAd;

  // Populate the custom native ad assets.
  self.headlineView.text = [customNativeAd stringForKey:@"Headline"];
  self.mainImageView.image = [customNativeAd imageForKey:@"MainImage"].image;
  self.captionView.text = [customNativeAd stringForKey:@"Caption"];
}
...

AdChoices アイコンをレンダリングする

デジタル サービス法(DSA)への準拠の一環として、欧州経済領域(EEA)で配信される純広告には、AdChoices アイコンと Google の [この広告について] ページへのリンクが必要です。カスタムのネイティブ広告を実装する場合は、AdChoices アイコンを表示する必要があります。メインの広告アセットを表示する際は、AdChoices アイコンをレンダリングして、クリック リスナーを設定することが重要です。

次の例では、AdChoices アイコンをレンダリングし、適切なクリック動作を構成します。

Swift

class MySimpleNativeAdView: UIView {
  @IBOutlet weak var adChoicesView: UIImageView!

  override func awakeFromNib() {
    super.awakeFromNib()

    // Enable clicks on AdChoices.
    adChoicesView.addGestureRecognizer(
      UITapGestureRecognizer(
        target: self,
        action: #selector(performClickOnAdChoices(_:))))
    adChoicesView.isUserInteractionEnabled = true
  }

  @objc func performClickOnAdChoices(_ sender: UIImage!) {
    customNativeAd.performClickOnAsset(withKey:
      GADNativeAssetIdentifier.adChoicesViewAsset.rawValue)
  }

  func populate(withCustomNativeAd customNativeAd: GADCustomNativeAd) {

    // Render the AdChoices image.
    let adChoicesKey = GADNativeAssetIdentifier.adChoicesViewAsset.rawValue
    let adChoicesImage = customNativeAd.image(forKey: adChoicesKey)?.image
    adChoicesView.image = adChoicesImage
    adChoicesView.isHidden = adChoicesImage == nil
    ...
  }
}

Objective-C

@interface MySimpleNativeAdView ()

@property(nonatomic, weak) IBOutlet UIImageView *adChoicesView;

@end

@implementation MySimpleNativeAdView

- (void)awakeFromNib {
  [super awakeFromNib];
  // Enable clicks on AdChoices.
  [self.adChoicesView addGestureRecognizer:[[UITapGestureRecognizer alloc]
                                            initWithTarget:self
                                            action:@selector(performClickOnAdChoices:)]];
  self.adChoicesView.userInteractionEnabled = YES;
}

- (void)performClickOnAdChoices:(UITapGestureRecognizer *)sender {
    [self.customNativeAd performClickOnAssetWithKey:GADNativeAdChoicesViewAsset];
}

- (void)populateWithCustomNativeAd:(GADCustomNativeAd *)customNativeAd {
  // Render the AdChoices image.
  GADNativeAdImage *adChoicesAsset = [customNativeAd
    imageForKey:GADNativeAdChoicesViewAsset];
  self.adChoicesView.image = adChoicesAsset.image;
  self.adChoicesView.hidden = (adChoicesAsset == nil);
  ...
}

カスタムのネイティブ広告フォーマットのネイティブ動画

カスタムのフォーマットを作成する際は、そのフォーマットを動画対応にすることもできます。

アプリに実装する際は、GADCustomNativeAd.mediaView プロパティを使って動画のビューを取得して、このビューをビュー階層に追加します。広告に動画コンテンツがない場合は、動画なしで広告を表示する代替プランを用意します。

次の例では、広告に動画コンテンツがあるかどうかを確認し、動画がない場合はその表示対象位置に画像を表示しています。

Swift

...
  /// Populates the ad view with the custom native ad object.
  func populate(withCustomNativeAd customNativeAd: GADCustomNativeAd) {
    if customNativeAd.videoController.hasVideoContent(),
      let mediaView = customNativeAd.mediaView {
      updateMainView(mediaView)
    } else {
      // Assumes your native format has an image asset with the name MainImage.
      let image: UIImage? = customNativeAd.image(forKey: "MainImage")?.image
      updateMainView(UIImageView(image: image))
    }
  }

  private func updateMainView(_ mainView:UIView) {
    // Assumes you have a placeholder view for your media content.
    // Remove all the placeholder's subviews.
    for subview: UIView in mainPlaceholder.subviews {
      subview.removeFromSuperview()
    }
    mainPlaceholder.addSubview(mainView)
    // Size the media view to fill our container size.
    mainView.translatesAutoresizingMaskIntoConstraints = false
    let viewDictionary: [AnyHashable: Any] = ["mainView":mainView]
    mainPlaceholder.addConstraints(NSLayoutConstraint.constraints(
      withVisualFormat: "H:|[mainView]|", options: [], metrics: nil,
      views: viewDictionary as? [String : Any] ?? [String : Any]()))
    mainPlaceholder.addConstraints(NSLayoutConstraint.constraints(
      withVisualFormat: "V:|[mainView]|", options: [], metrics: nil,
      views: viewDictionary as? [String : Any] ?? [String : Any]()))
  }
...

Objective-C

...
- (void)populateWithCustomNativeAd:(GADCustomNativeAd *)ad {
  UIView *mainView = nil;
  if (ad.videoController.hasVideoContent) {
    mainView = ad.mediaView;
  } else {
    // Assumes your native format has an image asset with the name MainImage.
    UIImage *image = [ad imageForKey:@"MainImage"].image;
    mainView = [[UIImageView alloc] initWithImage:image];
  }
  // Assumes you have a placeholder view for your media content.
  for (UIView *subview in self.mainPlaceholder.subviews) {
    [subview removeFromSuperview];
  }
  [self.mainPlaceholder addSubview:mainView];

  // Size the main view to fill our container size.
  [mainView setTranslatesAutoresizingMaskIntoConstraints:NO];
  NSDictionary *viewDictionary = NSDictionaryOfVariableBindings(mainView);
  [self.mainPlaceholder
      addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[mainView]|"
                                                             options:0
                                                             metrics:nil
                                                               views:viewDictionary]];
}
...

カスタム ネイティブ広告の動画エクスペリエンスをカスタマイズする方法について詳しくは、GADVideoController をご覧ください。

実際に動作するネイティブ動画の例については、アド マネージャーのカスタム レンダリング サンプルをダウンロードしてください。

カスタムのネイティブ広告のクリックとインプレッションの処理

カスタムのネイティブ広告フォーマットでは、アプリは、インプレッションを記録して SDK にクリック イベントを報告する役割を担います。

インプレッションの記録

カスタムのネイティブ広告のインプレッションを記録するには、対応する GADCustomNativeAdrecordImpression メソッドを呼び出します。

Swift

myCustomNativeAd.recordImpression()

Objective-C

[myCustomNativeAd recordImpression];

アプリが誤って同じ広告に対してメソッドを複数回呼び出しても、SDK では、1 件のリクエストに対するインプレッションが重複して記録されないようになっています。

クリックの記録

アセットビューでクリックが発生したことを SDK に報告するには、対応する GADCustomNativeAdperformClickOnAssetWithKey: メソッドを呼び出し、クリックされたアセットの名前を渡します。たとえば、「MainImag」というカスタム フォーマットにアセットが存在し、そのアセットに対応するビューで発生したクリックをレポートする場合、コードは次のようになります。

Swift

myCustomNativeAd.performClickOnAsset(withKey: "MainImage")

Objective-C

[myCustomNativeAd performClickOnAssetWithKey:@"MainImage"];

広告に関連付けられているすべてのアセットビューについてこのメソッドを呼び出す必要はありません。たとえば、表示されてもクリックやタップができないようになっている「Caption」という別のアセットがある場合は、アプリでそのビューに対して performClickOnAssetWithKey: を呼び出す必要はありません。

カスタム クリック アクションへの応答

GADCustomNativeAd には、タイプが GADNativeAdCustomClickHandler のプロパティ customClickHandler があります。

Swift

typealias GADNativeAdCustomClickHandler = (assetID: String) -> Void

Objective-C

typedef void (^GADNativeAdCustomClickHandler)(NSString *assetID);

これは、assetID を入力パラメータとして受け取るブロック(Objective-C の場合)またはクロージャ(Swift の場合)です。これにより、クリックされたアセットが識別されます。

カスタムのネイティブ広告がクリックされると、SDK は 3 つの応答を次の順序で試行します。

  1. customClickHandler のブロック(Objective-C の場合)またはクロージャ(Swift の場合)を呼び出す(設定されている場合)。
  2. 広告のディープリンク URL を走査し、一致するアプリが見つかった最初の URL を開く。
  3. ブラウザを開き、広告の従来のリンク先 URL に移動する。

customClickHandler プロパティでは、Objective-C のブロックと Swift のクロージャを使用できます。ブロックまたはクロージャを設定すると、SDK で実行されます。それ以上の処理は行われません。ただし、nil 値を設定した場合、SDK は広告に登録されているディープリンクまたはリンク先 URL にフォールバックします。

カスタム クリック ハンドラを使用すると、クリックに対する応答として最適な動作(UI を更新するか、別のビュー コントローラを表示する、または単にクリックのログを記録するなど)をアプリ自体が決定できます。アラートを表示する方法について、次に例を示します。

Swift

myCustomNativeAd.customClickHandler = { assetID in
  if assetID == "MainImage" {
    let alertView = UIAlertView(title: "Custom Click",
        message: "You just clicked on the image!",
        delegate: self,
        cancelButtonTitle: "OK")
    alertView.alertViewStyle = .default
    alertView.show()
  }
}
myCustomNativeAd.performClickOnAsset(withKey: "MainImage")

Objective-C

[self.customNativeAd setCustomClickHandler:^(NSString *assetID){
  if ([assetID isEqualToString:@"MainImage"]) {
    [[[UIAlertView alloc] initWithTitle:@"Custom Click"
                                message:@"You just clicked on the image!"
                               delegate:self
                      cancelButtonTitle:@"OK"
                      otherButtonTitles:nil] show];
  }
}];
[self.customNativeAd performClickOnAssetWithKey:@"MainImage"];

ネイティブ広告コードのテスト

直接販売の広告

直接販売のネイティブ広告がどのように表示されるかテストするには、次のアド マネージャー広告ユニット ID を使用します。

/21775744923/example/native

これは、アプリ インストール広告やコンテンツ広告のほか、次のアセットを含むカスタムのネイティブ広告フォーマットのサンプルも配信するよう設定されています。

  • 広告見出し(テキスト)
  • メイン画像(画像)
  • 説明(テキスト)

ネイティブ バックフィル広告

ネイティブ バックフィル広告の動作をテストするには、次のアド マネージャー広告ユニットを使用します。

/21775744923/example/native-backfill

この広告ユニットを使用すると、AdChoices オーバーレイを含むアプリ インストール広告とコンテンツ広告のサンプルが配信されます。

広告配信を開始する際は、実際の広告ユニットとフォーマット ID を参照するようコードを事前に更新してください。