광고 네트워크 미디에이션 어댑터 개발

이 가이드는 미디에이션 어댑터를 제작하려는 광고 네트워크를 대상으로 합니다. 게시자는 게시자 미디에이션을 참고하세요.

미디에이션 어댑터는 광고 네트워크와 Google 모바일 광고 미디에이션 간의 통신 계층입니다. 어댑터는 광고 네트워크의 광고를 게재하는 동시에 AdMob에 관련 광고 이벤트를 전달합니다. 어댑터는 필수 기능을 제공하기 위해 GADMAdNetworkAdapter 프로토콜을 구현해야 합니다.

기본 요건

  • Xcode 15.3 이상
  • 배포 대상 8.0 이상
  • Google 모바일 광고 iOS SDK 다운로드의 미디에이션 어댑터 폴더에 있는 추가 헤더

광고 네트워크는 Google과 미디에이션 어댑터를 만들기 위한 협력 관계를 수립해야 합니다.

샘플 광고 네트워크

이 가이드에서는 샘플 광고 네트워크용 어댑터를 만드는 방법을 보여줍니다. 샘플 광고 네트워크 SDK에 포함된 클래스는 대부분의 광고 네트워크가 제공하는 클래스를 대표합니다.

@interface SampleBanner : UILabel

@property(nonatomic, copy) NSString *adUnit;
@property(nonatomic, weak) id<SampleBannerAdDelegate> delegate;
- (void)fetchAd:(SampleAdRequest *)request;

@end

typedef NS_ENUM(NSInteger, SampleErrorCode) {
  SampleErrorCodeBadRequest = 0,
  SampleErrorCodeUnknown = 1,
  SampleErrorCodeNetworkError = 2,
  SampleErrorCodeNoInventory = 3,
};

@interface SampleAdRequest : NSObject

@property(nonatomic, assign) BOOL testMode;
@property(nonatomic, copy) NSArray *keywords;

@end

@interface SampleInterstitial : NSObject

@property(nonatomic, copy) NSString *adUnit;
@property(nonatomic, weak) id<SampleInterstitialAdDelegate> delegate;
@property(nonatomic, assign, getter=isInterstitialLoaded) BOOL interstitialLoaded;
- (void)fetchAd:(SampleAdRequest *)request;
- (void)show;

@end

@protocol SampleBannerAdDelegate
- (void)bannerDidLoad:(SampleBanner *)banner;
- (void)banner:(SampleBanner *)banner didFailToLoadAdWithError:(SampleErrorCode)error;
- (void)bannerWillLeaveApplication:(SampleBanner *)banner;

@end

@protocol SampleInterstitialAdDelegate<NSObject>
- (void)interstitialDidLoad:(SampleInterstitial *)interstitial;
- (void)interstitial:(SampleInterstitial *)interstitial
    didFailToLoadAdWithError:(SampleErrorCode)error;
- (void)interstitialWillPresentScreen:(SampleInterstitial *)interstitial;
- (void)interstitialWillDismissScreen:(SampleInterstitial *)interstitial;
- (void)interstitialDidDismissScreen:(SampleInterstitial *)interstitial;
- (void)interstitialWillLeaveApplication:(SampleInterstitial *)interstitial;

@end

이러한 클래스의 자세한 내용은 전체 샘플 SDK 구현을 참조하세요.

커넥터

미디에이션 어댑터는 GADMAdNetworkConnector 프로토콜을 구현하는 객체를 사용하여 Google 모바일 광고 SDK와 상호작용합니다. 지금부터 이 객체를 커넥터라고 하겠습니다 커넥터는 광고 요청에 필요한 정보를 노출하고 광고 이벤트 및 사용자 상호작용을 위해 미디에이션에 콜백하는 수단을 제공합니다. 커넥터는 초기화 시 미디에이션 어댑터에 제공됩니다. 커넥터를 인스턴스 변수에 저장하도록 어댑터를 설정합니다.

- (id)initWithGADMAdNetworkConnector:(id<GADMAdNetworkConnector>)c {
  if ((self = [super init])) {
    _connector = c;
  }
  return self;
}

서버 매개변수

광고 네트워크에는 게시자를 식별하기 위한 식별자가 필요할 수 있습니다. 예를 들어 샘플 광고 네트워크에는 광고 단위가 필요합니다. 이러한 필수 서버 매개변수는 credentials 메서드를 통해 어댑터에 제공되며, 이 메서드는 식별자의 NSDictionary와 해당 값을 반환합니다. 다음 코드는 커넥터로부터 샘플 광고 네트워크의 ad_unit라는 서버 매개변수를 가져옵니다.

