SDK8 AdMob Mediation Native
簡介
將說明如何將 TAmedia SDK 原生廣告與 Google AdMob 原生廣告(Native advanced)做 mediation 整合,關於 AdMob mediation 請參考:https://developers.google.com/admob/ios/mediate
串接準備
開始串接前請間確定已將 TAmedia SDK 整合至專案,並且完成初始化 SDK步驟,若您尚未完成請先參考開始使用教學完成相關設定。
確認已成功串接 AdMob 原生廣告,若還沒請參考 Google 教學AdMob原生廣告教學。新增自訂義事件請參考Google 說明。
最後,在專案中加入與 Custom Event 對應的 Class,其中 Custom Event 的 Class Name 需要和專案新增的 Class Name 保持一致,例如新增的 Class Name 為 TADCustomNative,Custom Event 的 Class Name 則必須是 專案名稱.TADCustomNative。(以 Swift 編寫的專案需加上專案名稱;若為以 OC編寫,則放入 Class Name)
整合方式
整合 AdMob 原生廣告需要兩個客製化 class,TADCustomNative 及 TADMediatedUnifiedNativeAd,可直接下載加入專案內或參考下方範例
TADCustomNative
AdMob 將透過這支程式來取得 TAmedia 廣告,其中關於 TADNativeAdOptions 及 TADMediaView 的客製化設定,可以自行參考教學文件進行設定,或保持預設值。
import Foundation import GoogleMobileAds import TAMediaAdsFramework class TADCustomNative: NSObject, GADCustomEventNativeAd { weak var delegate: GADCustomEventNativeAdDelegate? private var nativeAd: TADNativeAd? override required init() { super.init() } deinit { print("TADCustomNative deinit") } func request(withParameter serverParameter: String, request: GADCustomEventRequest, adTypes: [Any], options: [Any], rootViewController: UIViewController) { loadTADNativeAd(adUnitId: serverParameter) } func handlesUserClicks() -> Bool { return true } func handlesUserImpressions() -> Bool { return true } } extension TADCustomNative { private func loadTADNativeAd(adUnitId: String) { let request = TADRequest() request.showLog = true let option = TADNativeAdOptions() ///參見 http://wiki.tamedia.com.tw/iosDoc/Classes/TADNativeAdOptions.html // option.disableImageLoading = true //SDK 將不自動下載圖片 TADMediatedUnifiedNativeAd 內需更改 // option.mediaPreferImage = false //只會呈現圖片廣告 // option.startUnmuted = true //影片廣告會以非靜音方式呈現 // option.customControlsRequested = true // // option.allowAudioSessionControl = false //設為false則需自行設定影音廣告出現時 AVAudioSession 狀態 nativeAd = TADNativeAd(adUnitId: adUnitId) nativeAd?.delegate = self nativeAd?.load(request, withOption: option) } } extension TADCustomNative: TADNativeAdDelegate { func nativeAdDidReceive(_ ad: TADNativeAd!) { let nativeAdView = TADNativeAdView() let mediaView = TADNativeMediaView(frame: .zero) mediaView.mediaContent = ad.adContent.mediaContent ///參見 http://wiki.tamedia.com.tw/iosDoc/Classes/TADNativeMediaView.html // mediaView.setCallToActionVisible(false) //是否顯示 CTA 按鈕 // mediaView.setCallToActionTextSize(12) //設定 CTA 文字大小 // mediaView.setVolumeImageSize(24) //設定影音廣告靜音圖片大小 // mediaView.setVideoCountdownTextSize(17) //設定影音倒數文字大小 nativeAdView.addSubview(mediaView) nativeAdView.mediaView = mediaView let mapNativeAd = TADMediatedUnifiedNativeAd(tadNativeAd: ad, tadNativeAdView: nativeAdView) delegate?.customEventNativeAd(self, didReceive: mapNativeAd) } func nativeAd(_ ad: TADNativeAd!, didFailToReceiveAdWithError error: TADRequestError!) { delegate?.customEventNativeAd(self, didFailToLoadWithError: error) } }
TADMediatedUnifiedNativeAd
將取得的 TAmedia 廣告整合後透過 AdMob 提供的介面回傳給 AdMob
import Foundation import GoogleMobileAds import TAMediaAdsFramework class TADMediatedUnifiedNativeAd: NSObject { var tadNativeAd: TADNativeAd var tadNativeAdView: TADNativeAdView var mappedImages = [GADNativeAdImage]() var mapIcon: GADNativeAdImage? init(tadNativeAd: TADNativeAd, tadNativeAdView: TADNativeAdView) { self.tadNativeAdView = tadNativeAdView self.tadNativeAd = tadNativeAd super.init() self.tadNativeAd.delegate = self self.tadNativeAdView.mediaView?.statusDelegate = self guard let mediaContent = tadNativeAd.adContent.mediaContent else { return } if let tadImage = mediaContent.image1200x627?.image { let adImage = GADNativeAdImage(image: tadImage) tadNativeAdView.mediaView?.setMainImage(image: tadImage) mappedImages.append(adImage) } if let iconImage = tadNativeAd.adContent.iconSquare?.image { mapIcon = GADNativeAdImage(image: iconImage) } } deinit { print("TADMediatedUnifiedNativeAd - TADMediatedUnifiedNativeAd deinit") } } extension TADMediatedUnifiedNativeAd: TADNativeAdDelegate { func nativeAdDidImpression(_ ad: TADNativeAd!) { GADMediatedUnifiedNativeAdNotificationSource.mediatedNativeAdDidRecordImpression(self) print("TADMediatedUnifiedNativeAd - nativeAdDidImpression") } func nativeAdDidClick(_ ad: TADNativeAd!) { GADMediatedUnifiedNativeAdNotificationSource.mediatedNativeAdDidRecordClick(self) print("TADMediatedUnifiedNativeAd - nativeAdDidClick") } } extension TADMediatedUnifiedNativeAd: TADVideoStatusDelegate { func didStartVideo() { GADMediatedUnifiedNativeAdNotificationSource.mediatedNativeAdDidPlayVideo(self) } func didPlayVideo() { GADMediatedUnifiedNativeAdNotificationSource.mediatedNativeAdDidPlayVideo(self) } func didPauseVideo() { GADMediatedUnifiedNativeAdNotificationSource.mediatedNativeAdDidPauseVideo(self) } func didEndVideoPlayback() { GADMediatedUnifiedNativeAdNotificationSource.mediatedNativeAdDidEndVideoPlayback(self) } func didMuteVideo() {} func didUnmuteVideo() {} } extension TADMediatedUnifiedNativeAd: GADMediatedUnifiedNativeAd { var headline: String? { return tadNativeAd.adContent.longSubject } var images: [GADNativeAdImage]? { return mappedImages } var body: String? { return tadNativeAd.adContent.body } var icon: GADNativeAdImage? { return mapIcon } var callToAction: String? { return tadNativeAd.adContent.callToAction } var starRating: NSDecimalNumber? { return nil } var store: String? { return nil } var price: String? { return nil } var advertiser: String? { return nil } var extraAssets: [String: Any]? { return nil } var mediaView: UIView? { return tadNativeAdView.mediaView } var hasVideoContent: Bool { guard let mediaContent = tadNativeAd.adContent.mediaContent else { return false } return mediaContent.isVideoContent } func didRender(in view: UIView, clickableAssetViews: [GADNativeAssetIdentifier: UIView], nonclickableAssetViews: [GADNativeAssetIdentifier: UIView], viewController: UIViewController) { view.subviews.first { $0 is TADNativeAdView }?.removeFromSuperview() view.insertSubview(tadNativeAdView, at: 0) fillSuperView(view: tadNativeAdView) if let titleLabel = clickableAssetViews[GADNativeAssetIdentifier.headlineAsset] as? UILabel { titleLabel.isUserInteractionEnabled = true tadNativeAdView.longSubjectLabel = titleLabel } if let bodyLabel = clickableAssetViews[GADNativeAssetIdentifier.bodyAsset] as? UILabel { bodyLabel.isUserInteractionEnabled = true tadNativeAdView.bodyLabel = bodyLabel } if let ctaLabel = clickableAssetViews[GADNativeAssetIdentifier.callToActionAsset] { ctaLabel.isUserInteractionEnabled = true tadNativeAdView.callToActionView = ctaLabel } if let icon = clickableAssetViews[GADNativeAssetIdentifier.iconAsset] as? UIImageView { icon.isUserInteractionEnabled = true tadNativeAdView.squareImgeView = icon } if let mediaView = clickableAssetViews[GADNativeAssetIdentifier.mediaViewAsset], let tadMediaView = tadNativeAdView.mediaView { mediaView.subviews.first { $0 is TADNativeMediaView }?.removeFromSuperview() mediaView.addSubview(tadMediaView) fillSuperView(view: tadMediaView) } tadNativeAdView.nativeAd = tadNativeAd } func didUntrackView(_ view: UIView?) { print("TADMediatedUnifiedNativeAd - didUntrackView") tadNativeAdView.removeFromSuperview() tadNativeAdView.mediaView?.removeFromSuperview() } } extension TADMediatedUnifiedNativeAd { func fillSuperView(view: UIView) { view.frame = view.superview?.bounds ?? .zero } }
已知問題
點擊及曝光的事件當 TAmedia 廣告觸發後並沒有觸發 GADNativeAdDelegate 內 nativeAdDidRecordClick 及 nativeAdDidRecordImpression,目前推測為 Google SDK 的問題,若需要做相關紀錄須在 TADMediatedUnifiedNativeAd 內自行加入。
extension TADMediatedUnifiedNativeAd: TADNativeAdDelegate { func nativeAdDidImpression(_ ad: TADNativeAd!) { GADMediatedUnifiedNativeAdNotificationSource.mediatedNativeAdDidRecordImpression(self) print("TADMediatedUnifiedNativeAd - nativeAdDidImpression") /// 若需要紀錄曝光事件請在此自行加入 } func nativeAdDidClick(_ ad: TADNativeAd!) { GADMediatedUnifiedNativeAdNotificationSource.mediatedNativeAdDidRecordClick(self) print("TADMediatedUnifiedNativeAd - nativeAdDidClick") /// 若需要紀錄點擊事件請在此自行加入 } }