原生廣告自訂事件

必要條件

完成自訂事件設定

請求原生廣告

當瀑布式中介鏈中到達自訂事件明細時,系統會根據您在建立自訂事件時提供的類別名稱,呼叫 loadNativeAd() 方法。在本例中,該方法位於 SampleCustomEvent 中,然後呼叫 SampleNativeCustomEventLoader 中的 loadNativeAd() 方法。

如要要求原生廣告,請建立或修改可延伸 Adapter 的類別,以便實作 loadNativeAd()。如果已存在可擴充 Adapter 的類別,請在該類別中實作 loadNativeAd()。此外,請建立新類別來實作 UnifiedNativeAdMapper

自訂事件範例中,SampleCustomEvent 會擴充 Adapter 類別,然後委派至 SampleNativeCustomEventLoader

Java

package com.google.ads.mediation.sample.customevent;

import com.google.android.gms.ads.mediation.Adapter;
import com.google.android.gms.ads.mediation.MediationAdConfiguration;
import com.google.android.gms.ads.mediation.MediationAdLoadCallback;

import com.google.android.gms.ads.mediation.MediationNativeAdCallback;
...
public class SampleCustomEvent extends Adapter {
  private SampleNativeCustomEventLoader nativeLoader;

  @Override
  public void loadNativeAd(
      @NonNull MediationNativeAdConfiguration adConfiguration,
      @NonNull MediationAdLoadCallback<UnifiedNativeAdMapper, MediationNativeAdCallback> callback) {
    nativeLoader = new SampleNativeCustomEventLoader(adConfiguration, callback);
    nativeLoader.loadAd();
  }
}

SampleNativeCustomEventLoader 負責下列工作:

  • 載入原生廣告。

  • 實作 UnifiedNativeAdMapper 類別。

  • 接收並回報廣告事件回呼至 Google Mobile Ads SDK。

廣告設定中會納入 AdMob UI 中定義的選用參數。您可以透過 adConfiguration.getServerParameters().getString(MediationConfiguration.CUSTOM_EVENT_SERVER_PARAMETER_FIELD) 存取這個參數。這個參數通常是將廣告物件例項化時,廣告聯播網 SDK 所需的廣告單元 ID。

Java

package com.google.ads.mediation.sample.customevent;

import com.google.android.gms.ads.mediation.Adapter;
import com.google.android.gms.ads.mediation.MediationNativeAdConfiguration;
import com.google.android.gms.ads.mediation.MediationAdLoadCallback;
import com.google.android.gms.ads.mediation.MediationNativeAdCallback;
...

public class SampleNativeCustomEventLoader extends SampleNativeAdListener {
  /** Configuration for requesting the native ad from the third-party network. */
  private final MediationNativeAdConfiguration mediationNativeAdConfiguration;

  /** Callback that fires on loading success or failure. */
  private final MediationAdLoadCallback<UnifiedNativeAdMapper, MediationNativeAdCallback>
      mediationAdLoadCallback;

  /** Callback for native ad events. */
  private MediationNativeAdCallback nativeAdCallback;

  /** Constructor */
  public SampleNativeCustomEventLoader(
      @NonNull MediationNativeAdConfiguration mediationNativeAdConfiguration,
      @NonNull MediationAdLoadCallback<MediationNativeAd, MediationNativeAdCallback>
              mediationAdLoadCallback) {
    this.mediationNativeAdConfiguration = mediationNativeAdConfiguration;
    this.mediationAdLoadCallback = mediationAdLoadCallback;
  }

