Geniee-Wrapper-Ad-Banner-Adapter-Pubmatic-iOS 版本 1.0.2

Geniee-Wrapper-Ad-Banner-Adapter-Pubmatic-iOS 版本 1.0.2

Nguyen Duy Long“takaaki.kobayashi”Nguyen Thanh LongHironobu Yazaki 维护。



  • Geniee 提供

关于 GNWrapperAdSDK 的实现方法

摘要

为了通过 UPR 优化和 HB 提高收益,使用 GNWrapperAdSDK 获取 CustomTargeting 信息,并使用 Google AdManager 进行广告显示。
因此,我们使用 Firebase 的 RemoteConfig 功能和 Google AdManager。

  • 使用 Firebase 的 RemoteConfig 功能来获取广告框信息。
  • 根据上述获取的广告框信息,使用 GNWrapperAdSDK 获取 UnitId 和 CustomTargeting 信息。
  • 根据上述获取的 UnitId 和 CustomTargeting 信息,使用 Google AdManager 进行广告显示。

实现步骤

1. 应用程序项目设置

1.1 Firebase 初始设置

  1. 从Firebase管理界面创建项目并进行应用程序的注册。

  2. 在注册应用程序时,需要下载包含访问Firebase所需信息的文件GoogleService-Info.plist。请按照以下步骤进行下载。(或者,您也可以从已注册应用程序的设置界面下载文件。)

  3. 将下载的文件GoogleService-Info.plist添加到应用程序的项目中。

    有关Firebase的初始设置,请参考以下URL:将Firebase添加到iOS项目中

1.2. RemoteConfig初始设置

  1. 创建plist文件并记录default信息(广告信息)。当无法从Firebase的RemoteConfig功能获取广告信息时使用。

    使用以下JSON格式的字符串指定广告信息。

    第1层级 第2层级 类型 概括
    unit_id 字符串 用于AdManager的UnitId。
    timeout 数值 各个适配器中的请求等待时间(秒)。
    is_refresh 布尔值 刷新功能的启用/禁用。
    refresh_interval 数值 刷新时间(秒)。
    use_upr 布尔值 启用/禁用UPR。
    upr_settings 字典
    upr_key 字符串 UPR键。
    upr_value 字符串 UPR值。
    use_hb 布尔值 启用/禁用HeaderBidding。
    hb_list 列表
    hb_name 字符串 要使用的HB名称。
    hb_values 字符串 用于获取信息的信息。

    当hb_name="Prebid"时的"hb_values"

    第1层级 类型 概括
    prebid_server_host_type 字符串 Prebid信息(server_host_type)。
    "APPNEXUS"
    "RUBICON"
    "CUSTOM"
    prebid_server_host_url 字符串 Prebid信息(server_host_url)。
    prebid_server_account_id 字符串 Prebid信息(server_account_id)。
    config_id 字符串 Prebid信息(config_id)。
    ad_size 字符串 广告尺寸。
    宽x高

    当hb_name="Pubmatic"时的"hb_value"

    第1层级 类型 概括
    app_store_url 字符串 Pubmatic信息(app_store_url)。
    pub_id 字符串 Pubmatic信息(pub_id)。
    profile_id 字符串 Pubmatic信息(profile_id)。
    open_wrap_ad_unit_id 字符串 Pubmatic信息(UnitId)。
    ad_size 字符串 广告尺寸。
    宽x高

    示例代码

    {"unit_id":"/15671365/pm_sdk/PMSDK-Demo-App-Banner","timeout":3.2,"is_refresh":true,"refresh_interval":10,"use_upr":true,"upr_settings":{"upr_key":"geniee-upr","upr_value":"prod"},"use_hb":true,"hb_list":[{"hb_name":"Prebid","hb_values":{"prebid_server_host_type":"APPNEXUS","prebid_server_host_url":"","prebid_server_account_id":"bfa84af2-bd16-4d35-96ad-31c6bb888df0","config_id":"6ace8c7d-88c0-4623-8117-75bc3f0a2e45","ad_size":"320x50"}}, {"hb_name":"Pubmatic","hb_values":{"app_store_url":"https://play.google.com/store/apps/details?id=com.example.android&hl=en","pub_id":"156276","profile_id":"1165","open_wrap_ad_unit_id":"/15671365/pm_sdk/PMSDK-Demo-App-Banner","ad_size":"320x50"}},{"hb_name":"aaaa","hb_values":{}}]}
    

    关于Firebase RemoteConfig的初始设置,请参考以下URL。
    设置应用程序内的默认参数值