self.interstitialAd.adUnit = [[self.connector credentials] objectForKey:@"ad_unit"];

미디에이션 네트워크 설정

광고 네트워크는 네트워크에 필요한 서버 매개변수를 AdMob에 알려야 합니다. 이렇게 하면 AdMob에서 프런트엔드에서 네트워크를 구성할 수 있습니다.

AdMob에서는 프런트 엔드에서 미디에이션을 위해 네트워크를 설정할 때 어댑터를 인스턴스화하는 데 필요한 값을 입력하도록 요구합니다. 아래 스크린샷을 보면 Millennial Media에서는 애플리케이션 게재위치 식별자 (APID)가 필요하고 InMobi에는 앱 ID가 필요합니다.

미디에이션 광고 네트워크 구성의 자세한 내용은 도움말을 참조하세요.

미디에이션 광고 요청

미디에이션 배너 요청에서는 어댑터가 인스턴스화된 직후에 getBannerWithSize 메서드가 호출됩니다. 이 메서드는 아무것도 반환하지 않습니다. 이 메서드는 어댑터에 네트워크를 통한 비동기 광고 가져오기를 시작하라는 신호를 보냅니다. 어댑터가 SDK의 콜백을 수신 대기하도록 합니다. SDK가 지정된 광고 크기를 지원하지 않거나 배너 광고를 지원하지 않는 경우 커넥터의 adapter:didFailAd: 메서드를 호출합니다.

샘플 광고 네트워크의 getBannerWithSize 구현은 다음과 같습니다.

- (void)getBannerWithSize:(GADAdSize)adSize {
  //The adapter should fail immediately if the adSize is not supported
  if (!GADAdSizeEqualToSize(adSize, GADAdSizeBanner) &&
      !GADAdSizeEqualToSize(adSize, GADAdSizeMediumRectangle) &&
      !GADAdSizeEqualToSize(adSize, GADAdSizeFullBanner) &&
      !GADAdSizeEqualToSize(adSize, GADAdSizeLeaderboard)) {
    NSString *errorDesc =
        [NSString stringWithFormat:@"Invalid ad type %@, not going to get ad.",
                                   NSStringFromGADAdSize(adSize)];
    NSDictionary *errorInfo = [NSDictionary
        dictionaryWithObjectsAndKeys:errorDesc, NSLocalizedDescriptionKey, nil];
    NSError *error = [NSError errorWithDomain:GADErrorDomain
                                         code:GADErrorMediationInvalidAdSize
                                     userInfo:errorInfo];
    [self.connector adapter:self didFailAd:error];
    return;
  }
  self.bannerAd = [[SampleBanner alloc]
      initWithFrame:CGRectMake(0, 0, adSize.size.width, adSize.size.height)];

  self.bannerAd.delegate = self;
  self.bannerAd.adUnit = [[self.connector credentials] objectForKey:@"ad_unit"];

  // Setup request parameters.
  SampleAdRequest *request = [[SampleAdRequest alloc] init];
  request.testMode = self.connector.testMode;
  request.keywords = self.connector.userKeywords;
  [self.bannerAd fetchAd:request];
  NSLog(@"Requesting banner from Sample Ad Network");
}

추가 타겟팅 매개변수

커넥터에는 광고 타겟팅에 참조할 수 있는 일반적인 타겟팅 정보가 포함되어 있습니다.

  • userKeywords
  • testMode
  • childDirectedTreatment

미디에이션 추가

미디에이션 추가를 사용하면 광고 네트워크가 커넥터가 제공하는 추가 요청 매개변수에 포함되지 않는 추가 타겟팅 매개변수 또는 입력을 지원할 수 있습니다. 이 기능은 GADAdNetworkExtras 프로토콜을 구현하는 클래스를 통해 제공될 수 있습니다. 다음은 SampleAdNetworkExtras 클래스의 예입니다.

@interface SampleAdNetworkExtras : NSObject <GADAdNetworkExtras>
/// Should ad volume audio be muted.
@property(nonatomic, assign) BOOL muteAudio;

@end

게시자는 광고를 요청할 때 GADAdNetworkExtras 서브클래스의 인스턴스를 전달해야 합니다. 커넥터를 통해 이 GADAdNetworkExtras 서브클래스 인스턴스에 액세스할 수 있습니다. 네트워크에 대한 광고 요청을 작성할 때 미디에이션 추가를 사용하는 방법은 다음과 같습니다.