  /** Loads the native ad from the third-party ad network. */
  public void loadAd() {
    // Create one of the Sample SDK's ad loaders to request ads.
    Log.i("NativeCustomEvent", "Begin loading native ad.");
    SampleNativeAdLoader loader =
        new SampleNativeAdLoader(mediationNativeAdConfiguration.getContext());

    // All custom events have a server parameter named "parameter" that returns
    // back the parameter entered into the UI when defining the custom event.
    String serverParameter = mediationNativeAdConfiguration
        .getServerParameters()
        .getString(MediationConfiguration
        .CUSTOM_EVENT_SERVER_PARAMETER_FIELD);
    Log.d("NativeCustomEvent", "Received server parameter.");

    loader.setAdUnit(serverParameter);

    // Create a native request to give to the SampleNativeAdLoader.
    SampleNativeAdRequest request = new SampleNativeAdRequest();
    NativeAdOptions options = mediationNativeAdConfiguration.getNativeAdOptions();
    if (options != null) {
      // If the NativeAdOptions' shouldReturnUrlsForImageAssets is true, the adapter should
      // send just the URLs for the images.
      request.setShouldDownloadImages(!options.shouldReturnUrlsForImageAssets());

      request.setShouldDownloadMultipleImages(options.shouldRequestMultipleImages());
      switch (options.getMediaAspectRatio()) {
        case NativeAdOptions.NATIVE_MEDIA_ASPECT_RATIO_LANDSCAPE:
          request.setPreferredImageOrientation(SampleNativeAdRequest.IMAGE_ORIENTATION_LANDSCAPE);
          break;
        case NativeAdOptions.NATIVE_MEDIA_ASPECT_RATIO_PORTRAIT:
          request.setPreferredImageOrientation(SampleNativeAdRequest.IMAGE_ORIENTATION_PORTRAIT);
          break;
        case NativeAdOptions.NATIVE_MEDIA_ASPECT_RATIO_SQUARE:
        case NativeAdOptions.NATIVE_MEDIA_ASPECT_RATIO_ANY:
        case NativeAdOptions.NATIVE_MEDIA_ASPECT_RATIO_UNKNOWN:
        default:
          request.setPreferredImageOrientation(SampleNativeAdRequest.IMAGE_ORIENTATION_ANY);
      }
    }

    loader.setNativeAdListener(this);

    // Begin a request.
    Log.i("NativeCustomEvent", "Start fetching native ad.");
    loader.fetchAd(request);
  }
}

視廣告是否成功擷取或發生錯誤而定,您可以呼叫 onSuccess()onFailure()。系統會傳入實作 MediationNativeAd 的類別執行個體來呼叫 onSuccess()

一般來說,這些方法是在轉接程式實作的第三方 SDK 中實作。在本例中,Sample SDK 具有含有相關回呼的 SampleAdListener

Java

@Override
public void onNativeAdFetched(SampleNativeAd ad) {
  SampleUnifiedNativeAdMapper mapper = new SampleUnifiedNativeAdMapper(ad);
  mediationNativeAdCallback = mediationAdLoadCallback.onSuccess(mapper);
}

@Override
public void onAdFetchFailed(SampleErrorCode errorCode) {
  mediationAdLoadCallback.onFailure(SampleCustomEventError.createSampleSdkError(errorCode));
}

地圖原生廣告

不同的 SDK 都有各自的原生廣告格式。例如,一個可能會傳回包含「title」欄位的物件,而另一個可能會傳回「headline」欄位。此外,追蹤曝光和處理點擊的方法可能因 SDK 而異。

UnifiedNativeAdMapper 負責調和這些差異,並調整經中介的 SDK 原生廣告物件,以符合 Google Mobile Ads SDK 預期的介面。自訂事件應擴充這個類別,建立專屬於中介服務 SDK 的對應工具。以下是我們的自訂事件專案範例廣告對應工具範例:

Java

package com.google.ads.mediation.sample.customevent;

import com.google.android.gms.ads.mediation.UnifiedNativeAdMapper;
import com.google.android.gms.ads.nativead.NativeAd;
...

public class SampleUnifiedNativeAdMapper extends UnifiedNativeAdMapper {

  private final SampleNativeAd sampleAd;

