Développement de l'adaptateur d'enchères

本指南适用于希望构建出价适配器的广告联盟 才能参与 Google 中介的实时出价 (RTB)。如果您 是发布商,请参阅发布商中介 操作说明。

出价适配器是集成的客户端部分。适配器 让您的广告联盟 SDK 能够与 Google 移动广告 SDK 通信, 加载您的出价工具投放的广告。

为确保出价正常运行,您的适配器需要 初始化、收集信号、加载广告以及传达广告生命周期 事件。在本指南中,我们将向您介绍 用于处理这些操作。

出价适配器的工作流程

初始化

整个请求、响应和呈现生命周期的详细流程 如下所示:

适配器负责工作流程的以下部分:

  • 第 4-7 步:初始化适配器并回调 Google 移动广告 SDK 在初始化完成后运行

  • 第 10-13 步:从广告联盟 SDK 收集要发送到 出价工具参与实时出价请求,并将这些请求转发给 Google 移动 广告 SDK。

  • 第 18-21 步:如果您的出价工具返回胜出的出价,则根据 来响应您的出价工具的响应加载后,通知 Google 移动广告 SDK 广告已加载。

  • 第 23 步及后续步骤:在您的广告展示时,通知 Google 移动广告 展示和点击事件以及发生的其他广告事件的 SDK 在广告展示生命周期中发生的所有变化

实现出价适配器

要为 Google 移动广告 SDK 创建出价适配器,您必须: 扩展 RtbAdapter 抽象类。以下部分 解释了 RtbAdapter 中的每种抽象方法。

getSDKVersionInfo()

您应在此处返回 SDK 的版本。此版本将传递给您的 作为 OpenRTB 请求的一部分。

此方法要求您返回 VersionInfo。以下示例显示了 您可能需要将 SDK 的字符串版本转换为 VersionInfo.

@Override
public VersionInfo getSDKVersionInfo() {
  // Get your SDK's version as a string. E.g. "1.2.3"
  // String versionString = YourSdk.getVersion();
  String splits[] = versionString.split("\\.");
  if (splits.length >= 3) {
      int major = Integer.parseInt(splits[0]);
      int minor = Integer.parseInt(splits[1]);
      int micro = Integer.parseInt(splits[2]);
      return new VersionInfo(major, minor, micro);
   }

   String logMessage = String.format("Unexpected SDK version format: %s." +
           "Returning 0.0.0 for SDK version.", sdkVersion);
   Log.w(TAG, logMessage);
   return new VersionInfo(0, 0, 0);
}

getVersionInfo()

您应在此处返回适配器的版本。此版本将传递给您的 作为 OpenRTB 请求的一部分。

Google 的开源且已版本化 适配器 使用 4 位数的适配器版本模式,但 VersionInfo 只允许有 3 位 数字。为了解决此问题,建议将最后两位数字组合起来 复制到补丁版本中,如下所示。

@Override
public VersionInfo getVersionInfo() {
  // Get your adapters's version as a string. E.g. "1.2.3.0"
  String versionString = BuildConfig.VERSION_NAME;
  String splits[] = versionString.split("\\.");
  if (splits.length >= 4) {
      int major = Integer.parseInt(splits[0]);
      int minor = Integer.parseInt(splits[1]);
      int micro = Integer.parseInt(splits[2]) * 100 + Integer.parseInt(splits[3]);
      return new VersionInfo(major, minor, micro);
    }

    String logMessage = String.format("Unexpected adapter version format: %s." +
                "Returning 0.0.0 for adapter version.", versionString);
    Log.w(TAG, logMessage);
    return new VersionInfo(0, 0, 0);
}

initialize()

超时:30 秒

在适配器中,initialize() 方法是第一个被调用的方法。时间是 每次会话仅调用一次。此方法会为您提供 MediationConfiguration 对象,这些对象表示 针对您的广告联盟配置的此应用中的展示位置;你可以循环播放 来解析每个展示位置的凭据 并将相关数据传递到您的 SDK 进行初始化。

您的 SDK 经过初始化且可以开始接收广告请求后,请调用 InitializationCompleteCallbackonInitializationSucceeded() 方法。 系统会将此回调函数转发给应用发布商,以便他们知道 可以开始加载广告。

@Override
public void initialize(Context context,
    InitializationCompleteCallback initializationCompleteCallback,
    List<MediationConfiguration> mediationConfigurations) {
  // Initialize your ad network's SDK.
  ...

  // Invoke the InitializationCompleteCallback once initialization completes.
  initializationCompleteCallback.onInitializationSucceeded();
}

collectSignals()

超时:1 秒

每次发布商请求广告时,RtbAdapter 的新实例都会 并调用 collectSignals() 方法。此实例 RtbAdapter 将在广告请求、响应和 呈现生命周期collectSignals() 方法支持 适配器以从设备提供信号,以便在 OpenRTB 请求。

collectSignals() 在后台线程上调用。 Google 移动广告 SDK 会同时要求来自所有适配器的信号 参与出价。请遵循这一要求并限制对界面线程的调用 。您的适配器或 SDK 需要完成的繁重工作 信号应在 initialize() 方法中完成并进行缓存。

