システム定義のネイティブ広告フォーマットを表示する
ネイティブ広告が読み込まれると、GADAdLoaderDelegate プロトコルのいずれかのメッセージを介してネイティブ広告オブジェクトがアプリに届きます。広告を表示するのはアプリの役目ですが、必ずしも急ぐ必要はありません。システム定義の広告フォーマットを簡単に表示できるようにするため、SDK には便利なリソースが用意されています。
GADNativeAdView
GADNativeAd には、対応する「広告ビュー」クラス GADNativeAdView があります。この広告ビュークラスは UIView で、広告を表示する際に必ず使います。たとえば、1 つの GADNativeAdView で GADNativeAd の 1 つのインスタンスを表示できます。その広告のアセットの表示に使われる UIView オブジェクトはいずれも、GADNativeAdView オブジェクトのサブビューになります。
たとえば、UITableView に広告を表示している場合、そのセルの 1 つでのビュー階層は次のようになります。

GADNativeAdView クラスには、個々のアセットで使うビューの登録に使用する IBOutlets と、GADNativeAd オブジェクト自体を登録するためのメソッドがあります。この方法でビューを登録すると、次のようなタスクを SDK が自動的に処理できるようになります。
- クリックを記録する。
- インプレッションを記録する(画面に最初のピクセルが表示されたとき)。
- AdChoices オーバーレイを表示する。
AdChoices オーバーレイ
間接販売のネイティブ広告(AdMob バックフィル、Ad Exchange、AdSense 経由で配信される広告)については、SDK で AdChoices オーバーレイが追加されます。 AdChoices ロゴは自動的に挿入されるため、ネイティブ広告ビューのご希望の隅にスペースを空けておいてください。また、AdChoices オーバーレイは、そのアイコンをコンテンツ上で明確に識別できる場所に配置してください。 オーバーレイのデザインや機能について詳しくは、プログラマティック ネイティブ広告の実装に関するガイドラインをご確認ください。
広告の帰属表示
プログラマティック ネイティブ広告を表示する際は、広告の帰属表示を行って、そのビューが広告であることを示す必要があります。サンプルコード
このセクションでは、xib ファイルから動的に読み込まれるビューを使ってネイティブ広告を表示する方法を紹介します。この方法は、複数のフォーマットをリクエストする設定の GADAdLoaders を使う場合に極めて便利です。
UIViews をレイアウトする
まず、ネイティブ広告アセットを表示する UIViews をレイアウトします。この作業は Interface Builder で行います(他の xib ファイルを作成する場合と同様です)。ネイティブ広告をレイアウトする方法は次のようになります。

画像右上の [Custom Class(カスタムクラス)] の値を見ると、
GADNativeAdView が設定されています。これは、GADNativeAd の表示に使われる広告ビュークラスです。
また、広告の動画や画像の表示に使われる GADMediaView にもカスタムクラスを設定する必要があります。
アウトレットをビューにリンクする
ビューの設定が完了し、レイアウトに適切な広告ビュークラスを割り当てたら、作成済みの UIViews に広告ビューのアセット アウトレットをリンクします。広告用に作成した UIViews に、広告ビューのアセット アウトレットをリンクする方法を次に示します。

