原生廣告自訂事件

必要條件

完成自訂事件設定

請求原生廣告

當刊登序列中介服務鏈執行到自訂事件委刊項,系統會以您在建立自訂事件時指定的類別名稱,呼叫 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 (Beta 版)。

在 AdMob UI 中定義的選用參數會包含在廣告設定,使用 adConfiguration.getServerParameters().getString(MediationConfiguration.CUSTOM_EVENT_SERVER_PARAMETER_FIELD) 即可存取。這項參數通常是廣告單元 ID,廣告聯播網 SDK 在例項化廣告物件時會用到。

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 回呼中執行。以本例來說,範例 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 (Beta 版) 預期的介面。自訂事件應擴充這個類別,才能建立中介服務 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 參數,也就是範例 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 (Beta 版) 提供 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));

在額外資訊套組新增欄位

某些中介 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

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

Java

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

曝光和點擊事件

Google Mobile Ads SDK (Beta 版) 和中介 SDK 都需要知道何時發生曝光或點擊,但只有一個 SDK 需要追蹤這些事件。自訂事件有兩種方法可使用,具體取決於中介服務 SDK 是否支援自行追蹤曝光和點擊。

使用 Google Mobile Ads SDK (Beta 版) 追蹤點擊和曝光

如果中介服務 SDK 不會自行追蹤曝光和點擊,但支援記錄點擊和曝光的方法,Google Mobile Ads SDK (Beta 版) 就能追蹤這些事件並通知轉接程式。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);

如果自訂事件會覆寫點擊和曝光追蹤功能,就必須向 Google Mobile Ads SDK 回報 onAdClicked()onAdImpression() 事件。

如要追蹤曝光和點擊,中介服務 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 (Beta 版)

如要查看中介服務支援的所有回呼,請參閱MediationNativeAdCallback說明文件

自訂事件應盡量將這些回呼轉送至 Google Mobile Ads SDK (Beta 版),這樣應用程式才能收到相應的事件通知。以下是回呼使用範例:

到這裡就完成原生廣告的自訂事件導入設定!如需完整範例,請前往 GitHub