iOS Guidelines | 네이티브 광고

네이티브 광고는 앱 콘텐츠와 자연스럽게 결합하여 사용자 경험을 유지하면서 높은 관심을 유도하는 광고 형태입니다. 앱 인터페이스에 가장 어울리는 레이아웃을 선택하고 맞춤 설정할 수 있습니다. 네이티브 광고는 뉴스, 유틸리티, 커뮤니케이션 앱에 적합합니다.

간단한 과정을 통해 네이티브 광고 수익화를 시작해 보십시오.

네이티브 광고 설정

앱을 추가한 후 NATIVE CONTENT를 선택하여 네이티브 광고 유형에 맞는 배치를 생성합니다.

옵션에서 적합한 레이아웃을 선택합니다.

네이티브 광고 배치를 생성하면 배치 ID를 사용할 수 있습니다.

네이티브 광고 생성

  1. 헤더를 가져오고 ViewController.swift 파일에서 네이티브 광고 인스턴스를 선언합니다. ViewController 헤더 파일의 내용은 다음과 같습니다.
    import UIKit
    import InMobiSDK
    class ViewController: UIViewController, IMNativeDelegate {
        var nativeContent: String?
        var native: IMNative?
    }
    		
  2. 네이티브 광고 오브젝트 인스턴스화 ViewController.swift 파일의 내용은 다음과 같습니다.
    override func viewDidLoad() {
            super.viewDidLoad()
            native = IMNative.init(placementId: 13020009)
            native?.delegate = self
            native?.load()
    }
    		
  3. UIViewControllerdeinit 메소드에서 델리게이트를 nil로 설정합니다. 또는 배너를 릴리즈할 때 언제든지 설정할 수 있습니다.
    deinit {
           	 // perform the deinitialization
            	native?.delegate = nil
        	}
    		
  4. 광고 상태 콜백의 경우, IMNative의 델리게이트 속성을 구현합니다. 다음 콜백이 지원됩니다.
         /**
         * Notifies the delegate that the native ad has finished loading
         */
        public func nativeDidFinishLoading(_ native: IMNative!) {
            NSLog("[ViewController %@]", #function)
        }
        /**
         * Notifies the delegate that the native ad has failed to load with error.
         */
        public func native(_ native: IMNative!, didFailToLoadWithError error: IMRequestStatus!) {
            NSLog("[ViewController %@]", #function)
            NSLog("Native ad failed to load with error %@", error)
        }
        /**
         * Notifies the delegate that the native ad would be presenting a full screen content.
         */
        public func nativeWillPresentScreen(_ native: IMNative!) {
            NSLog("[ViewController %@]", #function)
        }
        /**
         * Notifies the delegate that the native ad has presented a full screen content.
         */
        public func nativeDidPresentScreen(_ native: IMNative!) {
            NSLog("[ViewController %@]", #function)
        }
        /**
         * Notifies the delegate that the native ad would be dismissing the presented full screen content.
         */
        public func nativeWillDismissScreen(_ native: IMNative!) {
            NSLog("[ViewController %@]", #function)
        }
        /**
         * Notifies the delegate that the native ad has dismissed the presented full screen content.
         */
        public func nativeDidDismissScreen(_ native: IMNative!) {
            NSLog("[ViewController %@]", #function)
        }
        /**
         * Notifies the delegate that the user will be taken outside the application context.
         */
        public func userWillLeaveApplication(from native: IMNative!) {
            NSLog("[ViewController %@]", #function)
        }
        /**
         * Notifies the delegate that the nativeStrands ad impression has been tracked
         */
        public func nativeAdImpressed(_ native: IMNative!){
            NSLog("[ViewController %@]", #function)
        }
    		
  5. 네이티브 광고 렌더링 및 노출 추적

    nativeAdDidFinishLoading 콜백을 받으면 네이티브 광고를 불러옵니다. nativeAd?.adContent 오브젝트는 네이티브 광고 콘텐츠를 제공합니다. 이를 새 UIView나 기존 UIView에 표시할 수 있습니다. 네이티브 광고 콘텐츠는 InMobi 포털에서 선택한 형식에 맞는 에셋으로 구성됩니다.

    예를 들어 뉴스 뷰 플로의 경우, 콘텐츠는 다음 에셋으로 구성됩니다.

    • 제목 - 광고 제목, 문자열
    • 콘텐츠 - 광고 설명, 문자열
    • 랜딩 URL - 광고 클릭 시 열 URL
    • 아이콘 - 아이콘 세부 사항, 즉, JSON 형식의 URL, 높이, 너비

    아래와 같이 뷰의 다양한 컴포넌트에 에셋을 사용할 수 있습니다.

    if (native?.adContent != nil)  {
             do{
                    let data = native?.adContent.data(using: .utf8)
    /* Convert the native JSON content to NSDictionary.*/
                    let jsonDict = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! NSDictionary
                    let nativeJsonDict = NSMutableDictionary(dictionary: jsonDict)
                    // The native JSON is parsed and can be used.
                    // To differentiate the native JSON dictionary from other data
                    nativeJsonDict.setObject(true, forKey: "isAd" as NSCopying)
    /* Examples of fetching the image and title are listed below*/
    	/*Fetch the image url from the dictionary in the following way.*/
    	let icon = dict?.object(forKey: "icon_xhdpi") as? NSDictionary
    let url = icon?.object(forKey: "url")
    /*Fetch the tile from the dictionary*/
    	let title = dict?.object(forKey: "title") as? String
                    if (items.count > 0) {
                        items.insert(nativeJsonDict, at: 1)
                    }
                 } catch {
                    print("Error Caught")
                }
            }
    		

    다음 값을 사용하여 필요한 뷰를 결합합니다. 예를 들어, 테이블 뷰를 생성하고 광고가 테이블 뷰의 한 셀에 있는 경우, tableView:cellForRowAtIndexPath: 메소드 내 뷰를 렌더링합니다. 예시는 다음과 같습니다.

     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cellIdentifier: String = "someIdentifier"
            var cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)
            if (cell == nil) {
                cell = UITableViewCell(style: .value1, reuseIdentifier: cellIdentifier)
            }
            let row = indexPath.row
            let dict = items[row] as? NSDictionary
            let isAd = dict?.object(forKey:"isAd") as? Int
       // If this is the row where the ad should be displayed,
            if  (isAd != nil) {
                let titleLabel: UILabel = UILabel()
                let descriptionLabel: UILabel = UILabel()
                let imageView: UIImageView = UIImageView()
                titleLabel.text = dict?.object(forKey: "title") as? String
                descriptionLabel.text = dict?.object(forKey: "subtitle") as? String
                let icon = dict?.object(forKey: "icon_xhdpi") as? NSDictionary
                let urlString = icon?.object(forKey: "url") as? String
                if let url = URL.init(string: urlString!)
                {
                    let data = NSData(contentsOf:url)
                    if data != nil {
                        imageView.image = UIImage(data:data! as Data)
                    }
                }
                titleLabel.frame = CGRect(<FRAME_FOR_YOUR_LABEL>)
                descriptionLabel.frame = CGRect(<FRAME_FOR_YOUR_LABEL>)
                imageView.frame = CGRect(<FRAME_FOR_YOUR_IMAGE>)
    //Add subviews to the cell
                cell?.addSubview(titleLabel)
                cell?.addSubview(descriptionLabel)
                cell?.addSubview(imageView)
                //Bind the cell to the native ad as it has rendered the ad.
                IMNative.bindNative(native, to: cell)
            }
            else {
                // This is a content item
                // UnBind the cell as it might be a reused cell from a native ad.
                IMNative.unBindView(cell)
            }
            return cell!
    }
    		

    다음 예시는 네이티브 광고 콘텐츠에 접근하여 이를 뉴스 플로에 렌더링하는 방법입니다. 다른 플로에 맞는 콘텐츠 에셋은 선택한 뷰에 따라 다를 수 있습니다.

    광고 콘텐츠가 렌더링되면 다음을 호출하여 이를 보고합니다.

    bindNative(_ native: IMNative!, to view: UIView!)
    IMNative.bindNative(native, to: renderedUIViewInstance)
    		

    여기에서 'renderedUIViewInstance'는 렌더링된 네이티브 광고를 나타냅니다. 즉, 테이블 뷰의 경우, 네이티브 광고를 셀 중 하나에 렌더링했다면 광고를 렌더링한 후 해당 셀을 이 메소드에 전달해야 합니다.

    이 셀이 다른 콘텐츠나 다른 네이티브 광고 인스턴스에 재사용될 때 IMNative 클래스 메소드인 unBindView:(UIView*)view 메소드를 호출합니다. 광고를 불러오지 않았다면 두 메소드 모두 실패하게 됩니다.

  6. 클릭 수 추적 및 랜딩 페이지 처리

    reportAdClick:(NSDictionary*) 매개변수를 호출하여 네이티브 광고 인스턴스에 클릭을 보고합니다.

    매개변수 사전에는 퍼블리셔가 네이티브 광고 인스턴스에 제공하고자 하는 추가 정보를 포함시킬 수 있습니다.

    클릭을 보고하고 랜딩 페이지를 직접 열려면 nativeAd?.reportAdClick(paramsDictionary)를 호출합니다.

    • 광고 콘텐츠에 랜딩 페이지 영역이 있는 경우, reportAdClick 메소드를 호출한 후 네이티브 광고의 랜딩 페이지를 처리해야 합니다.
    • 랜딩 페이지가 'landing_url' 키와 함께 네이티브 광고 콘텐츠에 표시됩니다. 또한, 랜딩 페이지 URL이 외부에서 열립니다.
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
        {
            print(items[indexPath.row])
            let dict = items[indexPath.row] as? NSDictionary        
            if (dict?.object(forKey:"isAd") as? Int) != nil {
                let landingUrl = dict?.value(forKey: "landingURL") as? String
                native?.reportAdClick(nil)
                if(landingUrl != nil) {
                    let landingPageURL = URL.init(string:landingUrl!)
                    UIApplication.shared.open(landingPageURL!)
                }
            }
            tableView.deselectRow(at: indexPath, animated: true)
        }
    		

    클릭을 보고하고 InMobi에서 랜딩 페이지를 열도록 하려면 를 호출합니다.

    native?.reportAdClickAndOpenLandingURL(paramsDictionary) 
       func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
        {
            print(items[indexPath.row])
            let dict = items[indexPath.row] as? NSDictionary
            if (dict?.object(forKey:"isAd") as? Int) != nil {
                native?.reportAdClickAndOpenLandingURL(nil)
            }
            tableView.deselectRow(at: indexPath, animated: true)
        }
    		

CreativeID 검색 중

진행되고 있는 모든 광고 품질 검사를 피해나와, 관련성이없고 불쾌한 소재 또는 사용자에게 혼란을주는 광고를 보여줌으로써 앱의 사용자 경험을 손상시키는 불량 광고주가 가끔 있습니다. 이러한 상황을 극복하기 위해 광고 인스턴스의 creativeID를 검색하고 InMobi 담당자에게 암호화 된 creativeID를보고 할 수 있습니다.

mNativeAd.creativeId // mNativeAd는 예제 인스턴스입니다.

통합 테스트

  1. InMobi 포털에서 테스트 모드를 구성합니다.

    Tools - Diagnostics로 이동하여 Test Mode를 Global ON 또는 Selective ON으로 설정합니다.

    광고를 처음으로 연동하려는 경우 Test ModeGlobal ON으로 설정합니다.
    특정 디바이스에 선택적으로 테스트 트래픽을 활성화하려는 경우

    이미 이 광고에 이전 버전의 SDK를 연동한 적이 있으므로 몇 개의 디바이스에 테스팅을 제한해야 하는 경우
    Test ModeSelective ON으로 설정합니다.

    디바이스 섹션에서:

    1. Device ID 상자에 디바이스 ID를 입력합니다.
    2. Device Name 상자에서 이름을 설정합니다.
    3. Add Device를 클릭하여 테스트 디바이스를 추가합니다.

    이미 구성된 디바이스가 있는 경우, 해당 디바이스를 선택하면 테스트 모드가 활성화됩니다.

    참고: 앱을 정식으로 출시하기 전에 반드시 테스트 모드를 비활성화하십시오. 이를 비활성화하지 않으면 앱을 수익화할 수 없습니다.

    이제 테스트를 진행할 수 있습니다.

    디바이스 ID 확인

    디바이스 ID는 기본적으로 IDFA 또는 IFA(Identifier for Advertising)입니다. 디바이스 ID를 확인하는 가장 쉬운 방법은 SDK 로그 수준을 “디버그”로 설정하는 것입니다. 디버그 로그를 활성화하려면 아래와 같이 이를 AppDelegate.swift 파일 내의 didFinishLaunchingWithOptions 메소드에 추가하십시오.

    func application(_ application: UIApplication, didFinishLaunchingWithOptions 
    launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
            //Initialize InMobi SDK with your account ID
            IMSdk.initWithAccountID("Insert InMobi account ID here")
            IMSdk.setLogLevel(.debug)
            // Do your stuff.
            return true
        }
    		

    디버그 모드에서 디바이스 ID는 다음과 같이 XCode 개발자 콘솔에 로깅됩니다. “퍼블리셔 디바이스 ID는 <디바이스-ID>입니다.”

    이 디바이스 ID를 Device ID 상자에 입력할 수 있습니다.

  2. Diagnostics 탭에서 광고 및 광고 요청에 대한 피드백을 확인할 수도 있으며, 이는 특히 연동 과정에서 유용하게 활용할 수 있습니다.

  3. 네이티브 광고를 불러왔을 때 다음 주요 InMobi SDK 로그가 콘솔에 표시되어야 합니다.

    [InMobi] InMobi SDK initialized with account id: <your account id here>

    [InMobi] Fetching native ad for placement id: <your placement id here>

    [InMobi] Publisher device id is <device id here>

    [InMobi] Native ad successfully fetched for placement id: <your placement id here>

  4. 이제 InMobi 테스트 광고를 앱에서 확인할 수 있습니다.
  5. 광고를 생성하기 전에 SDK가 올바르게 초기화되지 않을 경우, 일반적으로 다음 로그가 표시됩니다.

    ** ERROR ** [InMobi] ___ Please initialize the SDK before creating a <ad format> ad.

    ** ERROR ** [InMobi] ___ Account id cannot be null or empty. Please provide a valid Account id.

    [InMobi] Invalid account id passed to init. Please provide a valid account id.

모든 주요 로그는 다음 표에서 확인할 수 있습니다.

SDK 초기화

시나리오 로그 수준 로그
Publisher passed null or empty account id (퍼블리셔가 null 또는 빈 계정 ID를 전달함) 오류 Account id cannot be null or empty. Please provide a valid Account id.
Publisher passed a valid account id (퍼블리셔가 올바른 계정 ID를 전달함) 디버그 InMobi SDK initialized with account id: <account id>
Publisher passed an invalid account Id (퍼블리셔가 잘못된 계정 ID를 전달함) 오류 Invalid account id passed to init. Please provide a valid account id.
Newer version of SDK is available (SDK 버전이 업데이트됨) 디버그 A newer version (ver. 6.0.0) of the InMobi SDK is available! You are currently on an older version (ver. 5.3.1). Download the latest InMobi SDK from http://www.inmobi.com/products/sdk/#downloads

광고 공통

시나리오 로그 수준 로그
Ad requested when no network available (네트워크를 사용할 수 없을 때 광고 요청됨) 오류 Network not reachable currently. Please try again.
Ad requested when ad state is loading or available (광고 상태를 불러오는 중이거나 사용할 수 있을 때 광고 요청됨) 오류 An ad load is already in progress. Please wait for the load to complete before requesting for another ad (Placement id :<placement id> ).
Ad requested when ad is viewed by user (사용자가 광고를 시청 중일 때 광고 요청됨) 오류 An ad is currently being viewed by the user. Please wait for the user to close the ad before requesting for another ad (Placement id : <placement id> ).
Publisher device Id (퍼블리셔 디바이스 ID) 디버그 Publisher device id is <Device Id>

네이티브 광고

시나리오 로그 수준 로그
Publisher created a native ad without initializing the SDK (퍼블리셔가 SDK를 초기화하지 않고 네이티브 광고를 생성함) 오류 Please initialize the SDK before creating a native ad
Publisher created a native ad with an invalid placement id (퍼블리셔가 잘못된 배치 ID로 네이티브 광고를 생성함) 오류 Please provide a valid placement id to create a native ad
Publisher called load on a native (퍼블리셔가 네이티브 광고에 로드를 호출함) 디버그 Fetching an native ad for placement id: <placement id>
Successfully fetched ad (광고를 가져옴) 디버그 Native ad successfully fetched for placement id: <placement id>
Failed to fetch the ad (광고를 가져오지 못함) 오류 Failed to fetch native ad for placement id:<Placement id> with error:<Status code / message>
Publisher called bind on native ad with view (퍼블리셔가 뷰를 가진 네이티브 광고에 bind를 호출함) 디버그 Binding Native ad to view: <view info> for placement id: <placement id>
Publisher called unbind on native ad with view (퍼블리셔가 뷰를 가진 네이티브 광고에 unbind를 호출함) 디버그 Unbinding Native ad from view :<view info> for placement id: <placement id>
Started loading Context Code (컨텍스트 코드를 불러오기 시작함) 디버그 Started loading Native ad markup in the webview for placement id: <placement id>
Context Code loaded (컨텍스트 코드 불러옴) 디버그 Successfully loaded Native ad markup in webview for placement id: <placement id>
Viewable impression recorded (조회 가능 노출이 기록됨) 디버그 Viewable impression was recorded for Native ad with placement id: <placement id>
Old logs Null view attached Call prepareToTrackImpressions method with null view (이전 로그, null 뷰 연결됨, null 뷰를 가진 prepareToTrackImpressions 메소드 호출) 오류 Please pass a non-null view object to bindNative
View already attached Call prepareToTrackImpressions method with already attached view (뷰가 이미 연결됨, 이미 연결된 뷰를 가진 prepareToTrackImpressions 메소드 호출) 오류 Failed to attach view
Attaching view before receiving ad Call prepareToTrackImpressions method even if ad is not received from server (광고를 불러오기 전에 뷰 연결하는 중, 서버에서 광고를 불러오지 않은 상태로 prepareToTrackImpressions 메소드 호출) 오류 Please wait for the ad to finish loading before making a call to prepareToTrackImpressions
reportAdClick in invalid ad state Call reportAdClick method with null view or invalid view (reportAdClick의 광고 상태가 올바르지 않음, null 뷰 또는 올바르지 않은 뷰를 가진 reportAdClick 메소드 호출) 오류 reportAdClick call made in wrong state

고급

사용자 정의 노출 수 및 클릭 수 추적

사용자 정의 노출 추적 및 클릭을 보고하려면 IMCustomNative 클래스를 사용합니다.

import InMobiSDK
	
  • 사용자 정의 노출 추적 스크립트를 사용하여 노출을 추적하려면 다음 메소드를 사용합니다.

    renderedUIViewInstance 및 사용자 정의 추적 스크립트를 매개변수로 전달합니다.

    open class func bindNative(_ native: IMNative!, to view: UIView!, withImpressionTrackerScript impressio	nTracker: String!)
    		
  • 사용자 정의 노출 추적 URL을 사용하여 노출을 추적하려면 다음 메소드를 사용합니다.

    renderedUIViewInstance 및 사용자 정의 추적 URL을 매개변수로 전달합니다.

    open class func bindNative(_ native: IMNative!, to view: UIView!, withImpressionTrackerURL impressionTrackerURL: URL!)
    		
  • 아래 섹션에 기재된 대로 랜딩 페이지를 직접 엽니다.
    • 사용자 정의 클릭 추적 스크립트를 사용하여 클릭을 보고하려면 다음 메소드를 사용합니다.

      클릭 매개변수 및 사용자 정의 클릭 추적 스크립트를 매개변수로 전달합니다.

      open func reportAdClick(_ extras: [AnyHashable : Any]!, withCustomClickTrackerScript clickTracker: String!)
      			
    • 사용자 정의 클릭 추적 URL을 사용하여 클릭을 보고하려면 다음 메소드를 사용합니다.

      클릭 매개변수 및 사용자 정의 클릭 추적 URL을 매개변수로 전달합니다.

      open func reportAdClick(_ extras: [AnyHashable : Any]!, withCustomClickTrackerURL clickTrackerURL: URL!)
      			
  • 랜딩 페이지를 직접 열지 않으려면 다음 메소드를 사용합니다. InMobi에서 랜딩 페이지를 열게 됩니다.
    • 사용자 정의 클릭 추적 스크립트를 사용하여 클릭을 보고하려면 다음 메소드를 사용합니다.

      클릭 매개변수 및 사용자 정의 클릭 추적 스크립트를 매개변수로 전달합니다.

      open func reportAdClickAndOpenLandingURL(_ extras: [AnyHashable : Any]!, withCustomClickTrackerScript clickTracker: String!)
      			
    • 사용자 정의 클릭 추적 URL을 사용하여 클릭을 보고하려면 다음 메소드를 사용합니다.

      클릭 매개변수 및 사용자 정의 클릭 추적 URL을 매개변수로 전달합니다.

      open func reportAdClickAndOpenLandingURL(_ extras: [AnyHashable : Any]!, withCustomClickTrackerURL clickTrackerURL: URL!)
      			

viewcontroller 클래스의 내용은 다음과 같습니다.

override func viewDidLoad() {
        super.viewDidLoad()
        customNative = IMCustomNative.init(placementId: "Insert native Placement ID Here")
        customNative?.delegate = self
        customNative?.load()
}
//Track impressions using custom script
IMCustomNative.bindNative(customNative, to: UIRenderedView, withImpressionTrackerScript: "custom script here")
IMCustomNative.bindNative(customNative, to: UIRenderedView, withImpressionTrackerURL: "custom impression tracking URL here")
customNative?.reportAdClick("clicks params", withCustomClickTrackerScript: "custom script here")
customNative?.reportAdClick("clicks params", withCustomClickTrackerURL: “custom click tracking URL here”)
customNative?.reportAdClickAndOpenLandingURL("clicks params", withCustomClickTrackerScript: "custom script here")
customNative?.reportAdClickAndOpenLandingURL("clicks params",  withCustomClickTrackerURL: “custom impression tracking URL here”)