Custom Native Ad Formats

自定义原生广告格式

除了系统定义的原生广告格式之外,Ad Manager 发布商还可以通过自行指定一系列素材资源来创建自己的原生广告格式。这类格式称为自定义原生广告格式,可以用于预订型广告。这样,发布商就可以将任意结构化数据传递给应用。这些广告由 NativeCustomTemplateAd 对象表示。

加载自定义原生广告格式

本指南介绍了如何加载和显示自定义原生广告格式

构建 AdLoader

与统一原生广告一样,自定义原生广告格式也是使用 AdLoader 类加载的:

Java

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

Kotlin

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

forUnifiedNativeAd 方法配置 AdLoader 来请求应用安装广告非常类似,forCustomTemplateAd 方法也会通过设置该加载程序来处理自定义模板广告。系统会将如下三个参数传递到该方法中:

  • AdLoader 应该请求的自定义模板的模板 ID。每种自定义的原生广告格式都具有与其相关联的模板 ID 值。此参数指示您的应用希望 AdLoader 请求哪个模板。
  • 广告成功加载后要调用的 OnCustomTemplateAdLoadedListener
  • 用户点按或点击广告时要调用的 OnCustomClickListener(可选)。有关此监听器的详情,请参阅下面的“处理点击次数和展示次数”部分。

由于单个广告单元可以设置为投放多个广告素材模板,因此可以使用唯一模板 ID 多次调用 forCustomTemplateAd,以便使广告加载程序为可能存在的多种自定义原生广告格式做好准备。

模板 ID

在 Ad Manager 界面中的投放标签中,转到广告素材 > 原生广告格式部分,即可找到用于唯一标识原生自定义广告格式的模板 ID:

每个自定义原生广告格式的模板 ID 都显示在其名称下方。点击其中一个名称可以转到详细信息屏幕,该屏幕中显示了相应模板的字段信息:

您可以在此处添加、修改和移除各个字段。请注意右侧的变量 ID 列。这些 ID 用于访问具体素材资源,在下一节中我们会详加讨论。

展示自定义原生广告格式

自定义原生广告格式与系统定义的原生广告格式的不同之处在于:发布商有权定义自己的广告制作“模板”(即素材资源列表)。因此,与系统定义的格式相比,自定义原生广告的展示过程会在以下方面有所不同:

  1. 因为 NativeCustomTemplateAd 类用于处理您在 Ad Manager 中定义的任何自定义原生广告格式,因此它没有命名的素材资源 get 程序。它实际提供的是以模板字段的变量 ID 为参数的 getTextgetImage 等方法。
  2. 没有 NativeContentAdView 等可用于 NativeCustomTemplateAd 的专用广告视图类。您可以随意使用 FrameLayout、RelativeLayout 或任何有助于改善用户体验的广告视图类。
  3. 因为没有专用的 ViewGroup 类,所以您不需要注册任何用于展示广告素材资源的视图。这会在展示广告时节省几行代码,但也意味着您后续需要做一点额外的工作来处理点击。

以下是一个展示 NativeCustomTemplateAd 的示例函数:

Java

    public void displayCustomTemplateAd (ViewGroup parent,
                                         NativeCustomTemplateAd customTemplateAd) {
        // 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_template_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(customTemplateAd.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(
                nativeCustomTemplateAd.getImage("MainImage").getDrawable());

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