1.3. Framework的纳入

  1. 请在Podfile中添加以下描述。(如果没有Podfile,请使用命令pod init进行创建)

    • Firebase

       # Firebase
       pod 'Firebase/Core'
       pod 'Firebase/RemoteConfig'
      
    • GoogleMobileAdSDK

       # GoogleAdSDK
       pod 'Google-Mobile-Ads-SDK'
      
    • GNWrapperAdSDK

       # GNWrapperAdSDK
       pod 'Geniee-Wrapper-Ad-SDK-iOS'
      

      如果要在本地纳入GNWrapperAdSDK,请将"GNWrapperAdSDK.framework"纳入项目中,并在项目设置的Build Settings中指定Framework Search Paths的设置为"GNWrapperAdSDK.framework"的路径。

    • 在Prebid广告中使用情况

       # Prebid
       pod 'PrebidMobile'
       # GNHBPrebidBannerAdapter
       pod 'Geniee-Wrapper-Ad-Banner-Adapter-Prebid-iOS'
      

      如果要在本地纳入GNHBPrebidBannerAdapter,请将"GNHBPrebidBannerAdapter.framework"纳入项目中,并在项目设置的Build Settings中指定Framework Search Paths的设置为"GNHBPrebidBannerAdapter.framework"的路径。

    • 在Pubmatic广告中使用情况

       # PubMatic
       pod 'OpenWrapSDK'
       pod 'OpenWrapEventHandler/DFP'
       # GNHBPubmaticBannerAdapter
       pod 'Geniee-Wrapper-Ad-Banner-Adapter-Pubmatic-iOS'
      

      如果要在本地纳入GNHBPubmaticBannerAdapter,请将"GNHBPubmaticBannerAdapter.framework"纳入项目中,并在项目设置的Build Settings中指定Framework Search Paths的设置为"GNHBPubmaticBannerAdapter.framework"的路径。

  2. 使用命令pod install将Framework纳入项目中。

1.4. Google AdManager初始设置

  1. 选择用于广告显示的功能。
    在文件Info.plist中添加以下内容。
    如果不指定,则启动应用程序时可能会崩溃。

    功能 密钥 类型
    使用Google AdManager的情况 GADIsAdManagerApp 布尔值 YES

2. 应用程序的处理实现

2.1. 初始化处理

应用程序启动后处理(AppDelegate)中添加Firebase的初始化处理。

・objective-c

@import Firebase;

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    [FIRApp configure];
    return YES;
}
@end

・swift

import Firebase

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        FirebaseApp.configure()
        return true
    }
}

2.2. Firebase处理

有关详细Firebase的RemoteConfig功能,请参阅以下URL。

参考资料:在iOS中使用Firebase Remote Config

2.2.1 初始化处理
  1. 使用Firebase功能,请添加import处理。

    ・objective-c

    @import Firebase;

    ・swift

    import Firebase
  2. 方法viewDidLoad中执行以下初始化操作。

    • 获取RemoteConfig对象。
    • 在RemoteConfig功能获取信息失败时指定默认值(remoteConfig.setDefaults处理中指定plist文件(1.2.创建))

    ・objective-c

    @interface ViewController ()
    @property(nonatomic, weak) FIRRemoteConfig *remoteConfig;
    @end
    
    @implementation ViewController
    
    // For Firebase.
    static NSString* const FIREBASE_DEFAULT_REMOTE_CONFIG = @"DefaultRemoteConfig";
    static double const FIREBASE_FETCH_TIME_INTERVAL_SECONDS = 720;
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        _remoteConfig = [FIRRemoteConfig remoteConfig];
        FIRRemoteConfigSettings *remoteConfigSettings = [[FIRRemoteConfigSettings alloc] init];
        remoteConfigSettings.minimumFetchInterval = FIREBASE_FETCH_TIME_INTERVAL_SECONDS;
        _remoteConfig.configSettings = remoteConfigSettings;
        [_remoteConfig setDefaultsFromPlistFileName:FIREBASE_DEFAULT_REMOTE_CONFIG];    
    }

    ・swift

    // For Firebase.
    let FIREBASE_DEFAULT_REMOTE_CONFIG: String = "DefaultRemoteConfig"
    let FIREBASE_FETCH_TIME_INTERVAL_SECONDS: Double = 720
    
    var remoteConfig: RemoteConfig! = nil
    
    override func viewDidLoad() {
        self.remoteConfig = RemoteConfig.remoteConfig()
        self.remoteConfig.setDefaults(fromPlist: FIREBASE_DEFAULT_REMOTE_CONFIG)
    }
