네이티브 맞춤 이벤트

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

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

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

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

기본 요건

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

샘플 SDK

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

샘플 SDK에서는 광고 네트워크의 프로덕션 SDK에 있는 것과 유사한 클래스를 제공합니다. SampleNativeAdRequest와 같은 요청 객체, SampleNativeAdLoader와 같은 광고 로더 등 실제 네트워크의 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: 게시자의 광고 로드 환경설정을 나타내는 NSArray 객체가 포함된 GADAdLoaderOptions입니다.

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

다음은 구현된 requestNativeAdWithParameter: 메소드를 보여주는 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 배열에 GADNativeAdImageAdLoaderOptions 값이 true로 설정된 shouldDownloadImages 객체가 포함되어 있으면 맞춤 이벤트는 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에서 네이티브 광고 객체를 수신할 때 GADMediatedNativeAd의 하위 클래스로 미디에이션 대상 SDK의 네이티브 광고 객체를 '매핑'하여 Google 모바일 광고 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 모바일 광고 SDK로 반환할 때 이 클래스를 사용해야 합니다.

매퍼 클래스에서 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];
  }
}

샘플 SDK의 네이티브 광고 객체에 대한 참조가 SampleMediatedNativeAd에 있으므로 이 객체에서 적절한 메소드를 호출하기만 하면 클릭 또는 노출을 보고할 수 있습니다.

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

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

클릭 또는 노출을 직접 추적하는 맞춤 이벤트가 didRenderInView: 프로토콜의 GADMediatedUnifiedNativeAd 메시지를 이용해 네이티브 광고의 보기를 미디에이션된 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 맞춤 이벤트를 작성하는 방법에 대해 알아보았습니다.