ADX Library
  • ADXLibrary
  • Android
    • Integrate
    • SDK Integration
      • Initialize
      • Ad Formats
        • Banner Ad
        • Interstitial Ad
        • Native Ad
        • Rewarded Ad
          • AD(X)
          • AdMob
      • Ad Error
      • Ad Revenue
        • Banner Ad
        • Interstitial Ad
        • Native Ad
        • Rewarded Ad
      • Sample Application
    • Targeting Android 12
    • Change log
  • iOS
    • Integrate
    • SDK Integration
      • Initialize
      • Ad Formats
        • Banner Ad
        • Interstitial Ad
        • Native Ad
        • Rewarded Ad
          • AD(X)
          • AdMob
      • Ad Error
      • Ad Revenue
        • Banner Ad
        • Interstitial Ad
        • Native Ad
        • Rewarded Ad
      • Sample Application
    • Supporting iOS 14+
      • App Tracking Transparency
      • SKAdNetwork ID List
    • Change log
  • Unity
    • Integrate
    • SDK Integration
      • Initialize
      • Ad Formats
        • Banner Ad
        • Interstitial Ad
        • Rewarded Ad
          • AD(X)
          • AdMob (ADX v2.4.0 미만)
          • AdMob (ADX v2.4.0 이상)
      • Ad Error
      • Ad Revenue
        • Banner Ad
        • Interstitial Ad
        • Rewarded Ad
      • Sample Application
    • Change log
  • Flutter
    • Integrate
    • SDK Integration
      • Initialize
      • Ad Formats
        • Banner Ad
        • Interstitial Ad
        • Rewarded Ad
      • Sample Application
    • Change log
  • Appendix
    • SSV Callback (Server-Side Verification)
    • UMP (User Messaging Platform)
Powered by GitBook
On this page
  • 1. 기본 요건
  • 2. 레이아웃 설정
  • 3. 구현
  • Case 1: 하나의 View를 사용하는 경우
  • Case 2: UITableView / UICollectionView에서 AdPlacer를 사용하는 경우
  • 4. Ad Revenue (paidEventHandler)

Was this helpful?

  1. iOS
  2. SDK Integration
  3. Ad Formats

Native Ad

PreviousInterstitial AdNextRewarded Ad

Last updated 7 months ago

Was this helpful?

1. 기본 요건

  • 를 프로젝트에 추가합니다.

  • Native Ad용으로 발급받은 Ad Unit ID를 사용합니다.

  • 광고를 요청하기 전에 를 먼저 진행합니다.

    • SDK 초기화는 앱 실행 시 한 번만 호출하여 주시고, 광고 요청은 초기화가 완료된 후에 이뤄져야 합니다.

    • iOS 14 이상 지원하는 경우, 권한 요청 완료 후 광고를 요청해주세요.

2. 레이아웃 설정

Native Ad의 경우, 광고에 사용 될 레이아웃을 직접 구성해야 합니다. 필수 구성 요소들은 다음과 같습니다.

  • Title : UILabel

  • Main Text : UILabel

  • Call-To-Action : UIButton

  • Icon Image : UIImageView

  • Main Image : UIImageView

  • Privacy Icon : UIImageView

  • Ad Tag : UIView (UILabel 또는 UIImageView)

Ad Tag 요소는 "Ad" 또는 "Advertisement" 문자열을 보여주는 UI 구성 요소를 포함하여, 광고라는 것을 명확하게 사용자에게 인식을 시켜야 합니다. 이 요소가 포함되지 않으면, 일부 광고 네트워크의 광고 송출이 중단될 수 있습니다.

2.1.0 버전부터 Native Ad의 CTA (Call-To-Action)가 UILabel에서 UIButton으로 변경 되었습니다.

이 요소들은 반드시 포함하여 구성하여 주시고, 광고 컨텐츠를 덮는 View가 없어야 합니다. 또한 텍스트 변경, 이미지 변경, 터치 시 액션 변경 등 광고 컨텐츠에 관련된 부분을 가공하거나 변경하지 않도록 주의 부탁드립니다.

// NativeAdView.h

#import <ADXLibrary/ADXNativeAdRendering.h>

@interface NativeAdView : UIView <ADXNativeAdRendering>
        
