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

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

アド マネージャーのパブリッシャーは、システム定義のネイティブ フォーマットに加えて、アセットのカスタムリストを定義して独自のネイティブ広告フォーマットを作成することもできます。こうしたフォーマットはカスタム ネイティブ広告フォーマットと呼ばれ、予約済み広告で使用できます。これによりパブリッシャーは、任意の構造化データをアプリに渡すことができます。これらの広告は、NativeCustomFormatAd オブジェクトで表されます。

カスタムのネイティブ広告フォーマットを読み込む

このガイドでは、カスタムのネイティブ広告フォーマットを読み込んで表示する方法について説明します。

AdLoader をビルドする

カスタムのネイティブ広告フォーマットは、ネイティブ広告と同様に AdLoader クラスを使用して読み込みます。

Java

AdLoader adLoader = new AdLoader.Builder(context, "/6499/example/native")
    .forCustomFormatAd("10063170",
      new NativeCustomFormatAd.OnCustomFormatAdLoadedListener() {
          @Override
          public void onCustomFormatAdLoaded(NativeCustomFormatAd ad) {
              // Show the custom format and record an impression.
          }
      },
      new NativeCustomFormatAd.OnCustomClickListener() {
          @Override
          public void onCustomClick(NativeCustomFormatAd ad, String s) {
              // Handle the click action
          }
      })
    .withAdListener( ... )
    .withNativeAdOptions( ... )
    .build();

Kotlin

val adLoader = AdLoader.Builder(this, "/6499/example/native")
        .forCustomFormatAd("10063170",
            { ad ->
                // Show the custom format and record an impression.
            },
            { ad, s ->
            // Handle the click action
            })
        .withAdListener( ... )
        .withNativeAdOptions( ... )
        .build()

forCustomFormatAd メソッドでカスタム ネイティブ広告フォーマットをリクエストするように AdLoader を設定します。このメソッドに渡されるパラメータは次の 3 つです。

  • AdLoader でリクエストする必要があるカスタム ネイティブ広告フォーマットの ID。カスタムのネイティブ広告フォーマットにはそれぞれ ID が関連付けられています。このパラメータは、アプリが AdLoader にリクエストする形式を示します。
  • 広告が正常に読み込まれたときに呼び出される OnCustomFormatAdLoadedListener
  • ユーザーが広告をタップまたはクリックしたときに呼び出される OnCustomClickListener(省略可)。このリスナーについて詳しくは、以下の「クリックとインプレッションの処理」セクションをご覧ください。

1 つの広告ユニットを設定して複数のクリエイティブ フォーマットを配信できるため、一意のフォーマット ID を指定して forCustomFormatAd を複数回呼び出し、使用可能な複数のカスタム ネイティブ広告フォーマット用に広告ローダーを準備できます。

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

カスタムのネイティブ広告フォーマットを識別するために使用するフォーマット ID は、アド マネージャー管理画面の [配信] プルダウンの [ネイティブ] セクションで確認できます。

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

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

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

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

  1. NativeCustomFormatAd クラスは、お客様がアド マネージャーで定義したカスタム ネイティブ広告フォーマットを処理するためのクラスであるため、アセットを取得するための名前付き「ゲッター」はありません。代わりに、フィールドの名前をパラメータとして受け取る getTextgetImage などのメソッドが用意されています。
  2. NativeCustomFormatAd で使用する NativeAdView のような専用の広告ビュークラスはありません。ユーザー エクスペリエンスにとって適切なレイアウトであれば自由に使用できます。
  3. 専用の ViewGroup クラスがないため、広告のアセットの表示に使用するビューを登録する必要はありません。これにより、広告を表示するまでのコードを減らすことができますが、後でクリックを処理するために、余分な作業が必要になります。

NativeCustomFormatAd を表示する関数の例を次に示します。

Java