SampleAdRequest *request = [[SampleAdRequest alloc] init];
SampleAdNetworkExtras *myAdNetworkExtras = [self.connector networkExtras];
request.muteAudio = myAdNetworkExtras.muteAudio;
[self.bannerAd fetchAd:request];

커넥터를 통해 GADAdNetworkExtras 서브클래스에 액세스할 수 있도록 하려면 networkExtrasClass를 구현하고 GADAdNetworkExtras 서브클래스를 반환합니다.

+ (Class<GADAdNetworkExtras>)networkExtrasClass {
  return [SampleAdNetworkExtras class];
}

어댑터가 미디에이션 추가 항목을 사용하지 않으면 networkExtrasClass 메서드가 Nil를 반환합니다.

미디에이션 알림

어댑터에서 네트워크의 광고 리스너를 구현하고 커넥터를 통해 관련 광고 이벤트 콜백을 전달해야 합니다. 아래 표에서는 각 대리자 메서드를 호출할 시점을 설명합니다.

메서드 호출 시점
adapter:didReceiveAdView: 배너 요청에 성공했을 때
adapter:didFailAd: 배너 요청에 실패했습니다.
adapterDidGetAdClick: 배너를 클릭했을 때
adapterWillPresentFullScreenModal: 배너에 인앱 오버레이가 표시되는 경우
adapterWillDismissFullScreenModal: 인앱 오버레이가 닫힙니다.
adapterDidDismissFullScreenModal: 인앱 오버레이가 닫혔을 때
adapterWillLeaveApplication: 사용자가 다른 애플리케이션을 실행하는 광고를 클릭하여 애플리케이션이 백그라운드로 이동하거나 종료되는 경우

다음 예에서는 샘플 광고 네트워크의 SampleBannerAdDelegate 인터페이스를 구현하여 오류 및 상태 메시지를 전달합니다.

- (void)bannerDidLoad:(SampleBanner *)banner {
  [self.connector adapter:self didReceiveAdView:banner];
}

- (void)banner:(SampleBanner *)banner didFailWithError:(SampleErrorCode)error {
  [self.connector adapter:self
                didFailAd:[NSError errorWithDomain:@"Ad request failed"
                                              code:error
                                          userInfo:nil]];
}

- (void)bannerWillLeaveApplication:(SampleBanner *)banner {
  [self.connector adapterDidGetAdClick:self];
  [self.connector adapterWillLeaveApplication:self];
}

인앱 오버레이 실행과 외부 애플리케이션 실행 비교

배너를 클릭하면 광고에서 전체 화면 오버레이나 외부 애플리케이션 (예: Safari, App Store)이 열릴 수 있습니다. 이 두 경우에 호출할 커넥터 콜백은 서로 다릅니다.

배너를 클릭하면 전체 화면 오버레이가 열리는 경우 오버레이를 표시할 때 adapterWillPresentFullScreenModal:를 호출하세요. 오버레이가 닫히면 adapterWillDismissFullScreenModal:adapterDidDismissFullScreenModal:를 모두 호출합니다.

배너 클릭 (또는 전체 화면 오버레이 클릭)으로 인해 사용자가 애플리케이션에서 나가는 경우 adapterWillLeaveApplication: 콜백을 호출합니다.

이제 배너용 미디에이션 어댑터가 정상적으로 작동하게 되었습니다. SampleAdapter의 전체 구현은 GitHub에서 확인할 수 있습니다.

전면 광고 어댑터 구현하기

전면 광고의 어댑터 구현은 배너 광고와 유사합니다. getInterstitial 메서드는 어댑터가 인스턴스화된 직후 호출됩니다. 이 메서드는 아무것도 반환하지 않습니다. 어댑터는 네트워크를 통한 비동기 광고 가져오기를 시작해야 합니다. 어댑터는 SDK의 대리자 역할을 하며 콜백을 수신 대기합니다. SDK가 전면 광고를 지원하지 않는 경우 다음과 같이 커넥터의 adapter:didFailAd: 메서드를 호출하세요.

- (void)getInterstitial {
  self.interstitialAd = [[SampleInterstitial alloc] init];
  self.interstitialAd.delegate = self;
  self.interstitialAd.adUnit =
      [[self.connector credentials] objectForKey:@"ad_unit"];

  SampleAdRequest *request = [[SampleAdRequest alloc] init];
  // Setup request parameters.
  request.testMode = self.connector.testMode;
  request.keywords = self.connector.userKeywords;

  [self.interstitialAd fetchAd:request];
  NSLog(@"Requesting interstitial from Sample Ad Network");
}

