네이티브 맞춤 이벤트

본 가이드는 AdMob 미디에이션을 사용하여 AdMob에서 지원하는 광고 네트워크가 아닌 네트워크에서 네이티브 광고를 로드하여 게재하려는 게시자를 대상으로 작성되었습니다. AdMob 미디에이션을 사용하여 배너 광고, 전면 광고 또는 보상형 디스플레이 광고를 로드하고 게재하는 방법에 대한 정보는 맞춤 이벤트를 참고하세요.

맞춤 이벤트는 다른 네트워크의 광고를 요청할 수 있는 미디에이션 어댑터 클래스입니다. 광고 단위의 미디에이션 설정에 이러한 클래스 중 하나의 이름을 추가하면 SDK에서 클래스를 인스턴스화하여 광고를 검색하는 데 사용할 수 있습니다. 네이티브 맞춤 이벤트 클래스는 다음과 같은 작업을 처리할 수 있어야 합니다.

  • 미디에이션 대상 네트워크의 네이티브 광고 요청
  • 미디에이션된 네트워크 SDK의 이벤트를 Google 모바일 광고 SDK에 전달
  • GADMediatedUnifiedNativeAd를 사용하여 미디에이션된 네이티브 광고 객체를 AdMob의 네이티브 광고 인터페이스에 매핑

각 작업에 대한 설명이 아래에 나와 있습니다. 샘플 맞춤 이벤트 프로젝트의 전체 소스는 GitHub 저장소에서도 확인할 수 있습니다.

기본 요건

AdMob 맞춤 이벤트를 구현하려면 먼저 프로젝트에 모바일 광고 SDK를 통합하세요. 광고 요청을 하는 방법 및 미디에이션의 작동 방식에 대해 알아보세요.

샘플 SDK

이 가이드에서 사용된 코드는 Google의 샘플 맞춤 이벤트 프로젝트에서 가져온 것으로, 여기에는 '샘플 SDK'가 포함되어 있습니다. 프로젝트에서 다른 광고 네트워크의 SDK를 미디에이션하는 맞춤 이벤트를 생성하는 방법을 설명하려면 미디에이션할 SDK가 필요하므로 Google에서 샘플 SDK라는 모의 SDK를 만들었습니다.

샘플 SDK에서는 광고 네트워크의 제작 SDK에 있는 클래스와 유사한 클래스를 제공합니다. 샘플 SDK에는 요청 객체(예: SampleNativeAdRequest), 광고 로더(예: SampleNativeAdLoader)와 더불어 실제 네트워크의 SDK를 시뮬레이션하는 데 사용되는 기타 클래스, 상수, 프로토콜이 포함되어 있습니다. 하지만 SDK에서 생성하는 광고는 모의 광고이며, 추가 네트워크 트래픽이 발생하지 않습니다.

네이티브 광고 요청하기

requestNativeAdWithParameter: 메서드

맞춤 이벤트 클래스는 GADCustomEventNativeAd 프로토콜을 구현해야 하며, 여기에는 Google 모바일 광고 SDK가 맞춤 이벤트에서 네이티브 광고를 요청할 때 사용하는 메서드가 포함됩니다.

Swift

func request(withParameter serverParameter: String,
                                   request: GADCustomEventRequest,
                                   adTypes: [Any],
                                   options: [Any],
                        rootViewController: UIViewController)

Objective-C

- (void)requestNativeAdWithParameter:(NSString *)serverParameter
                             request:(GADCustomEventRequest *)request
                             adTypes:(NSArray *)adTypes
                             options:(NSArray *)options
                  rootViewController:(UIViewController *)rootViewController;

이 메서드가 호출되면 맞춤 이벤트가 비동기식으로 네이티브 광고를 요청해야 합니다. requestNativeAdWithParameter:의 4가지 매개변수는 맞춤 이벤트에서 요청을 할 때 사용할 수 있는 정보를 전달합니다.

  • serverParameter: 광고 단위의 미디에이션 구성에 맞춤 이벤트를 추가할 때 각 요청과 함께 전달할 문자열 값을 입력할 수 있습니다. 이 매개변수에 이 값(일반적으로는 미디에이션된 네트워크에서 제공하는 다른 광고 단위 ID)이 포함됩니다.
  • request: 각 요청의 속성(예: 요청한 네이티브 형식)이 포함된 GADCustomEventRequest 객체입니다. GADCustomEventRequest에는 요청 시 게시자가 제공한 타겟팅 정보의 속성도 포함됩니다.
  • adTypes: 요청할 네이티브 형식을 지정하는 상수가 포함된 NSArray입니다. GADUnifiedNativeAd 객체의 경우 kGADAdLoaderAdTypeUnifiedNative를 포함해야 합니다.
  • options: 게시자의 광고 로드 환경설정을 나타내는 GADAdLoaderOptions 객체가 포함된 NSArray입니다.

