出價轉接程式開發

本指南適用於希望建立出價轉接程式的廣告聯播網,以在 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 使用者介面中設定的任何憑證。

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

當 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 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 Mobile Ads SDK,這樣 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();
        }
    }
});

原生廣告曝光追蹤的必要素材資源

Google Mobile Ads SDK 會在廣告顯示 1 像素時記錄原生廣告的曝光。如果您的廣告聯播網 SDK 需要顯示特定的素材資源才能顯示有效曝光,出價工具可以在出價回應中指出這些必要的原生素材資源。接著,Google Mobile Ads SDK 會在記錄曝光前,驗證是否顯示了必要的原生素材資源。

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

顯示廣告錯誤

如果是全螢幕格式 (例如插頁式廣告和獎勵廣告),在成功載入回呼時,您需要導入 MediationInterstitialAdMediationRewardedAd ,讓 Google Mobile Ads SDK 要求轉接程式顯示廣告。

根據 Google Mobile Ads SDK 的情況,如果轉接程式成功載入廣告,廣告就會在發布商要求顯示時隨時顯示。也就是說,每次呼叫節目呼叫都會產生一次曝光。

不過,某些極端情況下您可能無法顯示廣告。如果您無法顯示廣告,請呼叫 onAdFailedToShow() 回呼以取消曝光。

下表說明顯示回呼對全螢幕廣告格式的曝光記錄有何影響:

Callback 結果
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, ...);
  }
}