[Outlets(アウトレット)] パネルにおいて、Interface Builder でレイアウトした UIViews に、GADNativeAdView のアウトレットがリンクされています。これにより、どの UIView でどのアセットを表示するかを SDK に知らせます。また、これらのアウトレットは、広告内でクリック可能なビューを表していることも踏まえておいてください。
広告を表示する
レイアウトが完成してアウトレットをリンクしたら、読み込まれた広告を表示する次のコードをアプリに追加します。
Swift
func adLoader(_ adLoader: AdLoader, didReceive nativeAd: NativeAd) {
  // ...
  // Set ourselves as the native ad delegate to be notified of native ad events.
  nativeAd.delegate = self
  // Populate the native ad view with the native ad assets.
  // The headline and mediaContent are guaranteed to be present in every native ad.
  (nativeAdView.headlineView as? UILabel)?.text = nativeAd.headline
  nativeAdView.mediaView?.mediaContent = nativeAd.mediaContent
  // Some native ads will include a video asset, while others do not. Apps can use the
  // GADVideoController's hasVideoContent property to determine if one is present, and adjust their
  // UI accordingly.
  let mediaContent = nativeAd.mediaContent
  if mediaContent.hasVideoContent {
    // By acting as the delegate to the GADVideoController, this ViewController receives messages
    // about events in the video lifecycle.
    mediaContent.videoController.delegate = self
    videoStatusLabel.text = "Ad contains a video asset."
  } else {
    videoStatusLabel.text = "Ad does not contain a video."
  }
  // This app uses a fixed width for the GADMediaView and changes its height to match the aspect
  // ratio of the media it displays.
  if let mediaView = nativeAdView.mediaView, nativeAd.mediaContent.aspectRatio > 0 {
    let aspectRatioConstraint = NSLayoutConstraint(
      item: mediaView,
      attribute: .width,
      relatedBy: .equal,
      toItem: mediaView,
      attribute: .height,
      multiplier: CGFloat(nativeAd.mediaContent.aspectRatio),
      constant: 0)
    mediaView.addConstraint(aspectRatioConstraint)
    nativeAdView.layoutIfNeeded()
  }
  // These assets are not guaranteed to be present. Check that they are before
  // showing or hiding them.
  (nativeAdView.bodyView as? UILabel)?.text = nativeAd.body
  nativeAdView.bodyView?.isHidden = nativeAd.body == nil
  (nativeAdView.callToActionView as? UIButton)?.setTitle(nativeAd.callToAction, for: .normal)
  nativeAdView.callToActionView?.isHidden = nativeAd.callToAction == nil
  (nativeAdView.iconView as? UIImageView)?.image = nativeAd.icon?.image
  nativeAdView.iconView?.isHidden = nativeAd.icon == nil
  (nativeAdView.starRatingView as? UIImageView)?.image = imageOfStars(from: nativeAd.starRating)
  nativeAdView.starRatingView?.isHidden = nativeAd.starRating == nil
  (nativeAdView.storeView as? UILabel)?.text = nativeAd.store
  nativeAdView.storeView?.isHidden = nativeAd.store == nil
  (nativeAdView.priceView as? UILabel)?.text = nativeAd.price
  nativeAdView.priceView?.isHidden = nativeAd.price == nil
  (nativeAdView.advertiserView as? UILabel)?.text = nativeAd.advertiser
  nativeAdView.advertiserView?.isHidden = nativeAd.advertiser == nil
  // In order for the SDK to process touch events properly, user interaction should be disabled.
  nativeAdView.callToActionView?.isUserInteractionEnabled = false
  // Associate the native ad view with the native ad object. This is
  // required to make the ad clickable.
  // Note: this should always be done after populating the ad views.
  nativeAdView.nativeAd = nativeAd
}
SwiftUI
ビューモデルを作成する
ネイティブ広告を読み込み、ネイティブ広告データの変化を公開するビューモデルを作成します。
import GoogleMobileAds
class NativeAdViewModel: NSObject, ObservableObject, NativeAdLoaderDelegate {
  @Published var nativeAd: NativeAd?
  private var adLoader: AdLoader!
  func refreshAd() {
    adLoader = AdLoader(
      adUnitID: "ca-app-pub-3940256099942544/3986624511",
      // The UIViewController parameter is optional.
      rootViewController: nil,
      adTypes: [.native], options: nil)
    adLoader.delegate = self
    adLoader.load(Request())
  }
  func adLoader(_ adLoader: AdLoader, didReceive nativeAd: NativeAd) {
    // Native ad data changes are published to its subscribers.
    self.nativeAd = nativeAd
    nativeAd.delegate = self
  }
  func adLoader(_ adLoader: AdLoader, didFailToReceiveAdWithError error: Error) {
    print("\(adLoader) failed with error: \(error.localizedDescription)")
  }
}
UIViewRepresentable を作成する
NativeView の UIViewRepresentable を作成し、ViewModel クラスのデータの変化を検出できるようにします。
private struct NativeAdViewContainer: UIViewRepresentable {
  typealias UIViewType = NativeAdView
  // Observer to update the UIView when the native ad value changes.
  @ObservedObject var nativeViewModel: NativeAdViewModel
  func makeUIView(context: Context) -> NativeAdView {
    return
      Bundle.main.loadNibNamed(
        "NativeAdView",
        owner: nil,
        options: nil)?.first as! NativeAdView
  }
  func updateUIView(_ nativeAdView: NativeAdView, context: Context) {
    guard let nativeAd = nativeViewModel.nativeAd else { return }
    // Each UI property is configurable using your native ad.
    (nativeAdView.headlineView as? UILabel)?.text = nativeAd.headline
    nativeAdView.mediaView?.mediaContent = nativeAd.mediaContent
    (nativeAdView.bodyView as? UILabel)?.text = nativeAd.body
    (nativeAdView.iconView as? UIImageView)?.image = nativeAd.icon?.image
    (nativeAdView.starRatingView as? UIImageView)?.image = imageOfStars(from: nativeAd.starRating)
    (nativeAdView.storeView as? UILabel)?.text = nativeAd.store
    (nativeAdView.priceView as? UILabel)?.text = nativeAd.price
    (nativeAdView.advertiserView as? UILabel)?.text = nativeAd.advertiser
    (nativeAdView.callToActionView as? UIButton)?.setTitle(nativeAd.callToAction, for: .normal)
    // For the SDK to process touch events properly, user interaction should be disabled.
    nativeAdView.callToActionView?.isUserInteractionEnabled = false
    // Associate the native ad view with the native ad object. This is required to make the ad
    // clickable.
    // Note: this should always be done after populating the ad views.
    nativeAdView.nativeAd = nativeAd
  }
ビューをビュー階層に追加する
次のコードは、UIViewRepresentable をビュー階層に追加する方法を示したものです。
struct NativeContentView: View {
  // Single source of truth for the native ad data.
  @StateObject private var nativeViewModel = NativeAdViewModel()
  var body: some View {
    ScrollView {
      VStack(spacing: 20) {
        // Updates when the native ad data changes.
        NativeAdViewContainer(nativeViewModel: nativeViewModel)
          .frame(minHeight: 300)  // minHeight determined from xib.
Objective-C
- (void)adLoader:(GADAdLoader *)adLoader didReceiveNativeAd:(GADNativeAd *)nativeAd {
  // ...
  GADNativeAdView *nativeAdView = self.nativeAdView;
  // Set ourselves as the ad delegate to be notified of native ad events.
  nativeAd.delegate = self;
  // Populate the native ad view with the native ad assets.
  // The headline and mediaContent are guaranteed to be present in every native ad.
  ((UILabel *)nativeAdView.headlineView).text = nativeAd.headline;
  nativeAdView.mediaView.mediaContent = nativeAd.mediaContent;
  // This app uses a fixed width for the GADMediaView and changes its height
  // to match the aspect ratio of the media content it displays.
  if (nativeAdView.mediaView != nil && nativeAd.mediaContent.aspectRatio > 0) {
    NSLayoutConstraint *aspectRatioConstraint =
        [NSLayoutConstraint constraintWithItem:nativeAdView.mediaView
                                     attribute:NSLayoutAttributeWidth
                                     relatedBy:NSLayoutRelationEqual
                                        toItem:nativeAdView.mediaView
                                     attribute:NSLayoutAttributeHeight
                                    multiplier:(nativeAd.mediaContent.aspectRatio)
                                      constant:0];
    [nativeAdView.mediaView addConstraint:aspectRatioConstraint];
    [nativeAdView layoutIfNeeded];
  }
  if (nativeAd.mediaContent.hasVideoContent) {
    // By acting as the delegate to the GADVideoController, this ViewController
    // receives messages about events in the video lifecycle.
    nativeAd.mediaContent.videoController.delegate = self;
    self.videoStatusLabel.text = @"Ad contains a video asset.";
  } else {
    self.videoStatusLabel.text = @"Ad does not contain a video.";
  }
  // These assets are not guaranteed to be present. Check that they are before
  // showing or hiding them.
  ((UILabel *)nativeAdView.bodyView).text = nativeAd.body;
  nativeAdView.bodyView.hidden = nativeAd.body ? NO : YES;
  [((UIButton *)nativeAdView.callToActionView) setTitle:nativeAd.callToAction
                                               forState:UIControlStateNormal];
  nativeAdView.callToActionView.hidden = nativeAd.callToAction ? NO : YES;
  ((UIImageView *)nativeAdView.iconView).image = nativeAd.icon.image;
  nativeAdView.iconView.hidden = nativeAd.icon ? NO : YES;
  ((UIImageView *)nativeAdView.starRatingView).image = [self imageForStars:nativeAd.starRating];
  nativeAdView.starRatingView.hidden = nativeAd.starRating ? NO : YES;
  ((UILabel *)nativeAdView.storeView).text = nativeAd.store;
  nativeAdView.storeView.hidden = nativeAd.store ? NO : YES;
  ((UILabel *)nativeAdView.priceView).text = nativeAd.price;
  nativeAdView.priceView.hidden = nativeAd.price ? NO : YES;
  ((UILabel *)nativeAdView.advertiserView).text = nativeAd.advertiser;
  nativeAdView.advertiserView.hidden = nativeAd.advertiser ? NO : YES;
  // In order for the SDK to process touch events properly, user interaction
  // should be disabled.
  nativeAdView.callToActionView.userInteractionEnabled = NO;
  // Associate the native ad view with the native ad object. This is
  // required to make the ad clickable.
  // Note: this should always be done after populating the ad views.
  nativeAdView.nativeAd = nativeAd;
}
GitHub のサンプルコードの全文
Swift、SwiftUI、Objective-C でネイティブ広告を統合するサンプルコードの全文については、それぞれの GitHub リンクをご覧ください。
Swift: ネイティブ アドバンスのサンプル SwiftUI: ネイティブ広告のサンプル Objective-C: ネイティブ アドバンスのサンプルGADMediaView
画像アセットと動画アセットは、GADMediaView を介してユーザーに表示されます。このビューは xib ファイルで定義するか動的に構築される UIView であり、他のアセットビューの場合と同様に GADNativeAdView のビュー階層内に配置する必要があります。
他のすべてのアセットビューと同様に、メディアビューのコンテンツも設定する必要があります。これは、GADMediaView の mediaContent プロパティを使って設定します。GADNativeAd の mediaContent プロパティには、GADMediaView に渡すことができるメディア コンテンツが含まれています。
次のスニペットは、ネイティブ アドバンスのサンプル(Swift | Objective-C)で、GADNativeAd から GADMediaContent を使って GADMediaView にネイティブ広告アセットを渡す方法を示しています。
Swift
nativeAdView.mediaView?.mediaContent = nativeAd.mediaContent
Objective-C
nativeAdView.mediaView.mediaContent = nativeAd.mediaContent;
必ずネイティブ広告ビューの Interface Builder ファイルで、そのビューのカスタムクラスに GADMediaView を設定し、それを mediaView アウトレットにリンクします。
画像コンテンツ モードを変更する
GADMediaView クラスは、画像を表示する際に UIViewcontentMode プロパティに従います。GADMediaView での画像のスケーリング方法を変更する場合は、対応する UIViewContentMode を GADMediaView の contentMode プロパティに設定します。
たとえば、画像を GADMediaView のビューいっぱいに表示するには、次のように設定します(広告に動画がない場合)。
Swift
nativeAdView.mediaView?.contentMode = .scaleAspectFit
Objective-C
GADMediaView *mediaView = nativeAdView.mediaView;
if (mediaView) {
  mediaView.contentMode = UIViewContentModeScaleAspectFit;
}
GADMediaContent
GADMediaContent クラスは、GADMediaView クラスを使って表示されるネイティブ広告のメディア コンテンツに関するデータを保持します。GADMediaView mediaContent プロパティでの設定は次のようになります。
- 動画アセットがある場合は、その動画アセットがバッファリングされ、 - GADMediaView内で再生されます。動画アセットの有無は、- hasVideoContentで確認できます。
- 広告に動画アセットがない場合は、代わりに - mainImageアセットがダウンロードされ、- GADMediaView内に配置されます。
次のステップ
ユーザーのプライバシーについて詳細を確認します。