2.2.2 获取广告栏信息处理
  1. 使用remoteConfig.fetch处理向Firebase发送广告栏信息的检索请求。
    如果在初始化过程中已注册默认值,则在检索失败的情况下也会返回注册的默认值,因此不需要特别的错误检查。

    ・objective-c

    static NSString* const FIREBASE_KEY_CONFIG = @"GNWrapperConfig_iOS";
    
    [_remoteConfig fetchWithCompletionHandler:^(FIRRemoteConfigFetchStatus status, NSError *error) {
        if (status == FIRRemoteConfigFetchStatusSuccess) {
            [self.remoteConfig activateWithCompletion:^(BOOL changed, NSError * _Nullable error) {
                NSString *data = self.remoteConfig[FIREBASE_KEY_CONFIG].stringValue;
            }];
        } else {
            NSString *data = self.remoteConfig[FIREBASE_KEY_CONFIG].stringValue;
        }
    }];

    ・swift

    let FIREBASE_KEY_CONFIG: String = "GNWrapperConfig_iOS"
    
    remoteConfig.fetch(withExpirationDuration: TimeInterval(FIREBASE_FETCH_TIME_INTERVAL_SECONDS)) { (status, error) -> Void in
        if (status == .success) {
            self.remoteConfig.activate() { (changed, error) in
                let data = self.remoteConfig[self.FIREBASE_KEY_CONFIG].stringValue
            }
        } else {
            let data = self.remoteConfig[self.FIREBASE_KEY_CONFIG].stringValue
        }
    }

2.3. GNWrapperAdSDK处理

2.3.1 初期処理
  1. 使用GNWrapperAdSDK機能时,需要添加导入处理。

    ・objective-c

    #import <GNWrapperAdSdk/GNWrapperAdSDK.h>

    ・创建Swift桥接头部并添加以下内容。

    #import <GNWrapperAdSdk/GNWrapperAdSDK.h>
  2. 方法viewDidLoad中执行以下初始化操作。

    • GNWrapperAdBanner对象创建、初始化及addView处理。

    ・objective-c

    // Ad Size.
    #define ADMANAGER_AD_SIZE kGADAdSizeBanner
    
    @interface ViewController () <GNWrapperAdDelegate>
    @property(nonatomic, retain) GNWrapperAdBanner *gnWrapperAd;
    @property(nonatomic, retain) GNCustomTargetingParams *targetParams;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [GNWrapperAdSDK setLogPriority:GNLogPriorityInfo];
        _gnWrapperAdBanner = [[GNWrapperAdBanner alloc] init];
        [_gnWrapperAd setHidden:true];
        [self.view addSubview:_gnWrapperAd];
        _gnWrapperAd.frame = CGRectMake(0, 0, ADMANAGER_AD_SIZE.size.width, ADMANAGER_AD_SIZE.size.height);
        _gnWrapperAd.center = CGPointMake(self.view.center.x, self.view.center.y);
    }
    
    @end

    ・swift

    let ADMANAGER_AD_SIZE: GADAdSize = kGADAdSizeBanner
    
    var gnWrapperAd: GNWrapperAdBanner! = nil
    var targetParams: GNCustomTargetingParams! = nil
    
    override func viewDidLoad() {
        GNWrapperAdSDK.setLogPriority(GNLogPriorityInfo)	    self.gnWrapperAd = GNWrapperAdBanner.init()
        self.gnWrapperAd.isHidden = true
        self.view.addSubview(self.gnWrapperAd)
        self.gnWrapperAd.frame = CGRect(x: 0, y: 0, width: ADMANAGER_AD_SIZE.size.width, height: ADMANAGER_AD_SIZE.size.height)
        self.gnWrapperAd.center = CGPoint(x: self.view.center.x, y: self.view.center.y)
    }