Kotlin

    public fun displayCustomTemplateAd (parent: ViewGroup,
                                    customTemplateAd: NativeCustomTemplateAd) {
        val adView = layoutInflater
                .inflate(R.layout.ad_simple_custom_template, null)

        val myHeadlineView = adView.findViewById<TextView>(R.id.headline)
        myHeadlineView.setText(customTemplateAd.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(
                customTemplateAd.getImage("MainImage").drawable;

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

自定义原生广告格式的原生视频

在创建新的原生广告格式时,您可以选择让格式适用于视频。

只需选中上图中的复选框,即可让格式适用于视频;这样,当您为此格式制作新的广告素材时,您就可以选择提供视频素材资源。

在您的应用实现代码中,可以使用 NativeCustomTemplateAd.getVideoMediaView() 获取视频的视图,然后将此视图添加到视图层次结构中。如果广告没有视频内容,则需要制定备用方案,以便在没有视频的情况下也能展示广告。

以下示例代码会检查广告是否有视频内容,如果没有视频,则会在视频位置展示图片:

Java

    // Called when a custom native ad loads.
    @Override
    public void onCustomTemplateAdLoaded(NativeCustomTemplateAd ad) {
        VideoController videoController = ad.getVideoController();
        // Assumes you have a FrameLayout in your view hierarchy with the id media_placeholder.
        FrameLayout mediaPlaceholder = (FrameLayout) findViewById(R.id.media_placeholder);
        if (videoController.hasVideoContent()) {
            mediaPlaceholder.addView(ad.getVideoMediaView());
        } else {
            ImageView mainImage = new ImageView(this);
            mainImage.setAdjustViewBounds(true);
            // Assumes your native format has an image asset with the name MainImage.
            mainImage.setImageDrawable(ad.getImage("MainImage").getDrawable());
            mediaPlaceholder.addView(mainImage);
        }
    }
    

Kotlin

    NativeCustomTemplateAd.OnCustomTemplateAdLoadedListener { ad ->
        val videoController = ad.videoController
        // Assumes you have a FrameLayout in your view hierarchy with the id media_placeholder.
        val mediaPlaceholder = adView.findViewById<FrameLayout>(R.id.media_placeholder)
        if (videoController.hasVideoContent())
        {
            mediaPlaceholder.addView(ad.videoMediaView)
        }
        else
        {
            val mainImage = ImageView(this)
            mainImage.adjustViewBounds = true
            // Assumes your native format has an image asset with the name MainImage.
            mainImage.setImageDrawable(ad.getImage("MainImage").drawable)
            mediaPlaceholder.addView(mainImage)
        }
    }
    

请参阅 VideoController,详细了解如何才能量身定制自定义原生广告的视频体验。

您可以下载 Ad Manager 自定义呈现示例,以获取实际投放的原生视频广告示例。

自定义原生广告格式的点击次数和展示次数

使用自定义原生广告格式时,您的应用负责记录展示次数,并向 Google 移动广告 SDK 报告点击事件。

记录展示次数

要记录自定义模板广告的展示次数,只需在相应 NativeCustomTemplateAd 上调用 recordImpression 方法:

myCustomTemplateAd.recordImpression();
    

如果您的应用不小心针对同一个广告调用该方法两次,则 SDK 会自动阻止系统针对单个请求重复记录展示次数。

报告点击

要向 SDK 报告在素材资源视图中发生了点击,请在相应 NativeCustomTemplateAd 上调用 performClick 方法,并传入获得点击的素材资源的名称。例如,如果您的自定义模板中有一个名为“MainImage”的素材资源,并且您希望报告与该素材资源对应的 ImageView 上的点击,则代码大致会如下所示:

myCustomTemplateAd.performClick("MainImage");
    

请注意,您不需要为广告所关联的每个视图都调用此方法。例如,如果您有另一个名为“Caption”的字段,该字段只作展示之用,不会用于接受用户的点击或点按,则您的应用就不需要为该素材资源的视图调用 performClick

响应自定义点击操作

当自定义模板广告上发生点击时,SDK 可能会作出的响应有三种,具体尝试的响应顺序如下:

  1. 调用 AdLoader 中的 OnCustomClickListener(如果已提供)。
  2. 对于每个广告的深层链接网址,尝试查找内容解析器,并启动第一个能够解析网址的内容解析器。
  3. 打开浏览器并导航到广告的传统目标网址。

forCustomTemplateAd 方法接受 OnCustomClickListener。如果您传入监听器对象,SDK 会改为调用其 onCustomClick 方法,并且不会采取进一步操作。但是,如果您传递一个 null 值作为监听器,SDK 会退回到广告中注册的深层链接和/或目标网址。

自定义点击监听器可让您的应用决定响应点击的最佳操作,无论是更新界面、启动新活动还是仅记录点击。以下是一个只记录发生点击的示例:

Java

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

Kotlin

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

乍一看,存在自定义点击监听器似乎很奇怪。毕竟,您的应用刚刚告诉 SDK 发生了一次点击,为什么 SDK 应该反过来向应用报告?

这种信息流动其实有多方面的用处,但最重要的是,它让 SDK 能够保持对点击响应的控制。例如,它可以自动对已为广告素材设置的第三方跟踪网址执行 ping 操作,并在后台处理其他一些任务,而不需要任何额外的代码。