요청 정보를 전달하는 매개변수 외에도 rootViewController 매개변수는 광고가 표시될 UIViewController에 대한 참조를 제공합니다.

다음은 맞춤 이벤트 프로젝트의 예에서 가져온 코드 스니펫입니다. 구현된 requestNativeAdWithParameter: 메서드가 이 코드 스니펫에 나와 있습니다.

SampleCustomEventNativeAd(발췌)

Swift

func request(withParameter serverParameter: String, request: GADCustomEventRequest, adTypes: [Any], options: [Any], rootViewController: UIViewController) {

  let adLoader = SampleNativeAdLoader()
  let sampleRequest = SampleNativeAdRequest()

  if let options = options as? [GADAdLoaderOptions] {
    for loaderOptions: GADAdLoaderOptions in options {
      if let imageOptions = loaderOptions as? GADNativeAdImageAdLoaderOptions {

        sampleRequest.shouldRequestPortraitImages =
        imageOptions.preferredImageOrientation = .portrait;
        sampleRequest.shouldRequestMultipleImages = imageOptions.shouldRequestMultipleImages
        // If the GADNativeAdImageAdLoaderOptions' disableImageLoading
        // property is YES, the adapter should send just the URLs for the images.
        sampleRequest.shouldDownloadImages = !imageOptions.disableImageLoading
      }
      else if let options = loaderOptions as? GADNativeAdViewAdOptions {
        nativeAdViewAdOptions = options
      }
    }
  }
  // This custom event uses the server parameter to carry an ad unit ID,
  // which is the most common use case.
  adLoader.adUnitID = serverParameter
  adLoader.delegate = self
  adLoader.fetchAd(sampleRequest)
}

Objective-C

- (void)requestNativeAdWithParameter:(NSString *)serverParameter
                             request:(GADCustomEventRequest *)request
                             adTypes:(NSArray *)adTypes
                             options:(NSArray *)options
                  rootViewController:(UIViewController *)rootViewController {
  SampleNativeAdLoader *adLoader = [[SampleNativeAdLoader alloc] init];
  SampleNativeAdRequest *sampleRequest = [[SampleNativeAdRequest alloc] init];

  for (GADNativeAdImageAdLoaderOptions *imageOptions in options) {
    if (![imageOptions isKindOfClass:[GADNativeAdImageAdLoaderOptions class]]) {
      continue;
    }

    sampleRequest.shouldRequestPortraitImages =
        imageOptions.preferredImageOrientation ==
        GADNativeAdImageAdLoaderOptionsOrientationPortrait;
    sampleRequest.shouldDownloadImages = !imageOptions.disableImageLoading;
    sampleRequest.shouldRequestMultipleImages = imageOptions.shouldRequestMultipleImages;
  }

  // This custom event uses the server parameter to carry an ad unit ID,
  // which is the most common use case.
  adLoader.adUnitID = serverParameter;
  adLoader.delegate = self;

  [adLoader fetchAd:sampleRequest];
}

위의 코드는 모의 '샘플 SDK'를 통해 가상의 광고 네트워크로 미디에이션하는 샘플 맞춤 이벤트입니다. 맞춤 이벤트는 requestNativeAdWithParameter: 매개변수에서 제공된 정보를 사용하여 샘플 SDK의 SampleNativeAdLoader에 광고를 요청합니다. 또한 이벤트를 샘플 SDK에서 Google 모바일 광고 SDK로 다시 전달할 수 있도록 자신을 SampleNativeAdLoader의 대리자로 할당합니다. 이 과정에 대해서는 다음 섹션에서 설명합니다.

GADAdLoaderOptions

네이티브 광고를 요청할 때 게시자는 GADAdLoaderOptions 객체의 배열을 제공하여 해당 요청의 환경설정(예: 이미지 애셋 반환 방법)을 지정합니다. 이 환경설정은 requestNativeAdWithParameter: 메서드의 매개변수 중 하나로 맞춤 이벤트에 제공됩니다. 맞춤 이벤트는 options 배열을 하나씩 반복하면서 포함된 환경설정에 따라 작동해야 합니다.

예를 들어 options 배열에 shouldDownloadImages 값이 true로 설정된 GADNativeAdImageAdLoaderOptions 객체가 포함되어 있으면 맞춤 이벤트는 URL뿐 아니라 실제 이미지 애셋을 반환해야 합니다. 이때 변경된 SDK에서 이미지의 URL만 제공하는 경우 맞춤 이벤트는 해당 URL을 사용하여 이미지 파일을 다운로드하고 해당 데이터를 게시자에게 제공해야 합니다.

모바일 광고 SDK에 이벤트 전달하기