@property (nonatomic, weak) IBOutlet UILabel *titleLabel;
@property (nonatomic, weak) IBOutlet UILabel *mainTextLabel;
@property (nonatomic, weak) IBOutlet UIButton *callToActionButton;
@property (nonatomic, weak) IBOutlet UIImageView *iconImageView;
@property (nonatomic, weak) IBOutlet UIImageView *mainImageView;
@property (nonatomic, weak) IBOutlet UIImageView *privacyInformationIconImageView;
        
@end

// NativeAdView.m

@implementation NativeAdView

- (void)layoutSubviews {
    [super layoutSubviews];
}

- (UILabel *)nativeMainTextLabel {
    return self.mainTextLabel;
}

- (UILabel *)nativeTitleTextLabel {
    return self.titleLabel;
}

- (UIButton *)nativeCallToActionButton {
    return self.callToActionButton;
}

- (UILabel *)nativeSponsoredByCompanyTextLabel {
    return self.sponsoredByLabel;
}

- (UIImageView *)nativeIconImageView {
    return self.iconImageView;
}

- (UIImageView *)nativeMainImageView {
    return self.mainImageView;
}

- (UIImageView *)nativePrivacyInformationIconImageView {
    return self.privacyInformationIconImageView;
}

@end
import UIKit
import ADXLibrary

class NativeAdView: UIView {
    @IBOutlet var contentsView: UIView!
    @IBOutlet var titleLabel: UILabel!
    @IBOutlet var mainTextLabel: UILabel!
    @IBOutlet var callToActionButton: UIButton!
    @IBOutlet var iconImageView: UIImageView!
    @IBOutlet var privacyInformationIconImageView: UIImageView!
    @IBOutlet var mainImageView: UIImageView!
    
    convenience init() {
        self.init(frame: .zero)
        initView()
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        initView()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initView()
    }
    
    func initView() {
        Bundle.main.loadNibNamed("NativeAdView", owner: self, options: nil)
        addSubview(contentsView)
        
        contentsView.frame = self.bounds
        contentsView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
    }
}

extension NativeAdView: ADXNativeAdRendering {
    func nativeMainTextLabel() -> UILabel {
        return self.mainTextLabel
    }
    
    func nativeTitleTextLabel() -> UILabel {
        return self.titleLabel
    }
    
    func nativeCallToActionButton() -> UIButton {
        return self.callToActionButton
    }
    
    func nativeIconImageView() -> UIImageView {
        return self.iconImageView
    }
    
    func nativeMainImageView() -> UIImageView {
        return self.mainImageView
    }
    
    func nativePrivacyInformationIconImageView() -> UIImageView {
        return self.privacyInformationIconImageView
    }
}

3. 구현

Native Ad는 다음 2가지 방법 중 하나로 광고를 로드할 수 있습니다.

Case 1: 하나의 View를 사용하는 경우

  1. ADXNativeAdFactory의 setRenderingViewClass:renderingViewClass:메서드를 사용하여 RenderingViewClass를 구성합니다.

  2. ADXNativeAdFactoryDelegate callback을 등록합니다.

  3. ADXNativeAdFactoryDelegate의 loadAd를 호출하여 광고를 로드합니다.

  4. 광고 로드가 완료되면 ADXNativeAdFactoryDelegate의 onSuccess:nativeAd:가 호출됩니다.

#import "NativeAdViewController"
#import "NativeAdView.h"

#import <ADXLibrary/ADXNativeAdFactory.h>

@interface NativeAdViewController () <ADXNativeAdFactoryDelegate, ADXNativeAdDelegate>

@property (strong) ADXNativeAd *nativeAd;

@end

@implementation NativeAdViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [[ADXNativeAdFactory sharedInstance] 
        setRenderingViewClass:@"<ADX_NATIVE_AD_UNIT_ID>" 
        renderingViewClass:[NativeAdView class]];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [[ADXNativeAdFactory sharedInstance] addDelegate:self];
    [[ADXNativeAdFactory sharedInstance] loadAd:@"<ADX_NATIVE_AD_UNIT_ID>"];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [[ADXNativeAdFactory sharedInstance] removeDelegate:self];
}

#pragma mark - ADXNativeAdFactoryDelegate

- (void)onSuccess:(NSString *)adUnitId nativeAd:(ADXNativeAd *)nativeAd {
    NSLog(@"onSuccess : %@", adUnitId);

    if([adUnitId isEqualToString:ADX_NATIVE_AD_UNIT_ID]) {
        self.nativeAd = nativeAd;
        self.nativeAd.delegate = self;

        UIView *nativeAdView = [[ADXNativeAdFactory sharedInstance] 
            getNativeAdView:@"<ADX_NATIVE_AD_UNIT_ID>"];

        nativeAdView.frame = CGRectMake(0.0,
                                        100.0,
                                        320.0,
                                        300.0);
        [self.view addSubview:nativeAdView];
    }
}