2.3.2 로드 처리
  1. 在remoteConfig的fetch处理完成后,执行以下处理。

    ・objective-c

    NSString *data = self.remoteConfig[FIREBASE_KEY_CONFIG].stringValue;
    
    [self.gnWrapperAd initWithLoad:data delegate:self viewController:self];

    ・swift

    let data = self.remoteConfig[self.FIREBASE_KEY_CONFIG].stringValue
    
    self.gnWrapperAd.initWithLoad(data, delegate: self, viewController: self)
  2. 添加Delegate处理。

    ・objective-c

    // GNWrapperAdBannerDelegate
    
    - (void)onComplete:(GNWrapperAdBanner*)view params:(GNCustomTargetingParams *)params {
        _targetParams = params;
    }
    
    - (void)onError:(GNWrapperAdBanner*)view error:(NSError *)error{
        NSLog(@"ViewController: onError = %@", error.localizedDescription);
    }

    ・swift

    // GNWrapperAdBannerDelegate
    extension ViewController: GNWrapperAdBannerDelegate {
    
        func onComplete(_ view:GNWrapperAdBanner, params: GNCustomTargetingParams) {
            self.targetParams = params
        }
    
        func onError(_ view:GNWrapperAdBanner) {
            print("ViewController: onError")
        }
    
    }

2.4. 广告显示处理(AdManager)

关于详细的AdManager实现方法,请参考以下URL。

参考网站:

2.4.1 初期処理
  1. 使用AdManager功能时,需要添加导入处理。

    ・objective-c

    @import GoogleMobileAds;

    ・swift

    import GoogleMobileAds
  2. 方法viewDidLoad中执行以下初始化操作。

    • DFPBannerView对象的创建、初始化及addView处理。

    ・objective-c

    @interface ViewController () <GADBannerViewDelegate, GADAppEventDelegate, GNWrapperAdDelegate>
    @property(nonatomic, strong) DFPBannerView *bannerView;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        _bannerView = [[DFPBannerView alloc] initWithAdSize:ADMANAGER_AD_SIZE];
        _bannerView.delegate = self;
        _bannerView.appEventDelegate = self;
        _bannerView.rootViewController = self;
        [self.view addSubview:_bannerView];
        _bannerView.center = CGPointMake(self.view.center.x, self.view.center.y);
    }
    
    @end

    ・swift

    var bannerView: DFPBannerView! = nil
    
    override func viewDidLoad() {
        self.bannerView = DFPBannerView.init(adSize: ADMANAGER_AD_SIZE)
        self.bannerView.delegate = self
        self.bannerView.appEventDelegate = self
        self.bannerView.rootViewController = self
        self.view.addSubview(self.bannerView)
        self.bannerView.center = CGPoint(x: self.view.center.x, y: self.view.center.y)
    }
  3. 添加Delegate处理,并为目前显示的广告View设置到GNWrapperAdSDK。

    • GADBannerViewDelegate。

    ・objective-c

    // GADBannerViewDelegate
    
    - (void)adViewDidReceiveAd:(DFPBannerView *)adView {
        [_gnWrapperAd requestRefresh:_bannerView];
    }
    
    - (void)adView:(DFPBannerView *)adView
    didFailToReceiveAdWithError:(GADRequestError *)error {
        NSLog(@"ViewController: didFailToReceiveAdWithError: %@", [error localizedDescription]);
    }

    ・swift

    extension ViewController: GADBannerViewDelegate {
    
        func adViewDidReceiveAd(_ bannerView: GADBannerView) {
            self.gnWrapperAd.requestRefresh(self.bannerView)
        }
    
        func adView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: GADRequestError) {
            print("ViewController: didFailToReceiveAdWithError: \(error.localizedDescription)")
        }
        
    }
    • GADAppEventDelegate。

    ・objective-c

    /// GADAppEventDelegate.
    
    - (void)adView:(DFPBannerView *)banner didReceiveAppEvent:(NSString *)name withInfo:(NSString *)info {
    }

    ・swift

    extension ViewController: GADAppEventDelegate {
    
        func adView(_ banner: GADBannerView, didReceiveAppEvent name: String, withInfo info: String?) {
        }
    
    }