맞춤 이벤트에서 미디에이션 대상 네트워크의 네이티브 광고를 로드하려고 할 때 다음과 같은 결과가 나올 수 있습니다. SDK가 네이티브 광고를 성공적으로 반환할 수도 있고, 오류가 발생할 수도 있으며, 게재 가능한 광고가 없다고 보고할 수도 있습니다. Google 모바일 광고 SDK는 이러한 이벤트를 인식할 수 있어야 하므로 GADCustomEventNativeAd 프로토콜에는 맞춤 이벤트가 이러한 이벤트를 전달하는 데 사용할 수 있는 GADCustomEventNativeAdDelegate 유형의 대리자가 포함되어 있습니다.

맞춤 이벤트는 '중개자' 역할도 하기 때문에 미디에이션된 SDK의 이벤트를 수신한 후 해당 GADCustomEventNativeAdDelegate 프로토콜 메시지를 대리자로 적절히 전송합니다. 맞춤 이벤트는 다음과 같은 메시지를 인식해야 합니다.

  • customEventNativeAd:didReceiveMediatedUnifiedNativeAd:: 맞춤 이벤트가 네이티브 광고 로드에 성공할 때 이 메시지를 전송해야 합니다. 이 메시지에서는 GADMediatedUnifiedNativeAd 유형의 단일 매개변수를 사용하며, 맞춤 이벤트가 이를 활용하여 방금 로드한 네이티브 광고의 '변형' 버전을 전달해야 합니다(GADMediatedUnifiedNativeAd 클래스에 대한 내용은 다음 섹션 참고).
  • customEventNativeAd:didFailToLoadWithError:: 맞춤 이벤트에서 네이티브 광고를 로드하려는 시도가 실패하면 이 메서드를 사용하여 실패를 보고해야 합니다. 이 메서드에서는 실패와 관련한 정보를 포함하는 단일 NSError 매개변수를 사용합니다.

다음은 위의 사항을 예시 맞춤 이벤트 프로젝트에서 실제로 구현한 예시입니다.

SampleCustomEventNativeAd(발췌)

Swift

extension SampleCustomEventNativeAdSwift: SampleNativeAdLoaderDelegate {

  func adLoader(_ adLoader: SampleNativeAdLoader, didReceive nativeAd: SampleNativeAd) {
    let mediatedAd = SampleMediatedNativeAdSwift(
    sampleNativeAd:nativeAd,nativeAdViewAdOptions: nativeAdViewAdOptions)
    delegate?.customEventNativeAd(self, didReceive: mediatedAd)
  }

  func adLoader(_ adLoader: SampleNativeAdLoader, didFailToLoadAdWith errorCode: SampleErrorCode) {
    let error = NSError(domain: customEventErrorDomain, code: errorCode.rawValue, userInfo: nil)
    delegate?.customEventNativeAd(self, didFailToLoadWithError: error)
  }

}

Objective-C

@interface SampleCustomEventNativeAd () <SampleNativeAdLoaderDelegate>
@end

@implementation SampleCustomEventNativeAd

@synthesize delegate;

...

#pragma mark SampleNativeAdLoaderDelegate implementation

- (void)adLoader:(SampleNativeAdLoader *)adLoader didReceiveNativeAd:(SampleNativeAd *)nativeAd {
  SampleMediatedNativeAd *mediatedAd =
      [[SampleMediatedNativeAd alloc] initWithSampleNativeAd:nativeAd
                                       nativeAdViewAdOptions:_nativeAdViewAdOptions];
  [self.delegate customEventNativeAd:self didReceiveMediatedUnifiedNativeAd:mediatedAd];
}

- (void)adLoader:(SampleNativeAdLoader *)adLoader
    didFailToLoadAdWithErrorCode:(SampleErrorCode)errorCode {
  NSError *error = [NSError errorWithDomain:customEventErrorDomain code:errorCode userInfo:nil];
  [self.delegate customEventNativeAd:self didFailToLoadWithError:error];
}

...

@end

클래스에서 샘플 SDK의 SampleNativeAdLoaderDelegate 프로토콜을 구현합니다. SampleCustomEventNativeAd.m(발췌)에서 맞춤 이벤트 클래스 자체가 SampleNativeAdLoader에 대리자로 할당되었습니다.

Swift

adLoader.delegate = self

Objective-C

adLoader.delegate = self;

이렇게 하면 샘플 SDK에서 실패 또는 성공을 보고할 때 맞춤 이벤트로 메시지를 다시 전송합니다. 그러면 맞춤 이벤트가 자체 대리자에 적절한 메시지를 전송하여 이벤트를 Google 모바일 광고 SDK에 전달합니다. 즉, Google 모바일 광고 SDK가 맞춤 이벤트를 수신하고 맞춤 이벤트가 미디에이션된 SDK를 수신하는 것입니다.

