出價轉接程式開發

本指南的適用對象:希望建立出價轉接程式,參與 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 會記錄 1 次曝光。若廣告聯播網 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, ...);
  }
}