准备好信号后,请使用您的onSuccess() 编码信号。

下面是一个实现示例:

@Override
public void collectSignals(RtbSignalData rtbSignalData,
                           SignalCallbacks signalCallbacks) {
  String signals = YourSdk.getSignals();
  signalCallbacks.onSuccess(signals);
}

如果您的适配器收集信号失败,请调用 signalCallbacks.onFailure() 提供一个字符串,说明所发生的错误。

实现广告加载方法

超时:10 秒

如果您的出价工具返回胜出的出价,则 Google 移动广告 SDK 会调用适配器以加载胜出的广告,从而将 出价工具返回,您的 SDK 需要加载该广告。

具体调用的加载方法取决于广告 请求的格式:

广告格式 加载方法
横幅 loadBannerAd()
插页式广告 loadInterstitialAd()
激励广告 loadRewardedAd()

为适配器支持的广告格式实现这些方法。

加载方法会在用户界面线程上调用,也可以在 用于提供信号的适配器此方法为您提供以下 参数:

  • MediationAdConfiguration,其中包含您的 SDK 需要 加载出价胜出的广告,例如出价响应和任何凭据 在 AdMob 界面中配置的发布商。

  • 用于通知 Google 移动广告 SDK 的 MediationAdLoadCallback 对象 在加载成功或失败时触发。

您的 SDK 加载广告后,请调用 mediationAdLoadCallback.onSuccess()。在 事件广告加载失败,则调用 mediationAdLoadCallback.onFailure() 用于说明所发生的错误的字符串。

mediationAdLoadCallback.onSuccess() 方法要求您传入 对象向“Ad”确认由 Google 移动 广告 SDK。这些广告界面会要求您提供有关广告的一些信息。

MediationAdConfiguration也有getWatermark() 方法返回表示 PNG 图片的采用 Base64 编码的字符串。此图片 应平铺在您广告上的透明叠加层中。 如需获得有关如何呈现水印的更多指导,请与 Google 联系。 它包含所展示广告的相关元数据,供发布商用于确定 所展示的广告的来源

对于横幅广告,系统会要求您提供横幅广告视图。对于非页内和 激励广告,系统会要求您实现 show() 方法,以便在 稍后才会更新我们建议您最好让自己的类 广告加载是否也负责实现这些广告方法。

以下是 loadBannerAd() 的实现示例。注意事项 适配器的实现代码会有所不同 与其他 SDK 集成

public final class SampleRtbAdapter extends RtbAdapter {
  ...

  @Override
  public void loadBannerAd(
      MediationBannerAdConfiguration adConfiguration,
      MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback> callback) {

      SampleBannerRenderer bannerRenderer =
          new SampleBannerRenderer(adConfiguration, callback);
      bannerRenderer.render();
    }
}

// Renders a banner ad, and forwards callbacks to the Google Mobile Ads SDK.
public class SampleBannerRenderer implements MediationBannerAd {
  private MediationBannerAdConfiguration adConfiguration;
  private final MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback> adLoadCallback;
  private AdView adView;
  private MediationBannerAdCallback callback;

  public SampleRtbBannerRenderer(
      MediationBannerAdConfiguration adConfiguration,
      MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback> adLoadCallback) {
    this.adConfiguration = adConfiguration;
    this.adLoadCallback = adLoadCallback;
  }

  public void render() {
    adView = new AdView(adConfiguration.getContext());
    adView.setAdSize(adConfiguration.getAdSize());
    // serverParameters are the parameters entered in the AdMob UI for your network.
    adView.setAdUnitId(adConfiguration.getServerParameters().getString("adUnitId"));

    // Map the callbacks from your SDK to Google's SDK.
    adView.setAdListener(new AdListener() {
      // See the next step for more information on callback mapping.
      // ...
    });

    // Get the bid response and watermark from the ad configuration and
    // pass the relevant information to your SDK.
    String ad = adConfiguration.getBidResponse();
    String watermark = adConfiguration.getWatermark();
    Bundle extras = new Bundle();
    extras.putString("bid", ad);
    extras.putString("watermark", watermark);
    AdRequest request = new AdRequest.Builder()
        .addNetworkExtrasBundle(AdMobAdapter.class, extras)
        .build();
    adView.loadAd(request);
  }

  // MediationBannerAd implementation

  @NonNull
  @Override
  public View getView() {
    return adView;
  }
}

中继广告展示生命周期事件

适配器最后负责通知 Google 移动广告 SDK 以便可以将它们转发给 发布商。发布商希望在特定时间收到这些回调,无论 由哪个广告网络来投放广告 因此,务必要尽可能多地 尽可能在适当的时间调用回调 移动广告 SDK 可以将这些内容转发给发布商。

适配器应在适用时调用以下事件:

适用于所有格式
方法 调用时间
reportAdClicked() 用户点击了广告。
reportAdImpression() 广告呈现了展示。
onAdOpened() 广告展示了全屏视图时。
onAdClosed() 广告的全屏视图已关闭时。
onAdLeftApplication() 广告导致用户离开应用时。
激励广告
onRewarded() 用户获得奖励。
视频回调(激励广告和原生广告)
onVideoStarted() 广告视频开始播放。
onVideoCompleted() 广告视频播完时。

适配器会收到 MediationAdLoadCallback<MediationAdT, MediationAdCallbackT> 对象返回给 mediationAdLoadCallback.onSuccess()。适配器 需要保留此对象并使用它来调用展示事件 出现的问题

通常情况下,其中大多数事件都是由广告网络的 SDK 促成的。通过 适配器的作用只是将广告联盟 SDK 中的回调映射到 Google 移动广告 SDK。

以下示例演示了如何从 SDK 的广告监听器,用于监听 Google 移动广告 SDK:

adView.setAdListener(new AdListener() {
    public void onAdLoaded() {
        callback = adLoadCallback.onSuccess(SampleBannerRenderer.this);
    }

    public void onAdImpression() {
        if (callback != null) {
            callback.reportAdImpression();
        }
    }

    public void onAdFailedToLoad(LoadAdError adError) {
        adLoadCallback.onFailure("Error: " + adError.toString());
    }

    public void onAdClosed() {
        if (callback != null) {
            callback.onAdClosed();
        }
    }

    public void onAdOpened() {
        if (callback != null) {
            callback.onAdOpened();
            callback.reportAdClicked();
        }
    }

    public void onAdLeftApplication() {
        if (callback != null) {
            callback.onAdLeftApplication();
        }
    }
});

跟踪原生广告展示所需的素材资源

每当原生广告展示 1 个像素时,Google 移动广告 SDK 就会为该原生广告记录一次展示。 。如果您的广告网络 SDK 需要展示特定素材资源 您的出价工具便可指定这些 原生素材资源。然后,Google 移动广告 SDK 会 确保先展示所需的原生素材资源,然后再记录展示次数。

请参阅原生必需的素材资源 文档 详细了解如何在出价中指定其他必需素材资源 响应。

显示广告错误

对于全屏广告格式,例如插页式广告和激励广告,成功 您将提供 MediationInterstitialAdMediationRewardedAd ,以便 Google 移动广告 SDK 可以请求适配器展示广告。

Google 移动广告 SDK 要求,如果适配器成功加载广告, 当发布商要求展示广告时,广告可以展示。这意味着 每个节目调用都应会带来展示

不过,在某些情况下,您可能还会无法展示广告。如果您 无法展示广告,请调用 onAdFailedToShow() 回调以取消展示。

下表显示了展示回调对全屏广告格式的展示次数记录有何影响:

回拨电话 结果
onAdOpened() Impression recorded
onAdFailedToShow() Impression failure1
持续数秒内未出现上述任何情况 Impression recorded

1 表示失败 您的广告网络不必为相应展示付费, 会影响可结算事件率的调整请参阅出价请求 信号 信息。

以下模拟示例演示了广告加载/展示生命周期 show 调用失败。

final class SampleRtbAdapter extends RtbAdapter implements MediationRewardedAd {

 private MediationRewardedAdCallback callback;
 private RewardedAd rewardedAd;

 ...

  @Override
  public void loadRewardedAd(
      MediationRewardedAdConfiguration adConfiguration,
      final MediationAdLoadCallback<MediationRewardedAd, MediationRewardedAdCallback> loadCallback) {

    // Load an ad. This mock example uses Google's SDK, but in practice
    // your adapter will load the ad using your ad network's SDK.
    RewardedAd.load(adConfiguration.getContext(),
        "ca-app-pub-3940256099942544/5224354917",
        new AdRequest.Builder().build(),
        new RewardedAdLoadCallback() {
          @Override
          public void onAdLoaded(@NonNull RewardedAd rewardedAd) {
            // When the ad loads, invoke the load success callback.
            callback = loadCallback.onSuccess(SampleRtbAdapter.this);
          }
        });
  }

  @Override
  public void showAd(Context context) {
    // In this mock example, your ad network requires an activity context, but
    // didn't receive one, making you unable to show the ad.
    if (!(context instanceof Activity)) {
      AdError error = new AdError(1, "Context must be an activity",
          "com.google.ads.mediation.sample");
      callback.onAdFailedToShow(error);
    }

    // This example shows Google SDK's callbacks, but it's likely your SDK
    // has similar presentation callbacks.
    rewardedAd.setFullScreenContentCallback(new FullScreenContentCallback() {
      @Override
      public void onAdShowedFullScreenContent() {
        // Your ad network SDK successfully showed the ad. Call onAdOpened().
        callback.onAdOpened();
      }

      @Override
      public void onAdFailedToShowFullScreenContent(AdError adError) {
        // Your ad network SDK failed to show the ad, invoke onAdFailedToShow.
        // In practice, you will map your SDK's error to an AdError.
        AdError error = new AdError(adError.getCode(), adError.getMessage(),
            adError.getDomain());
        callback.onAdFailedToShow(adError);
      }
    });


    rewardedAd.show((Activity) context, ...);
  }
}