위의 adLoader:didFailToLoadAdWithErrorCode 메서드에 작동 방식의 예가 자세히 나와 있습니다. 샘플 SDK는 광고 로드에 실패하면 맞춤 이벤트에 adLoader:didFailToLoadAdWithErrorCode: 메시지를 전송합니다. 맞춤 이벤트는 샘플 SDK에서 제공한 SampleErrorCode를 사용하여 새 NSError 객체를 만든 다음 customEventNativeAd:didFailToLoadWithError: 메시지를 통해 이를 자체 대리자로 전송합니다. 이와 같이 샘플 SDK 이벤트가 Google 모바일 광고 SDK 이벤트로 변환됩니다.

네이티브 광고 매핑하기

SDK마다 고유한 네이티브 광고 형식이 있습니다. 예를 들어 '제목' 필드가 포함된 객체를 반환하는 SDK와 '제목' 필드가 있는 SDK가 있을 수 있습니다. 또한 노출을 추적하고 클릭을 처리하는 데 사용되는 메서드가 SDK마다 다를 수 있습니다. 이러한 차이점을 해소하려면 맞춤 이벤트가 미디에이션된 네트워크 SDK의 네이티브 광고 객체를 수신할 때 Google 모바일 광고 SDK에서 예상하는 인터페이스와 일치하도록 GADMediatedNativeAd의 하위 클래스를 사용하여 미디에이션된 SDK의 네이티브 광고 객체를 '매핑'해야 합니다.

AdMob의 시스템 정의 통합 네이티브 광고 형식에는 해당 GADMediatedUnifiedNativeAd 클래스가 있습니다. 맞춤 이벤트는 미디에이션된 SDK에서 제공하는 네이티브 광고 객체를 매핑하기 위해 하위 클래스를 만들어야 합니다.

다음은 예시 맞춤 이벤트 프로젝트에 포함된 매퍼 클래스의 예입니다.

Swift

class SampleMediatedUnifiedNativeAdSwift : NSObject {

    var sampleAd : SampleNativeAd
    var mappedImages = [GADNativeAdImage]()
    var mappedIcon: GADNativeAdImage?
    var extras = [String:Any]()
    var nativeAdViewAdOptions: GADNativeAdViewAdOptions?
    let adInfoView = SampleAdInfoView()
    var sampleMediaView : SampleMediaView?

    init(sampleNativeAd : SampleNativeAd, nativeAdViewAdOptions : GADNativeAdViewAdOptions?) {
      sampleAd = sampleNativeAd
      super.init()
      extras = [SampleCustomEventConstantsSwift.awesomenessKey: sampleAd.degreeOfAwesomeness ?? ""]
      if let image = sampleAd.image {
         mappedImages = [GADNativeAdImage(image : image)]
      }
      else {
         let imageUrl = URL(fileURLWithPath : sampleAd.imageURL)
         mappedImages = [GADNativeAdImage(url : imageUrl, scale : sampleAd.imageScale)]
      }
      if let icon = sampleAd.icon {
        mappedIcon = GADNativeAdImage(image : icon)
      }
      else {
       let iconURL = URL(fileURLWithPath : sampleNativeAd.iconURL)
       mappedIcon = GADNativeAdImage(url : iconURL, scale : sampleAd.iconScale)
      }
      self.nativeAdViewAdOptions = nativeAdViewAdOptions
      self.sampleMediaView = self.sampleAd.mediaView
    }
}

extension SampleMediatedUnifiedNativeAdSwift : GADMediatedUnifiedNativeAd {
    var advertiser : String? {
        return sampleAd.advertiser
    }

    var headline : String? {
      return sampleAd.headline
    }

    var images : [GADNativeAdImage]? {
      return mappedImages
    }

    var body : String? {
      return sampleAd.body
    }

    var icon : GADNativeAdImage? {
      return mappedIcon
    }

    var callToAction : String? {
      return sampleAd.callToAction
    }

    var starRating : NSDecimalNumber? {
      return sampleAd.starRating
    }

    var store : String? {
      return sampleAd.store
    }

    var price : String? {
      return sampleAd.price
    }

    var adChoicesView : UIView? {
      return adInfoView
    }

    var extraAssets : [String : Any]? {
      return extras
    }

    var mediaView : UIView?{
      return self.sampleMediaView!
    }

    var hasVideoContent : Bool {
      return self.sampleAd.mediaView != nil
    }

    func didRecordImpression() {
      sampleAd.recordImpression()
    }

    func didRender(in view: UIView, clickableAssetViews: [GADUnifiedNativeAssetIdentifier : UIView],
                       nonclickableAssetViews: [GADUnifiedNativeAssetIdentifier : UIView],
                               viewController: UIViewController) {
        // This method is called when the native ad view is rendered.
        // Here you would pass the UIView back to the mediated network's SDK.
        self.sampleAd.mediaView.playMedia()
    }

