本指南适用于为了在 Google 中介服务内参与实时出价 (RTB) 而希望构建出价适配器的广告联盟。如果您 是发布商,请参阅发布商中介 说明。
出价适配器是整个集成方案中的客户端部分。通过该适配器 ,您的广告联盟 SDK 可与 Google Mobile Ads SDK (Legacy) 通信,以 加载您的出价工具投放的广告。
为确保出价解决方案正常运作,您的适配器需要处理各种操作,包括初始化、收集信号、加载广告以及传达广告生命周期事件。在本指南中,我们将向您介绍如何实现适配器来处理这些操作。
出价适配器的工作流程
初始化
下面详细地展示了适配器的整个请求、响应和呈现生命周期流程:

适配器负责工作流程的以下部分:
第 4-7 步:初始化适配器,在初始化完成后回调 Google Mobile Ads SDK (Legacy) 。
第 10-13 步:收集来自您的广告联盟 SDK 的信号,以将其发送至您的出价工具供参与 RTB 请求使用,并将其转发至 Google 移动广告 SDK。
第 18-21 步:如果您的出价工具返回胜出的出价,则根据出价工具中的响应加载广告。加载完成后,通知 Google Mobile Ads SDK (Legacy) 广告已加载。
第 23 步及之后:在广告展示期间,将展示和点击事件以及广告展示生命周期内发生的其他广告事件通知 Google 移动广告 SDK。
实现出价适配器
如需为 Google Mobile Ads SDK (Legacy) 创建出价适配器,您必须扩展 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 初始化完毕并准备好接收广告请求后,调用 InitializationCompleteCallback 的 onInitializationSucceeded() 方法。
系统会将此回调函数转发给应用发布商,让他们知道自己可以开始加载广告了。
@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 Mobile Ads SDK (Legacy)
会同时向参与出价的所有适配器
请求信号。请注意,在此期间限制对界面线程的调用。适配器或 SDK 需要执行的任何繁重工作(用于收集
信号)都应在 initialize() 方法中完成并缓存。
准备好信号后,使用编码后的信号调用 onSuccess() 回调。
下面是一个实现示例:
@Override
public void collectSignals(RtbSignalData rtbSignalData,
SignalCallbacks signalCallbacks) {
String signals = YourSdk.getSignals();
signalCallbacks.onSuccess(signals);
}
如果您的适配器无法收集信号,请使用说明所发生错误的字符串调用 signalCallbacks.onFailure()。
实现广告加载方法
超时时间:10 秒
如果您的出价工具返回胜出的出价,则 Google Mobile Ads SDK (Legacy) 会调用您的适配器以加载胜出的广告,这样便可从 出价工具返回的数据中将您的 SDK 加载该广告所需的全部数据都传递给您。
调用的确切加载方法取决于此请求所针对的广告格式:
| 广告格式 | 加载方法 |
|---|---|
| 横幅广告 | loadBannerAd()
|
| 插页式广告 | loadInterstitialAd()
|
| 激励广告 | loadRewardedAd()
|
为适配器支持的广告格式实现这些方法。
加载方法是在界面线程上调用的,并且是在您提供信号的同一适配器实例上调用的。此方法为您提供以下参数:
MediationAdConfiguration- 包含您的 SDK 加载出价胜出的广告所需的参数,例如出价响应和发布商在 AdMob 界面中配置的所有凭据。一个
MediationAdLoadCallback对象,用于在加载成功或失败时通知 Google Mobile Ads SDK (Legacy) 。
SDK 加载广告后,调用 mediationAdLoadCallback.onSuccess()。如果广告加载失败,请使用说明所发生错误的字符串调用 mediationAdLoadCallback.onFailure()。
mediationAdLoadCallback.onSuccess() 方法要求您传入一个对象,向 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 Google Mobile Ads SDK (Legacy).
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 Mobile Ads SDK (Legacy) 通知所有展示生命周期事件,以便这些事件可以转发给 发布商。无论是哪个广告联盟投放广告,发布商都会希望在特定时间收到这些回调函数,因此务必在适当时间尽可能多地调用这些回调函数,以便 Google Mobile Ads SDK (Legacy) 能将其转发给发布商。
适配器应在适用情况下调用以下事件:
| 所有格式通用 | |
|---|---|
| 方法 | 调用时间 |
reportAdClicked()
|
广告被点击。 |
reportAdImpression()
|
广告呈现了展示。 |
onAdOpened()
|
广告呈现了全屏视图。 |
onAdClosed()
|
广告的全屏视图已关闭。 |
onAdLeftApplication()
|
广告导致用户离开应用。 |
| 激励广告 | |
onRewarded()
|
用户获得了奖励。 |
| 视频回调(激励广告和原生广告) | |
onVideoStarted()
|
广告的视频已开始播放。 |
onVideoCompleted()
|
广告的视频已播放完毕。 |
适配器在调用 mediationAdLoadCallback.onSuccess() 后会收到 MediationAdLoadCallback<MediationAdT, MediationAdCallbackT>
对象。适配器应保留此对象,并使用它来调用广告上发生的展示事件。
通常,这类事件大都由您广告联盟的 SDK 提供支持。适配器的作用只是将回调函数从您的广告联盟 SDK 映射到 Google Mobile Ads SDK (Legacy)。
以下示例演示了如何将回调函数从您 SDK 的广告监听器转发至 Google Mobile Ads SDK (Legacy):
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();
}
}
});
跟踪原生广告展示所必需的素材资源
Google Mobile Ads SDK (Legacy) 当原生广告的 1 像素可见时,会记录该广告的展示。如果您的广告联盟 SDK 要求显示特定素材资源才能算作有效展示,您的出价工具可以在出价响应中指明这些必需的原生广告素材资源。Google Mobile Ads SDK (Legacy) 然后,验证 必需的原生广告素材资源是否已展示,然后再记录展示。
如需详细了解如何在出价 响应中指定其他必需的素材资源,请参阅有关必需原生广告素材资源 的文档。
显示广告错误
对于全屏广告格式(例如插页式广告和激励广告),您需要在加载成功时执行的回调函数中实现
MediationInterstitialAd
或 MediationRewardedAd
,以便 Google Mobile Ads SDK (Legacy) 可以要求您的适配器展示广告。
Google Mobile Ads SDK (Legacy) 预计,如果适配器成功加载了广告, 则当发布商要求展示广告时,该广告已准备就绪。这意味着,每次展示调用都应产生一次展示。
不过,在某些特殊情况下,您可能无法展示广告。如果您
无法展示广告,请调用
onAdFailedToShow()
回调以取消展示。
下表说明了展示回调函数对全屏广告格式的展示记录结果有何影响:
| 回调 | 结果 |
|---|---|
| onAdOpened() | Impression recorded
|
| onAdFailedToShow() | Impression failure1
|
| 在几秒钟内未调用上述任何回调 | Impression recorded
|
1 对于失败的展示,您的广告联盟无需为此次展示付费,但这会影响您的可结算事件率价目调整。如需了解详情,请参阅出价请求 信号。
以下模拟示例展示了加载/展示生命周期,其中广告展示调用可能会导致失败。
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, ...);
}
}