- (void)onFailure:(NSString *)adUnitId {
    NSLog(@"onFailure : %@", adUnitId);
}

#pragma mark - ADXNativeAdDelegate

- (UIViewController *)viewControllerForPresentingModalView {
    return self;
}

@end
import UIKit
import ADXLibrary

class NativeAdViewController: UIViewController {
    
    var nativeAd: ADXNativeAd?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        ADXNativeAdFactory.sharedInstance().setRenderingViewClass(
            "<ADX_NATIVE_AD_UNIT_ID>", 
            renderingViewClass: NativeAdView.self)
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        ADXNativeAdFactory.sharedInstance().add(self)
        ADXNativeAdFactory.sharedInstance().loadAd("<ADX_NATIVE_AD_UNIT_ID>")
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        ADXNativeAdFactory.sharedInstance().remove(self)
    }
}

extension NativeAdViewController: ADXNativeAdFactoryDelegate, ADXNativeAdDelegate {
    
    // MARK: - ADXNativeAdFactoryDelegate
    public func onSuccess(_ adUnitId: String!, nativeAd: ADXNativeAd!) {
        if (adUnitId == ADX_NATIVE_AD_UNIT_ID) {
            self.nativeAd = nativeAd
            self.nativeAd?.delegate = self
            
            let nativeAdView = ADXNativeAdFactory.sharedInstance()
                .getNativeAdView("<ADX_NATIVE_AD_UNIT_ID>")
                
            nativeAdView?.frame = CGRect(
                x: (UIScreen.main.bounds.width - 300.0)/2,
                y: 100.0,
                width: 300.0,
                height: 270.0)
                
            self.view.addSubview(nativeAdView!)
            
        } else {
            print("fail to load")
        }
    }
    
    public func onFailure(_ adUnitId: String!) {
        print("onFailure :", adUnitId!)
    }
    
    // MARK: - ADXNativeAdDelegate
    func viewControllerForPresentingModalView() -> UIViewController {
        return self
    }
}

Case 2: UITableView / UICollectionView에서 AdPlacer를 사용하는 경우

  1. ADXNativeAdFactory의 setRenderingViewClass:renderingViewClass: 메서드를 사용하여 RenderingViewClass를 구성합니다.

  2. 로드할 광고의 크기를 설정합니다.

    • 광고의 크기는 xib파일에서 사이즈를 지정하시거나 frame으로 세팅해주셔야 합니다.

  3. ADXAdPositioning을 이용하여 고정 및 반복 위치를 지정합니다.

    • addFixedIndexPath: 고정할 광고 위치

    • enableRepeatingPositionsWithInterval: 광고 반복 위치

  4. loadAdsForAdUnitID: 를 호출하여 광고를 로드합니다.

#import "NativeAdPlacerViewController.h"
#import "NativeAdView.h"

#import <ADXLibrary/ADXNativeAdFactory.h>

@interface NativeAdPlacerViewController () <UICollectionViewDataSource, UICollectionViewDelegate, ADXCollectionViewAdPlacerDelegate>

@property (weak) IBOutlet UICollectionView *colltionView;
@property (strong) ADXCollectionViewAdPlacer *placer;

@end

@implementation NativeAdPlacerViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [[ADXNativeAdFactory sharedInstance] 
        setRenderingViewClass:@"<ADX_NATIVE_AD_UNIT_ID>" 
        renderingViewClass:[NativeAdView class]];
    
    // 광고 고정 및 반복 위치 지정 
    ADXAdPositioning *adPositioning = [ADXAdPositioning positioning];
    [adPositioning addFixedIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
    [adPositioning enableRepeatingPositionsWithInterval:3];
    
    self.placer = [[ADXNativeAdFactory sharedInstance] 
        getCollectionViewAdPlacer:@"<ADX_NATIVE_AD_UNIT_ID>"
        collectionView:self.colltionView
        viewController:self
        adPositioning:adPositioning];
        
    [self.placer loadAdsForAdUnitID:@"<ADX_NATIVE_AD_UNIT_ID>"];
}
import UIKit
import ADXLibrary

class NativeAdPlacerViewController: UIViewController {
    