    func didRecordClickOnAsset(withName assetName: GADUnifiedNativeAssetIdentifier, view: UIView, viewController: UIViewController) {
       sampleAd.handleClick(on: view)
    }

    func didUntrackView(_ view: UIView?) {
        // This method is called when the mediatedNativeAd is no longer
        // rendered in the provided view. Here you would remove any
        // tracking from the view that has mediated native ad.
    }

}

Objective-C

    @interface SampleMediatedNativeAd ()
    @property(nonatomic, strong) SampleNativeAd *sampleAd;
    @property(nonatomic, copy) NSArray *mappedImages;
    @property(nonatomic, strong) GADNativeAdImage *mappedIcon;
    @property(nonatomic, copy) NSDictionary *extras;
    @property(nonatomic, strong) GADNativeAdViewAdOptions *nativeAdViewAdOptions;
    @property(nonatomic, strong) SampleAdInfoView *adInfoView;
    @property(nonatomic, strong) SampleMediaView *mediaView;

    @end

    @implementation SampleMediatedNativeAd

    - (instancetype)initWithSampleNativeAd:(SampleNativeAd *)sampleNativeAd
                     nativeAdViewAdOptions:(nullable GADNativeAdViewAdOptions *)nativeAdViewAdOptions {
      if (!sampleNativeAd) {
        return nil;
      }

      self = [super init];
      if (self) {
        _sampleAd = sampleNativeAd;
        _extras = @{SampleCustomEventExtraKeyAwesomeness : _sampleAd.degreeOfAwesomeness};

        if (_sampleAd.image) {
          _mappedImages = @[ [[GADNativeAdImage alloc] initWithImage:_sampleAd.image] ];
        } else {
          NSURL *imageURL = [[NSURL alloc] initFileURLWithPath:_sampleAd.imageURL];
          _mappedImages =
              @[ [[GADNativeAdImage alloc] initWithURL:imageURL scale:_sampleAd.imageScale] ];
        }

        if (_sampleAd.icon) {
          _mappedIcon = [[GADNativeAdImage alloc] initWithImage:_sampleAd.icon];
        } else {
          NSURL *iconURL = [[NSURL alloc] initFileURLWithPath:_sampleAd.iconURL];
          _mappedIcon = [[GADNativeAdImage alloc] initWithURL:iconURL scale:_sampleAd.iconScale];
        }
        _mediaView = _sampleAd.mediaView;
        _nativeAdViewAdOptions = nativeAdViewAdOptions;

        // The sample SDK provides an AdChoices view (SampleAdInfoView).
        // If your SDK provides image and clickthrough URLs for its
        // AdChoices icon instead of an actual UIView, the adapter is
        // responsible for downloading the icon image and creating the
        // AdChoices icon view.
        _adInfoView = [[SampleAdInfoView alloc] init];
      }
      return self;
    }

    - (BOOL)hasVideoContent {
      return self.sampleAd.mediaView != nil;
    }

    - (UIView *)mediaView {
      return _mediaView;
    }

    - (NSString *)advertiser {
      return self.sampleAd.advertiser;
    }

    - (NSString *)headline {
      return self.sampleAd.headline;
    }

    - (NSArray *)images {
      return self.mappedImages;
    }

    - (NSString *)body {
      return self.sampleAd.body;
    }

    - (GADNativeAdImage *)icon {
      return self.mappedIcon;
    }

    - (NSString *)callToAction {
      return self.sampleAd.callToAction;
    }

    - (NSDecimalNumber *)starRating {
      return self.sampleAd.starRating;
    }

    - (NSString *)store {
      return self.sampleAd.store;
    }

    - (NSString *)price {
      return self.sampleAd.price;
    }

    - (NSDictionary *)extraAssets {
      return self.extras;
    }

    - (UIView *)adChoicesView {
      return self.adInfoView;
    }

    // Because the Sample SDK has click and impression tracking via
    // methods on its native ad object which the developer is required
    // to call, there's no need to pass it a reference to the UIView
    // being used to display the native ad. So there's no need to
    // implement mediatedNativeAd:didRenderInView:viewController:clickableAssetViews:nonClickableAssetViews
    // here. If your mediated network does need a reference to the view,
    // this method can be used to provide one. You can also access the
    // clickable and non-clickable views by asset key if the mediation
    // network needs this information.
    - (void)didRenderInView:(UIView *)view
           clickableAssetViews:
               (NSDictionary<GADUnifiedNativeAssetIdentifier, UIView *> *)clickableAssetViews
        nonclickableAssetViews:
            (NSDictionary<GADUnifiedNativeAssetIdentifier, UIView *> *)nonclickableAssetViews
                viewController:(UIViewController *)viewController {
      // This method is called when the native ad view is rendered.
      // Here you would pass the UIView back to the mediated
      // network's SDK.
      // Playing video using SampleNativeAd's playVideo method
      [_sampleAd playVideo];
    }

    - (void)didUntrackView:(UIView *)view {
      // This method is called when the mediatedNativeAd is no longer
      // rendered in the provided view. Here you would remove any
      // tracking from the view that has mediated native ad.
    }

    - (void)didRecordImpression {
      if (self.sampleAd) {
        [self.sampleAd recordImpression];
      }
    }

    - (void)didRecordClickOnAssetWithName:(GADUnifiedNativeAssetIdentifier)assetName
                                     view:(UIView *)view
                           viewController:(UIViewController *)viewController {
      if (self.sampleAd) {
        [self.sampleAd handleClickOnView:view];
      }
    }

    @end