MediationBannerAdapter와 마찬가지로 커넥터에서 게시자 식별 및 광고 타겟팅 정보를 받을 수 있습니다.

미디에이션 알림

어댑터에서 네트워크의 광고 대리자를 구현하고 커넥터를 통해 관련 광고 이벤트 콜백을 전달해야 합니다. 아래 표에서는 각 대리자 메서드를 호출하는 시점을 설명합니다.

메서드 호출 시점
adapterDidReceiveInterstitial: 전면 광고 요청에 성공한 경우
adapter:didFailInterstitial: 전면 광고 요청에 실패했습니다.
adapterDidGetAdClick: 전면 광고를 클릭했을 때
adapterWillPresentInterstitial: 전면 광고가 표시됩니다.
adapterWillDismissInterstitial: 전면 광고가 닫히는 경우
adapterDidDismissInterstitial: 전면 광고가 닫힌 경우
adapterWillLeaveApplication: 사용자가 다른 애플리케이션을 실행하는 광고를 클릭하여 애플리케이션이 백그라운드로 이동하거나 종료되는 경우

다음 예에서는 샘플 광고 네트워크의 SampleInterstitialAdDelegate 인터페이스를 구현하여 오류 및 상태 메시지를 전달합니다.

- (void)interstitialDidLoad:(SampleInterstitial *)interstitial {
  [self.connector adapterDidReceiveInterstitial:self];
}

- (void)interstitial:(SampleInterstitial *)interstitial
    didFailWithError:(SampleErrorCode)error {
  [self.connector adapter:self
      didFailInterstitial:[NSError errorWithDomain:@"Ad request failed"
                                              code:error
                                          userInfo:nil]];
}

- (void)interstitialWillPresentScreen:(SampleInterstitial *)interstitial {
  [self.connector adapterWillPresentInterstitial:self];
}

- (void)interstitialWillDismissScreen:(SampleInterstitial *)interstitial {
  [self.connector adapterWillDismissInterstitial:self];
}

- (void)interstitialDidDismissScreen:(SampleInterstitial *)interstitial {
  [self.connector adapterDidDismissInterstitial:self];
}

전면 광고 표시

어댑터가 adapterDidReceiveInterstitial를 호출한 후에는 presentInterstitialFromRootViewController가 호출될 때까지 전면 광고가 표시되도록 기다려야 합니다. 전면 광고를 언제 표시할지는 앱 개발자가 결정하며, 이 시점은 수신 후 몇 분이 걸릴 수도 있습니다.

다음은 샘플 광고 네트워크에 대한 presentInterstitialFromRootViewController:의 구현입니다.

- (void)presentInterstitialFromRootViewController:
    (UIViewController *)rootViewController {
  if ([self.interstitialAd isLoaded]) {
    [self.interstitialAd show];
  }
}

미디에이션 어댑터에서 전면 광고를 처리할 준비가 되었습니다. SampleAdapter의 전체 구현은 GitHub에서 확인할 수 있습니다.

FAQ

어댑터를 SDK 라이브러리의 일부로 포함해야 하나요? 아니면 별도의 라이브러리로 포함해야 하나요?
개발자가 하나의 라이브러리만 참조하여 네트워크를 통합할 수 있도록 어댑터를 SDK 라이브러리의 일부로 포함하는 것이 좋습니다.
어댑터가 배너 광고만 지원하는 경우 어떻게 해야 하나요?

배너만 지원하는 어댑터는 전면 광고 요청 미디에이션에 오류 이벤트를 전달해야 합니다.

- (void)getInterstitial {
  NSDictionary *errorInfo = @{ NSLocalizedDescriptionKey : @"Some error" };
  NSError *error = [NSError errorWithDomain:GADErrorDomain
                                       code:GADErrorInvalidRequest
                                   userInfo:errorInfo];
  [self.connector adapter:self didFailInterstitial:error];
  return;
}
어댑터가 전면 광고만 지원하는 경우 어떻게 해야 하나요?

전면 광고만 지원하는 어댑터는 배너 요청에 대해 미디에이션에 오류 이벤트를 전달해야 합니다.

- (void)getBannerWithSize:(GADAdSize)adSize {
  NSDictionary *errorInfo = @{ NSLocalizedDescriptionKey : @"Some error" };
  NSError *error =
      [NSError errorWithDomain:GADErrorDomain
                          code:GADErrorInvalidRequest
                      userInfo:errorInfo];
  [self.connector adapter:self didFailAd:error];
  return;
}