    @IBOutlet var collectionView: UICollectionView!
    var placer : ADXCollectionViewAdPlacer!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        ADXNativeAdFactory.sharedInstance().setRenderingViewClass(
            "<ADX_NATIVE_AD_UNIT_ID>", 
            renderingViewClass: NativeAdView.self)
        
        let adPositioning = ADXAdPositioning()
        adPositioning.addFixedIndexPath(IndexPath(row: 0, section: 0))
        adPositioning.enableRepeatingPositions(withInterval: 3)
        
        self.placer = ADXNativeAdFactory.sharedInstance()
            .getCollectionViewAdPlacer(
                "<ADX_NATIVE_AD_UNIT_ID>", 
                collectionView: collectionView, 
                viewController: self, 
                adPositioning: adPositioning
            )

        self.placer.loadAds(forAdUnitID: "<ADX_NATIVE_AD_UNIT_ID>")
    }
}

extension NativeAdPlacerViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 60;
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell : UICollectionViewCell = collectionView.adx_dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! UICollectionViewCell
        
        return cell
    }
}

Cell의 position 정보가 달라지기 때문에, UITableView는 ADXTableViewAdPlacer.h, UICollectionView는 ADXCollectionViewAdPlacer.h 파일을 참고하시어 대체 메서드를 사용해주시기 바랍니다.

4. Ad Revenue (paidEventHandler)

광고 노출에 대한 예상 광고 수익을 확인할 수 있습니다.

  • 이 기능은 iOS ADX SDK 2.6.2 이상 버전을 사용하시는 것이 권장됩니다.

  • 아래 예제와 같이' paidEventHandler' 를 사용하여 예상되는 eCPM 값을 확인할 수 있습니다.

  • 'ADXCollectionViewAdPlacer' 및 'ADXTableViewAdPlacer' 를 사용하는 경우, 이 기능은 지원되지 않습니다.

  • 미디에이션 설정 과정에서 수동적으로 설정한 값과 정확한 값이 섞여 있어서 예상 값으로 사용하시는 것을 권장드립니다.

  • eCPM의 통화(Currency) 단위는 USD입니다.

#import <UIKit/UIKit.h>
#import <ADXLibrary/ADXNativeAdFactory.h>
#import "NativeAdViewController.h"
#import "NativeAdView.h"
#import <FirebaseAnalytics/FirebaseAnalytics.h>
#import <AppsFlyerAdRevenue/AppsFlyerAdRevenue.h>

@interface NativeAdViewController () <ADXNativeAdFactoryDelegate, ADXNativeAdDelegate>
@property (nonatomic, strong) ADXNativeAd *nativeAd;
@end

@implementation NativeAdViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [[ADXNativeAdFactory sharedInstance] 
        setRenderingViewClass:@"<ADX_NATIVE_AD_UNIT_ID>" 
        renderingViewClass:[NativeAdView class]];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [[ADXNativeAdFactory sharedInstance] addDelegate:self];
    [[ADXNativeAdFactory sharedInstance] loadAd:@"<ADX_NATIVE_AD_UNIT_ID>"];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];    
    [[ADXNativeAdFactory sharedInstance] removeDelegate:self];
}

- (void)handleAdRevenue:(NSNumber *)revenue {
    // 1) Firebase Analytics
    [FIRAnalytics logEventWithName:kFIREventAdImpression
                        parameters: @{
        kFIRParameterAdPlatform: @"AD(X)",
        kFIRParameterAdFormat: @"NativeAd",
        kFIRParameterAdUnitName: @"ADX Native Ad",
        kFIRParameterCurrency: @"USD",
        kFIRParameterValue: revenune
    }];
    
    // 2) AppsFlyer
    NSDictionary * adRevenueParams = @{
        @"AdUnitName" : @"ADX Native Ad",
        @"AdType" : @"NativeAd",
    };
    
    AppsFlyerAdRevenue * appsFlyerAdRevenue = [AppsFlyerAdRevenue shared];
    [appsFlyerAdRevenue 
        logAdRevenueWithMonetizationNetwork:@"AD(X)"
        mediationNetwork:AppsFlyerAdRevenueMediationNetworkTypeCustom
        eventRevenue:revenune
        revenueCurrency:@"USD"
        additionalParameters:adRevenueParams];
}

#pragma mark - ADXNativeAdFactoryDelegate