  public SampleUnifiedNativeAdMapper(SampleNativeAd ad) {
    sampleAd = ad;
    setHeadline(sampleAd.getHeadline());
    setBody(sampleAd.getBody());
    setCallToAction(sampleAd.getCallToAction());
    setStarRating(sampleAd.getStarRating());
    setStore(sampleAd.getStoreName());
    setIcon(
        new SampleNativeMappedImage(
            ad.getIcon(), ad.getIconUri(), SampleCustomEvent.SAMPLE_SDK_IMAGE_SCALE));
    setAdvertiser(ad.getAdvertiser());

    List<NativeAd.Image> imagesList = new ArrayList<NativeAd.Image>();
    imagesList.add(new SampleNativeMappedImage(ad.getImage(), ad.getImageUri(),
        SampleCustomEvent.SAMPLE_SDK_IMAGE_SCALE));
    setImages(imagesList);

    if (sampleAd.getPrice() != null) {
      NumberFormat formatter = NumberFormat.getCurrencyInstance();
      String priceString = formatter.format(sampleAd.getPrice());
      setPrice(priceString);
    }

    Bundle extras = new Bundle();
    extras.putString(SampleCustomEvent.DEGREE_OF_AWESOMENESS, ad.getDegreeOfAwesomeness());
    this.setExtras(extras);

    setOverrideClickHandling(false);
    setOverrideImpressionRecording(false);

    setAdChoicesContent(sampleAd.getInformationIcon());
  }

  @Override
  public void recordImpression() {
    sampleAd.recordImpression();
  }

  @Override
  public void handleClick(View view) {
    sampleAd.handleClick(view);
  }

  // The Sample SDK doesn't do its own impression/click tracking, instead relies on its
  // publishers calling the recordImpression and handleClick methods on its native ad object. So
  // there's no need to pass a reference to the View being used to display the native ad. If
  // your mediated network does need a reference to the view, the following method can be used
  // to provide one.

  @Override
  public void trackViews(View containerView, Map<String, View> clickableAssetViews,
      Map<String, View> nonClickableAssetViews) {
    super.trackViews(containerView, clickableAssetViews, nonClickableAssetViews);
    // If your ad network SDK does its own impression tracking, here is where you can track the
    // top level native ad view and its individual asset views.
  }

  @Override
  public void untrackView(View view) {
    super.untrackView(view);
    // Here you would remove any trackers from the View added in trackView.
  }
}

我們現在來仔細查看建構函式程式碼。

保留對中介原生廣告物件的參照

建構函式會接受 SampleNativeAd 參數,也就是 Sample SDK 用於原生廣告的原生廣告類別。對應程式需要參照經過調解的廣告,才能傳遞點擊和曝光事件。SampleNativeAd 會儲存為本機變數。

設定對應的素材資源屬性

建構函式會使用 SampleNativeAd 物件填入 UnifiedNativeAdMapper 中的素材資源。

這個程式碼片段會取得經仲介的廣告價格資料,並用於設定對應器的價格:

Java

if (sampleAd.getPrice() != null) {
    NumberFormat formatter = NumberFormat.getCurrencyInstance();
    String priceString = formatter.format(sampleAd.getPrice());
    setPrice(priceString);
}

在這個範例中,中介廣告會將價格儲存為 double,而 AdMob 會為相同素材資源使用 String。轉譯器負責處理這類轉換。

地圖圖片素材資源

對應圖片資產比對應 doubleString 等資料類型更為複雜。圖片可能會自動下載,或以網址值的形式傳回。他們的像素與 dpi 比例也可能不同。

為協助您管理這些詳細資料,Google Mobile Ads SDK 提供 NativeAd.Image 類別。您需要建立 UnifiedNativeAdMapper 的子類別來對應經中介的原生廣告,同樣地,您也應在對應圖片素材資源時建立 NativeAd.Image 的子類別。

以下是自訂事件的 SampleNativeMappedImage 類別範例:

Java

public class SampleNativeMappedImage extends NativeAd.Image {

  private Drawable drawable;
  private Uri imageUri;
  private double scale;

  public SampleNativeMappedImage(Drawable drawable, Uri imageUri, double scale) {
    this.drawable = drawable;
    this.imageUri = imageUri;
    this.scale = scale;
  }

  @Override
  public Drawable getDrawable() {
    return drawable;
  }

  @Override
  public Uri getUri() {
    return imageUri;
  }

  @Override
  public double getScale() {
    return scale;
  }
}

SampleNativeAdMapper 會在這個行中使用對應的圖片類別,設定對應器的圖示圖片素材資源:

Java

setIcon(new SampleNativeMappedImage(ad.getAppIcon(), ad.getAppIconUri(),
    SampleCustomEvent.SAMPLE_SDK_IMAGE_SCALE));

在 extras Bundle 中新增欄位