2.4.2 로드 처리
  1. 在GNWrapperAdSDK的onComplete处理时,执行以下处理。

    ・objective-c

    - (void)onComplete:(GNWrapperAd*)view params:(GNCustomTargetingParams *)params {
        _targetParams = params;
    
        [_gnWrapperAd setHidden:true];
        [_bannerView setHidden:false];
        _bannerView.adUnitID = _targetParams.unitId;
    
        DFPRequest * request = [DFPRequest request];
        request.customTargeting = _targetParams.targetParams;
        [self.bannerView loadRequest:request];
    }

    ・swift

    func onComplete(_ view:GNWrapperAd, params: GNCustomTargetingParams) {
        self.targetParams = params
    
        self.gnWrapperAd.isHidden = true
        self.bannerView.isHidden = false
        self.bannerView.adUnitID = self.targetParams.unitId
    
        let request: DFPRequest = DFPRequest.init()
        request.customTargeting = (self.targetParams.targetParams as! [AnyHashable : Any])
        self.bannerView.load(request)
    }
  2. 如果广告框信息包含"Prebid"信息,则在AdManager加载完成时,添加以下处理。

    ・objective-c

    func adViewDidReceiveAd(_ bannerView: GADBannerView) {
    	self.gnWrapperAd.requestRefresh(self.bannerView)
        if ("Prebid" == self.gnWrapperAd.getAfterLoadedGAMBanner()) {
            AdViewUtils.findPrebidCreativeSize(self.bannerView,
                success: { (size) in
                    self.bannerView.resize(GADAdSizeFromCGSize(size))
                },
                failure: { (error) in
                    print("ViewController: adViewDidReceiveAd error = \(error.localizedDescription)")
                }
            )
        }
    }

    ・swift

    - (void)adViewDidReceiveAd:(DFPBannerView *)adView {
        [_gnWrapperAd requestRefresh:_bannerView];
        if ([@"Prebid" isEqualToString:[_gnWrapperAd getAfterLoadedGAMBanner]]) {
            [AdViewUtils findPrebidCreativeSize:adView
                                        success:^(CGSize size) {
                                            [adView resize:GADAdSizeFromCGSize(size)];
                                        } failure:^(NSError * _Nonnull error) {
                                            [GNLog logWithPriority:GNLogPriorityError message:[NSString stringWithFormat:@"ViewController: adViewDidReceiveAd error = %@", [error localizedDescription]]];
                                        }];
        }
    }
  3. 如果广告框信息包含"Pubmatic"信息,则在AdManager的AppEvent时,添加以下处理。

    ・objective-c

    func adView(_ banner: GADBannerView, didReceiveAppEvent name: String, withInfo info: String?) {
        if ("pubmaticdm" == name) {
            if (self.gnWrapperAd.isNecessaryShow()) {
                self.gnWrapperAd.isHidden = false
                self.bannerView.isHidden = true
    
                self.gnWrapperAd.show()
                self.gnWrapperAd.requestRefresh(self.gnWrapperAd)
            }
        }
    }

    ・swift

    - (void)adView:(DFPBannerView *)banner didReceiveAppEvent:(NSString *)name withInfo:(NSString *)info {
        if ([@"pubmaticdm" isEqualToString:name]) {
            if ([_gnWrapperAd isNecessaryShow]) {
                [_gnWrapperAd setHidden:false];
                [_bannerView setHidden:true];
    
                [_gnWrapperAd show];
                [_gnWrapperAd requestRefresh:_gnWrapperAd];
            }
        }
    }

备注

  • 有关一系列实现代码的示例,请参考示例应用程序。
  • 从iOS14开始,使用IDFA需要用户的明确许可。(本补偿措施自2021年初起实施。实施方法请参考此处。)