네이티브 광고 맞춤 이벤트

기본 요건

맞춤 이벤트 설정을 완료합니다.

네이티브 광고 요청

폭포식 구조 미디에이션 체인에서 맞춤 이벤트 광고 항목에 도달하면 맞춤 이벤트를 만들 때 제공한 클래스 이름에 loadNativeAd() 메서드가 호출됩니다. 이 경우 이 메서드는 SampleCustomEvent에 있고 SampleNativeCustomEventLoader에서 loadNativeAd() 메서드를 호출합니다.

네이티브 광고를 요청하려면 Adapter를 확장하여 loadNativeAd()를 구현하는 클래스를 만들거나 수정하세요. Adapter를 확장하는 클래스가 이미 있다면 이 클래스에 loadNativeAd()를 구현합니다. 또한 UnifiedNativeAdMapper를 구현할 새 클래스를 만듭니다.

맞춤 이벤트 예에서 SampleCustomEventAdapter 클래스를 확장한 다음 SampleNativeCustomEventLoader에 위임합니다.

자바

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 모바일 광고 SDK에 광고 이벤트 콜백 수신 및 보고

AdMob UI에 정의된 선택적 매개변수는 광고 구성에 포함됩니다. 이 매개변수는 adConfiguration.getServerParameters().getString(MediationConfiguration.CUSTOM_EVENT_SERVER_PARAMETER_FIELD)를 통해 액세스할 수 있습니다. 이 매개변수는 일반적으로 광고 네트워크 SDK가 광고 객체를 인스턴스화할 때 요구하는 광고 단위 식별자입니다.

자바

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()를 호출합니다. onSuccess()MediationNativeAd를 구현하는 클래스의 인스턴스를 전달하여 호출됩니다.

일반적으로 이러한 메서드는 어댑터가 구현하는 서드 파티 SDK의 콜백 내에서 구현됩니다. 이 예시의 샘플 SDK에는 관련 콜백이 있는 SampleAdListener가 있습니다.

자바

@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마다 고유한 네이티브 광고 형식이 있습니다. 예를 들어 '제목' 필드가 포함된 객체를 반환하는 SDK와 '광고 제목' 필드가 있는 SDK가 있을 수 있습니다. 또한 노출을 추적하고 클릭을 처리하는 데 사용되는 메서드가 SDK마다 다를 수 있습니다.

UnifiedNativeAdMapper는 이러한 차이를 조정하고 미디에이션 대상 SDK의 네이티브 광고 객체를 Google 모바일 광고 SDK에서 예상하는 인터페이스와 일치하도록 조정합니다. 맞춤 이벤트는 이 클래스를 확장하여 미디에이션된 SDK에 해당하는 자체 매퍼를 만들어야 합니다. 다음은 예시 맞춤 이벤트 프로젝트에 포함된 광고 매퍼의 예입니다.

자바

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.
  }
}

이제 생성자 코드를 자세히 살펴보겠습니다.

미디에이션 대상인 네이티브 광고 객체에 대한 참조 보유하기

생성자는 샘플 SDK에서 네이티브 광고에 사용하는 네이티브 광고 클래스인 SampleNativeAd 매개변수를 허용합니다. 매퍼는 미디에이션 대상 광고에 대한 참조가 있어야 클릭 및 노출 이벤트를 전달할 수 있습니다. SampleNativeAd는 로컬 변수로 저장됩니다.

매핑된 애셋 속성 설정

생성자는 SampleNativeAd 객체를 사용하여 UnifiedNativeAdMapper에 애셋을 채웁니다.

다음 스니펫은 미디에이션 대상 광고의 가격 데이터를 가져와서 매퍼의 가격을 설정하는 데 사용합니다.

자바

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

이 예에서 미디에이션 대상 광고는 가격을 double로 저장하지만, AdMob에서는 같은 애셋에 String을 사용합니다. 이러한 변환을 매퍼에서 처리해야 합니다.

이미지 확장 소재 매핑하기

이미지 애셋 매핑은 double 또는 String과 같은 데이터 유형을 매핑하는 것보다 더 복잡합니다. 이미지는 자동으로 다운로드될 수도 있고 URL 값으로 반환될 수도 있습니다. 픽셀의 dpi 배율 또한 달라질 수 있습니다.

이러한 세부정보를 관리할 수 있도록 Google 모바일 광고 SDK에서 NativeAd.Image 클래스를 제공합니다. 미디에이션된 네이티브 광고를 매핑하기 위해 UnifiedNativeAdMapper의 하위 클래스를 만들어야 하는 것과 거의 마찬가지로, 이미지 애셋을 매핑할 때도 NativeAd.Image의 하위 클래스를 만들어야 합니다.

다음은 맞춤 이벤트의 SampleNativeMappedImage 클래스의 예입니다.

자바

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는 이 줄에서 매핑된 이미지 클래스를 사용하여 매퍼의 아이콘 이미지 애셋을 설정합니다.