먼저 초기화 메서드와 그 기능에 대해 알아보겠습니다.

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

초기화 메서드는 SampleNativeAd의 인스턴스를 유일한 매개변수로 허용합니다. 이는 네이티브 광고를 위해 샘플 SDK에서 사용되는 네이티브 광고 클래스입니다. 매퍼는 미디에이션된 광고 객체에 대한 참조가 있어야 클릭 및 노출 이벤트를 전달할 수 있으므로 이 참조를 sampleAd로 저장합니다. 또한 초기화 메서드는 GADNativeAdViewAdOptions의 인스턴스를 사용합니다.

기타 애셋을 보유할 NSDictionary 생성하기

미디에이션된 네트워크 중 일부는 AdMob 네이티브 광고 형식에 포함되지 않는 애셋을 추가로 제공할 수도 있습니다. GADMediatedUnifiedNativeAd 프로토콜에는 Google 모바일 광고 SDK가 매퍼에서 이러한 '추가' 애셋을 검색하는 데 사용하는 extraAssets 메서드가 포함되어 있습니다.

위의 초기화 메서드는 NSDictionary를 생성하고 샘플 SDK에서 제공한 추가 애셋으로 내용을 채웁니다(이 예시에서는 degreeOfAwesomeness라는 단일 NSString이 사용됨). 이 NSDictionary는 이후에 extraAssets 메서드의 반환값으로 사용됩니다.

Swift

extras = [SampleCustomEventExtraKeyAwesomeness : sampleAd.degreeOfAwesomeness]

Objective-C

_extras = @{SampleCustomEventExtraKeyAwesomeness : _sampleAd.degreeOfAwesomeness};

이미지 애셋 매핑하기

이미지 애셋을 매핑하는 일은 NSString, double 등의 단순 데이터 유형을 매핑할 때보다 조금 더 복잡합니다. 이미지는 자동으로 다운로드될 수도 있고 URL 값으로만 반환될 수도 있습니다. 픽셀 밀도 또한 달라질 수 있습니다. 맞춤 이벤트 개발자가 이러한 세부정보를 관리할 수 있도록 Google 모바일 광고 SDK에서 GADNativeAdImage 클래스를 제공합니다. 이미지 애셋 정보(실제 UIImage 객체 또는 NSURL 값)는 이 클래스를 통해 Google 모바일 광고로 반환되어야 합니다.

매퍼 클래스에서 GADNativeAdImage를 만들어 아이콘 이미지를 저장하는 방법은 다음과 같습니다.

Swift

if let icon = sampleAd.icon {
    mappedIcon = GADNativeAdImage(image : icon)
}
else {
    let iconURL = URL(fileURLWithPath : sampleNativeAd.iconURL)
    mappedIcon = GADNativeAdImage(url : iconURL, scale : sampleAd.iconScale)
}

Objective-C

if (_sampleAd.icon) {
   _mappedIcon = [[GADNativeAdImage alloc] initWithImage:_sampleAd.icon];
} else {
   NSURL *iconURL = [[NSURL alloc] initFileURLWithPath:_sampleAd.iconURL];
   _mappedIcon = [[GADNativeAdImage alloc] initWithURL:iconURL scale:_sampleAd.iconScale];
}

요청하기에 대한 섹션에서 설명했듯이 GADNativeAdImageAdLoaderOptions 객체를 사용하여 네이티브 광고 이미지를 자동으로 다운로드하지 않도록 지정할 수 있습니다. 이때 매퍼는 이미지가 이미 다운로드되었는지 확인하고, 적절한 정보를 사용하여 GADNativeAdImage를 만듭니다. 이 정보는 UIImage이거나 NSURL과 배율 값을 짝지은 쌍입니다.

초기화 메서드에 대해 설명을 마쳤으므로, 이제 클래스의 다른 위치에서 처리되는 작업을 살펴보겠습니다.

매핑된 애셋 반환하기