- (void)onSuccess:(NSString *)adUnitId nativeAd:(ADXNativeAd *)nativeAd {
    NSLog(@"onSuccess : %@", adUnitId);

    if([adUnitId isEqualToString:@"<ADX_NATIVE_AD_UNIT_ID>"]) {
        self.nativeAd = nativeAd;
        self.nativeAd.delegate = self;
        
        __weak typeof(self) weakSelf = self;
        self.nativeAd.paidEventHandler = ^(double eCPM) {
            __strong typeof(self) strongSelf = weakSelf;
            if(!strongSelf) { return; }
            NSNumber * revenue = [NSNumber numberWithDouble:eCPM/1000];
            [strongSelf handleAdRevenue:revenue];
        };

        UIView *nativeAdView = [[ADXNativeAdFactory sharedInstance] 
            getNativeAdView:@"<ADX_NATIVE_AD_UNIT_ID>"];

        nativeAdView.frame = CGRectMake(0.0,
                                        100.0,
                                        320.0,
                                        300.0);
        [self.view addSubview:nativeAdView];
    }
}

- (void)onFailure:(NSString *)adUnitId {
    NSLog(@"onFailure : %@", adUnitId);
}

#pragma mark - ADXNativeAdDelegate

- (UIViewController *)viewControllerForPresentingModalView {
    return self;
}

@end
import UIKit
import ADXLibrary
import FirebaseAnalytics
import AppsFlyerAdRevenue

class NativeAdViewController: UIViewController {
    
    var nativeAd: ADXNativeAd?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        ADXNativeAdFactory.sharedInstance().setRenderingViewClass(
            "<ADX_NATIVE_AD_UNIT_ID>", 
            renderingViewClass: NativeAdView.self)
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        ADXNativeAdFactory.sharedInstance().add(self)
        ADXNativeAdFactory.sharedInstance().loadAd("<ADX_NATIVE_AD_UNIT_ID>")
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        ADXNativeAdFactory.sharedInstance().remove(self)
    }
    
    func handleAdRevenue(revenue:NSNumber) {
        // 1) Firebase Analytics
        Analytics.logEvent(
            AnalyticsEventAdImpression,
            parameters: [
                AnalyticsParameterAdPlatform: "AD(X)",
                AnalyticsParameterAdUnitName: "ADX Native Ad",
                AnalyticsParameterAdFormat: "NativeAd",
                AnalyticsParameterValue: revenune,
                AnalyticsParameterCurrency: "USD",
            ])
        
        // 2) AppsFlyer
        let adRevenueParams:[AnyHashable: Any] = [
            "AdUnitName" : "ADX Native Ad",
            "AdType" : "NativeAd",
        ]
        
        AppsFlyerAdRevenue.shared().logAdRevenue(
            monetizationNetwork: "AD(X)",
            mediationNetwork: .custom,
            eventRevenue: revenune,
            revenueCurrency: "USD",
            additionalParameters: adRevenueParams)
    }
}

extension NativeAdViewController: ADXNativeAdFactoryDelegate, 
    ADXNativeAdDelegate 
{    
    // MARK: - ADXNativeAdFactoryDelegate
    public func onSuccess(_ adUnitId: String!, nativeAd: ADXNativeAd!) {
        if (adUnitId == "<ADX_NATIVE_AD_UNIT_ID>") {
            self.nativeAd = nativeAd
            self.nativeAd?.delegate = self
            
            self.nativeAd?.paidEventHandler = { [weak self] eCPM in
                let revenue:NSNumber = (eCPM / 1000) as NSNumber
                self?.handleAdRevenue(revenue: revenue)
            }
            
            let nativeAdView = ADXNativeAdFactory.sharedInstance()
                .getNativeAdView("<ADX_NATIVE_AD_UNIT_ID>")
                
            nativeAdView?.frame = CGRect(
                x: (UIScreen.main.bounds.width - 300.0)/2,
                y: 100.0,
                width: 300.0,
                height: 270.0)
                                         
            self.view.addSubview(nativeAdView!)
        } else {
            print("fail to load")
        }
    }
    
    public func onFailure(_ adUnitId: String!) {
        print("onFailure :", adUnitId!)
    }
    
    // MARK: - ADXNativeAdDelegate
    func viewControllerForPresentingModalView() -> UIViewController {
        return self
    }
}

AdJust의 광고 매출 데이터 연동을 지원합니다. 상세한 내용은 를 확인 부탁드립니다.

AdJust의 AD(X) SDK 연동 가이드
ATT(App Tracking Transparency)
SDK 초기화
ADX iOS SDK