部分經仲介的 SDK 會提供 AdMob 原生廣告格式以外的額外素材資源。UnifiedNativeAdMapper 類別包含 setExtras() 方法,用於將這些資產傳遞給發布者。SampleNativeAdMapper 會將此值用於範例 SDK 的「degree of awesomeness」素材資源:

Java

Bundle extras = new Bundle();
extras.putString(SampleCustomEvent.DEGREE_OF_AWESOMENESS, ad.getDegreeOfAwesomeness());
this.setExtras(extras);

發布商可以使用 NativeAd 類別的 getExtras() 方法擷取資料。

AdChoices

您的自訂事件負責在 UnifiedNativeAdMapper 上使用 setAdChoicesContent() 方法提供 AdChoices 圖示。以下來自 SampleNativeAdMapper 的程式碼片段,說明如何提供 AdChoices 圖示:

Java

public SampleNativeAdMapper(SampleNativeAd ad) {
    ...
    setAdChoicesContent(sampleAd.getInformationIcon());
}

曝光和點擊事件

Google Mobile Ads SDK 和中介 SDK 都需要知道曝光或點擊的發生時間,但只需要一個 SDK 就能追蹤這些事件。自訂事件可以使用兩種不同方法,具體取決於中介 SDK 是否支援自行追蹤曝光和點擊。

使用 Google Mobile Ads SDK 追蹤點擊和曝光

如果中介 SDK 不會自行執行曝光和點擊追蹤,但提供記錄點擊和曝光的方法,Google Mobile Ads SDK 便可追蹤這些事件並通知轉接程式。UnifiedNativeAdMapper 類別包含兩種方法:recordImpression()handleClick()。自訂事件可以實作,在中介服務的原生廣告物件上呼叫對應的方法:

Java

@Override
public void recordImpression() {
  sampleAd.recordImpression();
}

@Override
public void handleClick(View view) {
  sampleAd.handleClick(view);
}

由於 SampleNativeAdMapper 會保留對範例 SDK 原生廣告物件參照,因此可對該物件呼叫適當的方法,以回報點擊或曝光次數。請注意,handleClick() 方法會使用單一參數:與接收點擊的原生廣告素材資源相對應的 View 物件。

使用中介服務 SDK 追蹤點擊和曝光

部分中介 SDK 可能會自行追蹤點擊和曝光。在這種情況下,您應在 UnifiedNativeAdMapper 的建構函式中進行以下兩個呼叫,藉此覆寫預設的點擊和曝光追蹤:

Java

setOverrideClickHandling(true);
setOverrideImpressionRecording(true);

您必須使用覆寫點擊和曝光追蹤的自訂事件,才能將 onAdClicked()onAdImpression() 事件回報給 Google Mobile Ads SDK。

為了追蹤曝光和點擊,經仲介的 SDK 可能需要存取檢視畫面,才能啟用追蹤功能。自訂事件應覆寫 trackViews() 方法,並使用該方法將原生廣告的檢視畫面傳遞至中介 SDK 以便追蹤。自訂事件範例專案 (本指南的程式碼片段取自該專案) 中的範例 SDK 並未使用這項做法,但如果使用了,自訂事件程式碼會長這樣:

Java

@Override
public void trackViews(View containerView,
    Map<String, View> clickableAssetViews,
    Map<String, View> nonClickableAssetViews) {
  sampleAd.setNativeAdViewForTracking(containerView);
}

如果經仲介的 SDK 支援追蹤個別資產,則可查看 clickableAssetViews 內部,瞭解哪些檢視畫面應設為可點擊。此對應的索引鍵是 NativeAdAssetNames 中的素材資源名稱。UnifiedNativeAdMapper 提供對應的 untrackView() 方法,自訂事件可覆寫該方法,釋放對檢視區塊的任何參照,並將其與原生廣告物件解除關聯。

將中介服務事件轉送至 Google Mobile Ads SDK

您可以在 MediationNativeAdCallback 說明文件中找到中介服務支援的所有回呼。

請務必讓自訂事件盡可能轉送這些回呼,確保應用程式從 Google Mobile Ads SDK 接收這些對等事件。以下是使用回呼的範例:

如此就能完成原生廣告的自訂事件導入。您可以在 GitHub 上取得完整範例。