이 매퍼 클래스는 네이티브 광고의 예상 애셋에 해당하는 GADMediatedUnifiedNativeAd에서 메서드를 상속합니다. Google 모바일 광고 SDK가 이러한 메서드를 호출하여 애셋을 검색하므로 매퍼 클래스가 적절한 값을 반환해야 합니다. 이 작업은 대부분의 애셋에서 상당히 간단하게 처리됩니다.

Swift

var headline : String? {
  return sampleAd.headline
}

Objective-C

- (NSString *)headline {
  return self.sampleAd.headline;
}

하지만 일부 애셋에서는 데이터 유형이 일치하지 않거나 변환이 필요할 수 있습니다. 매퍼는 이러한 세부사항을 처리해야 하며, 애셋 메서드에서 이 작업을 수행하는 것이 좋습니다.

AdChoices

어댑터가 AdChoices 아이콘을 제공합니다. adChoicesView 메서드는 GADMediatedUnifiedNativeAd 프로토콜의 선택적 메서드입니다. SDK가 구현되면 제공된 Ad Choices 보기를 네이티브 광고에 표시합니다.

다음은 AdChoices 아이콘을 제공하는 방법을 구현한 예입니다.

Swift

class SampleMediatedUnifiedNativeAd: NSObject, GADMediatedUnifiedNativeAd {
  /// Ad networks should provide their own AdChoices view.
  private var adChoicesView: SampleAdChoicesView?

  var adChoicesView : UIView? {
      return adChoicesView
  }

Objective-C

@interface SampleMediatedNativeAd ()<GADMediatedUnifiedNativeAd> {

  /// Ad networks should provide their own AdChoices view.
  SampleAdChoicesView *_adChoicesView;

}

@implementation SampleMediatedNativeAd

- (UIView *)adChoicesView {
  return _adInfoView;
}

노출 및 클릭 이벤트

노출 또는 클릭이 발생할 때마다 미디에이션된 네트워크의 SDK에 알림을 전송해야 합니다. 매퍼 클래스는 자체적인 노출 및 클릭 추적에 필요한 정보를 미디에이션된 네트워크 SDK에 제공하거나 노출 또는 클릭이 발생할 때 미디에이션된 네트워크 SDK에 명시적으로 알립니다.

미디에이션 대상인 네이티브 광고 객체가 클릭 및 노출을 기록하는 메서드를 제공하는 경우 맞춤 이벤트의 매퍼 클래스에서 이러한 메서드를 사용할 수 있습니다. 이 방식이 가장 일반적으로 사용됩니다. GADMediatedUnifiedNativeAd에는 didRecordImpression:, didRecordClickOnAssetWithName:view:viewController: 등 두 개의 메서드가 포함되며, 매퍼는 이 두 메서드를 재정의하여 미디에이션된 네이티브 광고 객체에서 해당 메서드를 호출하는 데 사용해야 합니다.

다음은 SampleMediatedNativeAd에서 이를 처리하는 방법입니다.

Swift

func didRecordImpression() {
  sampleAd.recordImpression()
}

func didRecordClickOnAsset(withName assetName: GADUnifiedNativeAssetIdentifier,
                                    view: UIView,
                                    viewController: UIViewController) {
  sampleAd.handleClick(on: view)
}

Objective-C

- (void)didRecordImpression {
  if (self.sampleAd) {
    [self.sampleAd recordImpression];
  }
}

- (void)didRecordClickOnAssetWithName:(GADUnifiedNativeAssetIdentifier)assetName
                                 view:(UIView *)view
                       viewController:(UIViewController *)viewController {
  if (self.sampleAd) {
    [self.sampleAd handleClickOnView:view];
  }
}

SampleMediatedNativeAd는 샘플 SDK의 네이티브 광고 객체에 대한 참조를 보유하므로 해당 객체에 대해 적절한 메서드를 간단히 호출하여 클릭 또는 노출을 보고할 수 있습니다.

미디에이션된 SDK에서 클릭 및 노출을 추적하도록 허용하기

클릭 및 노출을 자체적으로 추적해야 하는 광고 네트워크를 위해 GADCustomEventNativeAd 프로토콜은 handlesUserClickshandlesUserImpressions라는 두 가지 선택 메시지를 제공합니다. 이러한 메시지 중 하나에서 YES가 반환되면 맞춤 이벤트에서 이러한 유형의 발생을 자체적으로 추적하고 있다는 뜻입니다. NO 또는 응답 없음이 반환되면 Google 모바일 광고 SDK가 맞춤 이벤트를 대신하여 클릭 및 노출 추적을 처리하고, GADMediatedUnifiedNativeAd에서 didRecordImpression:didRecordClickOnAssetWithName:을 사용하여 보고해야 한다는 뜻입니다.

클릭 또는 노출을 직접 추적하는 맞춤 이벤트가 GADMediatedUnifiedNativeAd 프로토콜의 didRenderInView: 메시지를 이용하여 네이티브 광고의 보기를 미디에이션된 SDK의 네이티브 광고 객체에 전달하므로, 미디에이션된 SDK가 이를 이용하여 실제로 추적할 수 있습니다. 지금까지 본 가이드의 예시 코드에 표시된 샘플 SDK에서는 클릭 및 노출을 처리할 때 이 방법을 사용하지 않지만, 이 방법을 사용하는 경우에는 다음과 같은 적절한 didRenderInView: 메서드를 사용해야 합니다.

Swift

func didRender(in view: UIView,
                  clickableAssetViews: [GADUnifiedNativeAssetIdentifier : UIView],
                  nonclickableAssetViews: [GADUnifiedNativeAssetIdentifier : UIView],
                  viewController: UIViewController) {
  sampleAd?.setNativeAdView(view)
}

Objective-C

- (void)didRenderInView:(UIView *)view
       clickableAssetViews:
           (NSDictionary<GADUnifiedNativeAssetIdentifier, UIView *> *)clickableAssetViews
    nonclickableAssetViews:
        (NSDictionary<GADUnifiedNativeAssetIdentifier, UIView *> *)nonclickableAssetViews
            viewController:(UIViewController *)viewController {
  [self.sampleAd setNativeAdView:view];
}

GADMediatedUnifiedNativeAd에는 정반대의 용도로 사용되는 didUntrackView:도 포함됩니다. 맞춤 이벤트가 이를 구현하여 보기에 대한 참조를 해제하고, 가능하면 네이티브 광고 객체와의 연결을 해제해야 합니다.

GADMediatedNativeAdNotificationSource

미디에이션된 네이티브 광고에서 화면의 프레젠테이션이나 클릭 기록과 같은 이벤트를 보고할 수 있도록 SDK에서 GADMediatedNativeAdNotificationSource 클래스를 제공합니다. 이 클래스에는 미디에이션된 네이티브 광고의 다양한 수명 이벤트에 해당하는 메서드 6개가 있으며, 각 메서드가 해당 광고 객체에 대한 참조를 합니다.

