出價轉接程式開發

本指南適用於希望建立出價轉接程式,參與 Google 中介服務即時出價 (RTB) 的廣告聯播網。發布商請參閱發布商中介服務操作說明。

出價轉接程式是整合的用戶端部分。廣告聯播網 SDK 可透過轉接程式,與 Google Mobile Ads SDK 溝通,載入出價方放送的廣告。

如要讓出價功能正常運作,轉接程式必須處理初始化、收集信號、載入廣告,以及傳遞廣告生命週期事件。本指南將逐步說明如何導入轉接程式,來處理這些作業。

出價轉接程式的工作流程

初始化

以下詳細說明轉接程式的完整「要求-回應-顯示」生命週期流程:

轉接程式負責下列工作流程:

  • 步驟 4 至 7:初始化轉接程式,並在完成後回呼 Google Mobile Ads SDK。

  • 步驟 10 至 13:從廣告聯播網 SDK 收集信號,傳送至出價工具參與 RTB 要求,再轉送至 Google Mobile Ads SDK。

  • 步驟 18 至 21:如果出價工具傳回得標出價,請根據出價工具的回應載入廣告。載入完成後,通知 Google Mobile Ads SDK 廣告已載入。

  • 步驟 23 和後續步驟:廣告顯示時,通知 Google Mobile Ads SDK 曝光、點擊事件,以及廣告顯示生命週期內的其他廣告事件。

導入出價轉接程式

如要為 Google Mobile Ads 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 Mobile Ads SDK 會同時向所有參與出價的轉接程式要求信號。請尊循這段時間,並限制 UI 執行緒呼叫。任何轉接程式或 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 會呼叫轉接程式載入最高出價廣告,並傳遞 SDK 載入該廣告所需的出價方傳回資料。

系統呼叫的確切載入方法,取決於這項要求所屬的廣告格式:

廣告格式 載入方法
橫幅 loadBannerAd()
插頁式廣告 loadInterstitialAd()
獎勵廣告 loadRewardedAd()

為轉接程式支援的廣告格式導入這些方法。

載入方法會在 UI 執行緒上呼叫,與您提供信號的轉接程式例項相同。這個方法會提供下列參數:

  • MediationAdConfiguration,包含 SDK 載入得標出價廣告所需的參數,例如出價回應,以及發布商在 AdMob 使用者介面設定的任何憑證。

  • MediationAdLoadCallback 物件,用於在載入成功或失敗時通知 Google Mobile Ads SDK。

SDK 載入廣告後,請呼叫 mediationAdLoadCallback.onSuccess()。如果事件廣告載入失敗,請呼叫 mediationAdLoadCallback.onFailure(),並提供說明發生錯誤的字串。

mediationAdLoadCallback.onSuccess() 方法需要傳入符合 Google Mobile Ads 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.
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 任何顯示生命週期事件,以便轉送給發布商。無論哪個廣告聯播網放送廣告,發布商都會在特定時間收到這些回呼,因此請務必盡可能在適當時間多叫用這些回呼,讓 Google Mobile Ads SDK 將回呼轉送給發布商。

在適當情況下,轉接程式應叫用下列事件:

所有格式皆適用
方法 呼叫時機
reportAdClicked() 廣告獲得點擊。
reportAdImpression() 顯示的廣告已計入曝光次數。
onAdOpened() 廣告以全螢幕顯示。
onAdClosed() 廣告的全螢幕顯示已關閉。
onAdLeftApplication() 廣告導致使用者離開應用程式。
獎勵廣告
onRewarded() 使用者獲得獎勵。
影片回呼 (獎勵和原生廣告)
onVideoStarted() 廣告影片已開始。
onVideoCompleted() 廣告影片已播放完畢。

轉接程式會在呼叫 mediationAdLoadCallback.onSuccess() 時,取得 MediationAdLoadCallback<MediationAdT, MediationAdCallbackT> 物件。轉接程式應保留這個物件,並用來叫用廣告上發生的顯示事件。

通常,這些事件大多是由廣告聯播網的 SDK 觸發。轉接程式的角色很簡單,就是將廣告聯播網 SDK 的回呼對應至 Google Mobile Ads SDK。

下列範例說明如何將回呼從 SDK 的廣告監聽器轉送至 Google Mobile Ads 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 Mobile Ads SDK 就會記錄一次曝光次數。如果廣告聯播網 SDK 要求顯示特定素材資源,才能算入有效曝光,出價工具可在出價回應中標明必要的原生素材資源。接著,Google Mobile Ads SDK 會在記錄曝光次數前,先驗證必要原生素材資源是否已顯示。

請參閱原生必要素材資源說明文件,進一步瞭解如何在出價回應中,指定其他必要素材資源。

顯示廣告錯誤

如果是插頁式和獎勵廣告等全螢幕格式,您會在成功載入回呼中提供 MediationInterstitialAdMediationRewardedAd 的導入,讓 Google Mobile Ads SDK 要求您的轉接程式顯示廣告。

Google Mobile Ads SDK 預期,若轉接程式成功載入廣告,發布商要求顯示廣告時,廣告應準備就緒。也就是說,每次顯示呼叫都應產生曝光次數。

不過,在某些特殊情況下,您可能無法顯示廣告,這時請呼叫 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, ...);
  }
}