자바

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

추가 항목 번들에 필드 추가

미디에이션된 SDK 중 일부는 AdMob 네이티브 광고 형식에 포함되지 않는 애셋을 추가로 제공합니다. UnifiedNativeAdMapper 클래스에는 이러한 에셋을 게시자에게 전달하는 데 사용되는 setExtras() 메서드가 포함됩니다. SampleNativeAdMapper는 샘플 SDK의 'degree of awesomeness' 애셋에 이 메서드를 사용합니다.

자바

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

게시자는 NativeAd 클래스의 getExtras() 메서드를 사용하여 데이터를 가져올 수 있습니다.

AdChoices

맞춤 이벤트에서 UnifiedNativeAdMappersetAdChoicesContent() 메서드를 사용하여 AdChoices 아이콘을 제공해야 합니다. 다음은 AdChoices 아이콘을 표시하는 방법을 보여주는 SampleNativeAdMapper의 스니펫입니다.

자바

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

노출 및 클릭 이벤트

노출 또는 클릭이 발생한 경우 Google 모바일 광고 SDK와 미디에이션된 SDK 모두 알아야 하지만 하나의 SDK에서만 이러한 이벤트를 추적하면 됩니다. 맞춤 이벤트는 미디에이션된 SDK에서 자체적으로 노출을 추적할 수 있는지 여부에 따라 두 가지 방식을 사용할 수 있습니다.

Google 모바일 광고 SDK를 사용하여 클릭 및 노출 추적하기

미디에이션된 SDK에서 자체적으로 노출 및 클릭 추적을 실행하지 않지만 클릭 및 노출을 기록하는 메서드를 제공하는 경우 Google 모바일 광고 SDK에서 이러한 이벤트를 추적하여 어댑터에 알릴 수 있습니다. UnifiedNativeAdMapper 클래스에는 맞춤 이벤트가 미디에이션된 네이티브 광고 객체에서 해당 메서드를 호출하기 위해 구현할 수 있는 두 가지 메서드인 recordImpression()handleClick()이 포함되어 있습니다.

자바

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

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

SampleNativeAdMapper는 샘플 SDK의 네이티브 광고 객체에 대한 참조를 보유하므로 해당 객체에 대해 적절한 메서드를 호출하여 클릭 또는 노출을 보고할 수 있습니다. handleClick() 메서드는 클릭이 발생한 네이티브 광고 애셋에 해당하는 View 객체인 단일 매개변수를 사용합니다.

미디에이션된 SDK를 사용하여 클릭 및 노출 추적하기

일부 미디에이션된 SDK는 자체적으로 클릭 및 노출을 추적하려고 할 수도 있습니다. 이 경우 UnifiedNativeAdMapper의 생성자에서 다음 두 메서드를 호출하여 기본 클릭 및 노출 추적을 재정의해야 합니다.

자바

setOverrideClickHandling(true);
setOverrideImpressionRecording(true);

클릭 및 노출 추적을 재정의하는 맞춤 이벤트는 onAdClicked()onAdImpression() 이벤트를 Google 모바일 광고 SDK에 보고해야 합니다.

노출수 및 클릭수를 추적하려면 미디에이션된 SDK에 추적을 사용 설정하기 위해 뷰에 대한 액세스 권한이 필요할 수 있습니다. 맞춤 이벤트는 trackViews() 메서드를 재정의하고 이 메서드를 사용하여 네이티브 광고의 보기를 추적할 미디에이션된 SDK에 전달해야 합니다. 이 가이드의 코드 스니펫을 발췌한 맞춤 이벤트 프로젝트 예의 샘플 SDK는 이 방식을 사용하지 않지만, 이 방식을 사용한다면 맞춤 이벤트 코드는 다음과 같았을 것입니다.

자바

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

미디에이션 대상 SDK에서 개별 애셋 추적을 지원하는 경우에는 어떤 뷰를 클릭이 가능하도록 설정해야 하는지를 clickableAssetViews에서 확인할 수 있습니다. 이 맵은 NativeAdAssetNames의 애셋 이름을 키로 하여 지정됩니다. UnifiedNativeAdMapper는 맞춤 이벤트가 재정의하여 뷰에 대한 참조를 해제하고 네이티브 광고 객체와 연결을 해제할 수 있는 상응하는 untrackView() 메서드를 제공합니다.

Google 모바일 광고 SDK로 미디에이션 이벤트 전달하기

미디에이션에서 지원하는 모든 콜백은 MediationNativeAdCallback 문서에서 확인할 수 있습니다.

맞춤 이벤트가 이러한 콜백을 최대한 많이 전달하여 앱이 Google 모바일 광고 SDK에서 동등한 이벤트를 수신하도록 하는 것이 중요합니다. 다음은 콜백을 사용하는 예입니다.

네이티브 광고용 맞춤 이벤트 구현이 완료되었습니다. 전체 예시는 GitHub에서 확인할 수 있습니다.