public void displayCustomFormatAd (ViewGroup parent,
                                     NativeCustomFormatAd customFormatAd) {
    // Inflate a layout and add it to the parent ViewGroup.
    LayoutInflater inflater = (LayoutInflater) parent.getContext()
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View adView = inflater.inflate(R.layout.custom_format_ad, parent);

    // Locate the TextView that will hold the value for "Headline" and
    // set its text.
    TextView myHeadlineView = (TextView) adView.findViewById(R.id.headline);
    myHeadlineView.setText(customFormatAd.getText("Headline"));

    // Locate the ImageView that will hold the value for "MainImage" and
    // set its drawable.
    Button myMainImageView = (ImageView) adView.findViewById(R.id.main_image);
    myMainImageView.setImageDrawable(
            customFormatAd.getImage("MainImage").getDrawable());

    ...
    // Continue locating views and displaying assets until finished.
    ...
}

Kotlin

public fun displayCustomFormatAd (parent: ViewGroup,
                                customFormatAd: NativeCustomFormatAd) {
    val adView = layoutInflater
            .inflate(R.layout.ad_simple_custom_format, null)

    val myHeadlineView = adView.findViewById<TextView>(R.id.headline)
    myHeadlineView.setText(customFormatAd.getText("Headline"));

    // Locate the ImageView that will hold the value for "MainImage" and
    // set its drawable.
    val myMainImageView = adView.findViewById(R.id.main_image);
    myMainImageView.setImageDrawable(
            customFormatAd.getImage("MainImage").drawable;

    ...
    // Continue locating views and displaying assets until finished.
    ...
}

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

カスタム フォーマットを作成する場合は、そのフォーマットを動画で使用することもできます。

アプリの実装では、NativeCustomFormatAd.getMediaContent() を使用してメディア コンテンツを取得できます。次に、setMediaContent() を呼び出して、メディアビューのメディア コンテンツをメディアビューに設定します。広告に動画コンテンツがない場合は、動画なしで広告を表示する別のプランを作成します。

次の例では、広告に動画コンテンツが含まれているかどうかを確認し、動画がない場合は広告の代わりに画像を表示します。

Java

// Called when a custom native ad loads.
@Override
public void onCustomFormatAdLoaded(final NativeCustomFormatAd ad) {

  MediaContent mediaContent = ad.getMediaContent();

  // Assumes you have a FrameLayout in your view hierarchy with the id media_placeholder.
  FrameLayout mediaPlaceholder = (FrameLayout) findViewById(R.id.media_placeholder);

  // Apps can check the MediaContent's hasVideoContent property to determine if the
  // NativeCustomFormatAd has a video asset.
  if (mediaContent != null && mediaContent.hasVideoContent()) {
    MediaView mediaView = new MediaView(mediaPlaceholder.getContext());
    mediaView.setMediaContent(mediaContent);
    mediaPlaceholder.addView(mediaView);

    // Create a new VideoLifecycleCallbacks object and pass it to the VideoController. The
    // VideoController will call methods on this object when events occur in the video
    // lifecycle.
    VideoController vc = mediaContent.getVideoController();
    vc.setVideoLifecycleCallbacks(
        new VideoController.VideoLifecycleCallbacks() {
          @Override
          public void onVideoEnd() {
            // Publishers should allow native ads to complete video playback before
            // refreshing or replacing them with another ad in the same UI location.
            super.onVideoEnd();
          }
        });
  } else {
    ImageView mainImage = new ImageView(this);
    mainImage.setAdjustViewBounds(true);
    mainImage.setImageDrawable(ad.getImage("MainImage").getDrawable());
    mediaPlaceholder.addView(mainImage);
    mainImage.setOnClickListener(
        new View.OnClickListener() {
          @Override
          public void onClick(View view) {
            ad.performClick("MainImage");
          }
        });
  }
}

Kotlin

// Called when a custom native ad loads.
NativeCustomFormatAd.OnCustomFormatAdLoadedListener { ad ->

  val mediaContent = ad.mediaContent

  // Apps can check the MediaContent's hasVideoContent property to determine if the
  // NativeCustomFormatAd has a video asset.
  if (mediaContent != null && mediaContent.hasVideoContent()) {
    val mediaView = MediaView(mediaPlaceholder.getContest())
    mediaView.mediaContent = mediaContent

    val videoController = mediaContent.videoController

    // Create a new VideoLifecycleCallbacks object and pass it to the VideoController. The
    // VideoController will call methods on this object when events occur in the video
    // lifecycle.
    if (videoController != null) {
      videoController.videoLifecycleCallbacks =
        object : VideoController.VideoLifecycleCallbacks() {
          override fun onVideoEnd() {
            // Publishers should allow native ads to complete video playback before refreshing
            // or replacing them with another ad in the same UI location.
            super.onVideoEnd()
          }
        }
    }
  } else {
    val mainImage = ImageView(this)
    mainImage.adjustViewBounds = true
    mainImage.setImageDrawable(ad.getImage("MainImage")?.drawable)

    mainImage.setOnClickListener { ad.performClick("MainImage") }
    customTemplateBinding.simplecustomMediaPlaceholder.addView(mainImage)
  }
}

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

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

カスタムのネイティブ広告フォーマットのクリック数とインプレッション数

カスタム ネイティブ広告フォーマットでは、アプリでインプレッションを記録し、クリック イベントを Google Mobile Ads SDK に報告する必要があります。

インプレッションを記録する

カスタム フォーマットの広告のインプレッションを記録するには、対応する NativeCustomFormatAdrecordImpression メソッドを呼び出します。

myCustomFormatAd.recordImpression();

アプリで誤って同じ広告に対してこのメソッドを 2 回呼び出した場合、SDK により、1 回のリクエストでインプレッションが重複して記録されることが自動的に防止されます。

クリック数のレポート

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

myCustomFormatAd.performClick("MainImage");

広告に関連付けられているすべてのビューでこのメソッドを呼び出す必要はありません。表示されるものの、ユーザーがクリックまたはタップしないことを意図した「Caption」という別のフィールドがある場合、アプリでそのアセットのビューに対して performClick を呼び出す必要はありません。

カスタム クリック アクションに応答する

カスタム フォーマットの広告がクリックされると、SDK から 3 つのレスポンスが次の順序で試行されます。

  1. OnCustomClickListener が指定されている場合は、AdLoader から呼び出します。
  2. 広告のディープリンク URL ごとに、コンテンツ リゾルバを特定し、最初に解決するリゾルバを開始します。
  3. ブラウザを開き、広告の従来のリンク先 URL に移動します。

forCustomFormatAd メソッドは OnCustomClickListener を受け入れます。リスナー オブジェクトを渡すと、SDK はその代わりに onCustomClick メソッドを呼び出し、それ以上のアクションは実行しません。ただし、リスナーとして null 値を渡すと、SDK は広告に登録されているディープリンクまたはリンク先 URL にフォールバックします。

カスタム クリック リスナーを使用すると、アプリはクリックに対する最適なアクション(UI の更新、新しいアクティビティの起動、クリックの記録のみなど)を決定できます。発生したクリックを記録するだけの例を次に示します。

Java

AdLoader adLoader = new AdLoader.Builder(context, "/6499/example/native")
    .forCustomFormatAd("10063170",
      new NativeCustomFormatAd.OnCustomFormatAdLoadedListener() {
        // Display the ad.
      },
      new NativeCustomFormatAd.OnCustomClickListener() {
          @Override
          public void onCustomClick(NativeCustomFormatAd ad, String assetName) {
            Log.i("MyApp", "A custom click just happened for " + assetName + "!");
          }
      }).build();

Kotlin

val adLoader = AdLoader.Builder(this, "/6499/example/native")
    .forCustomFormatAd("10063170",
        { ad ->
            // Display the ad.
        },
        { ad, assetName ->
                Log.i("MyApp", "A custom click just happened for $assetName!")
    }).build()

最初は、カスタム クリック リスナーが存在することに奇妙に思えるかもしれません。クリックの発生がアプリから SDK に通知されたばかりなのに、SDK がそれをアプリに報告する必要があるのはなぜでしょうか。

この情報フローが有用である理由もいくつかありますが、最も重要な点は SDK がクリックに対するレスポンスを制御し続けられる点です。たとえば、クリエイティブに設定された第三者トラッキング URL に対して自動的に ping を実行し、コードを追加せずにバックグラウンドで他のタスクを処理します。