  • mediatedNativeAdDidRecordImpression:: 맞춤 이벤트에서 미디에이션된 네이티브 광고가 이 메서드를 호출해야 하며, 해당 맞춤 이벤트는 노출을 직접 추적하여 Google 모바일 광고 SDK에 다시 노출을 보고합니다. 이는 보고를 위한 필수사항입니다.
  • mediatedNativeAdDidRecordClick:: 위와 마찬가지로, 자체 클릭을 추적하는 맞춤 이벤트는 미디에이션된 네이티브 광고를 통해 이 메서드를 호출하여 클릭 발생을 보고해야 합니다.
  • mediatedNativeAdWillPresentScreen:: 미디에이션된 네이티브 광고가 인앱 모달 화면에 열리기 직전에 호출해야 합니다.
  • mediatedNativeAdWillDismissScreen:: 미디에이션 대상인 네이티브 광고로 열린 인앱 모달 화면이 닫히기 직전에 호출해야 합니다.
  • mediatedNativeAdDidDismissScreen:: 미디에이션 대상인 네이티브 광고로 열린 인앱 모달 화면이 닫힌 후에 호출해야 합니다.
  • mediatedNativeAdWillLeaveApplication:: 도착 URL을 Safari에서 열 때와 같이, 미디에이션된 네이티브 광고로 인해 애플리케이션에서 포커스가 이탈하기 직전에 호출해야 합니다.

맞춤 이벤트 사용하기

맞춤 이벤트를 사용하려면 이를 광고 단위의 미디에이션 구성에 추가해야 합니다. 이 작업은 AdMob 인터페이스에서 처리할 수 있습니다. 맞춤 이벤트 생성하기에 광고 단위의 미디에이션 구성을 수정하는 방법이 자세히 나와 있습니다.

광고 단위의 미디에이션 구성에 맞춤 이벤트를 추가할 때 다음과 같은 3가지 정보를 입력해야 합니다.

  • Class Name: 맞춤 이벤트의 클래스 이름입니다.
  • Label: AdMob의 인터페이스에서 광고 단위의 미디에이션 소스를 표시하기 위해 맞춤 이벤트를 나타낼 때 사용하는 라벨입니다. 개발자를 위한 기능이며 AdMob.com에만 표시됩니다.
  • Parameter: 이 광고 단위로 요청이 이루어질 때마다 맞춤 이벤트에 전달되는 문자열 값입니다. 일반적으로 이 값은 미디에이션된 네트워크의 광고 단위 ID로 설정됩니다.

다음은 예시 맞춤 이벤트 항목의 스크린샷입니다.

여기까지입니다. AdMob의 자체 iOS 맞춤 이벤트를 작성하는 방법에 대해 알아보았습니다.