「SDK8 AdMob Mediation Native」修訂間的差異

出自TAMedia
跳至導覽 跳至搜尋
行 1: 行 1:
= 簡介 =
將說明如何將 TAmedia SDK 原生廣告與 Google AdMob 原生廣告([https://developers.google.com/admob/ios/native/advanced Native advanced])做 mediation 整合,關於 AdMob mediation 請參考:https://developers.google.com/admob/ios/mediate
= 串接準備 =
開始串接前請間確定已將 TAmedia SDK 整合至專案,並且完成[http://wiki.tamedia.com.tw/wiki/SDK8_Getting_Started_Guide#.E5.88.9D.E5.A7.8B.E5.8C.96.E8.A1.8C.E5.8B.95.E5.BB.A3.E5.91.8A_SDK 初始化 SDK]步驟,若您尚未完成請先參考[[SDK8 Getting Started Guide |開始使用教學]]完成相關設定。<br>
確認已成功串接 AdMob 原生廣告,若還沒請參考 Google 教學[https://developers.google.com/admob/ios/native/start AdMob原生廣告教學]。新增自訂義事件請參考[https://support.google.com/admob/answer/3083407 Google 說明]。<br>
最後,在專案中加入與 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 的客製化設定,可以自行參考教學文件進行設定,或保持預設值。
<nowiki>
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)
    }
}
</nowiki>
= TADMediatedUnifiedNativeAd =
將取得的 TAmedia 廣告整合後透過 AdMob 提供的介面回傳給 AdMob
<nowiki>
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
    }
}
</nowiki>
= 已知問題 =
點擊及曝光的事件當 TAmedia 廣告觸發後並沒有觸發 GADNativeAdDelegate 內 nativeAdDidRecordClick 及 nativeAdDidRecordImpression,目前推測為 Google SDK 的問題,若需要做相關紀錄須在 TADMediatedUnifiedNativeAd 內自行加入。
<nowiki>
extension TADMediatedUnifiedNativeAd: TADNativeAdDelegate {
    func nativeAdDidImpression(_ ad: TADNativeAd!) {
        GADMediatedUnifiedNativeAdNotificationSource.mediatedNativeAdDidRecordImpression(self)
        print("TADMediatedUnifiedNativeAd - nativeAdDidImpression")
        /// 若需要紀錄曝光事件請在此自行加入
    }
   
    func nativeAdDidClick(_ ad: TADNativeAd!) {
        GADMediatedUnifiedNativeAdNotificationSource.mediatedNativeAdDidRecordClick(self)
        print("TADMediatedUnifiedNativeAd - nativeAdDidClick")
        /// 若需要紀錄點擊事件請在此自行加入
    }
}
</nowiki>
<!--
= 簡介 =
= 簡介 =
將說明如何將 TAmedia SDK 原生廣告與 Google AdMob 原生廣告([https://developers.google.com/admob/ios/native/advanced Native advanced])做 mediation 整合,關於 AdMob mediation 請參考:https://developers.google.com/admob/ios/mediate
將說明如何將 TAmedia SDK 原生廣告與 Google AdMob 原生廣告([https://developers.google.com/admob/ios/native/advanced Native advanced])做 mediation 整合,關於 AdMob mediation 請參考:https://developers.google.com/admob/ios/mediate
行 514: 行 238:
}
}
</source>
</source>
-->

於 2023年4月7日 (五) 09:42 的修訂

簡介

將說明如何將 TAmedia SDK 原生廣告與 Google AdMob 原生廣告(Native advanced)做 mediation 整合,關於 AdMob mediation 請參考:https://developers.google.com/admob/ios/mediate

串接準備

首先先完成 mediation 基本 setup AdMob Mediation Setup, TADCustomEvent 將會透過此客製化 class 取得 TADNativeAd。


實作方式

TADCustomEventNative.swift

import Foundation
import GoogleMobileAds
import TAMediaAdsFramework


class TADCustomEventNative: NSObject {
    var tadNativeAd: TADNativeAd?
    var tadNativeAdView: TADNativeAdView?
    var mappedImages = [GADNativeAdImage]()
    var mapIcon: GADNativeAdImage?
    
    var delegate: GADMediationNativeAdEventDelegate?
    /// Completion handler called after ad load
    var completionHandler: GADMediationNativeLoadCompletionHandler?

    deinit {
        print("TADCustomEventNative - TADMediatedUnifiedNativeAd deinit")
    }
    
    func loadNativeAd(for adConfiguration: GADMediationNativeAdConfiguration,
        completionHandler: @escaping GADMediationNativeLoadCompletionHandler) {
        self.completionHandler = completionHandler
        let request = TADRequest()
        request.showLog = true
        let option = TADNativeAdOptions()
        /// 參見 http://wiki.tamedia.com.tw/iosDoc/Classes/TADNativeAdOptions.html
//        option.disableImageLoading = true //SDK 將不自動下載圖片
//        option.mediaPreferImage = true //只會呈現圖片廣告
//        option.startUnmuted = true     //影片廣告會以非靜音方式呈現
//        option.customControlsRequested = true //自行定義影音廣告的靜音/取消靜音、倒計時標籤和了解更多按鈕
//        option.allowAudioSessionControl = false //設為false則需自行設定影音廣告出現時 AVAudioSession 狀態
        tadNativeAd = TADNativeAd(adUnitId: adConfiguration.credentials.settings["parameter"] as? String)
        tadNativeAd?.delegate = self
        tadNativeAd?.load(request, withOption: option)
    }
    
    private func setup(nativeAd: TADNativeAd, nativeAdView: TADNativeAdView) {
        tadNativeAd = nativeAd
        tadNativeAdView = nativeAdView
        
        tadNativeAd?.delegate = 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)
        }
    }
}

extension TADCustomEventNative: 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
        
        setup(nativeAd: ad, nativeAdView: nativeAdView)
        
        if let handler = completionHandler {
            delegate = handler(self, nil)
        }
    }
    
    func nativeAd(_ ad: TADNativeAd!, didFailToReceiveAdWithError error: TADRequestError!) {
        if let handler = completionHandler {
            delegate = handler(nil, error)
        }
    }
    
    func nativeAdDidImpression(_ ad: TADNativeAd!) {
        print("TADCustomEventNative - nativeAdDidImpression")
        delegate?.reportImpression()
    }
    
    func nativeAdDidClick(_ ad: TADNativeAd!) {
        print("TADCustomEventNative - nativeAdDidClick")
        delegate?.reportClick()
    }

}

extension TADCustomEventNative: TADVideoStatusDelegate {
    func didStartVideo() {
        delegate?.didPlayVideo()
    }
    
    func didPlayVideo() {
        delegate?.didPlayVideo()
    }
    
    func didPauseVideo() {
        delegate?.didPauseVideo()
    }
    
    func didEndVideoPlayback() {
        delegate?.didEndVideo()
    }
    
    func didMuteVideo() {
        delegate?.didMuteVideo()
    }
    
    func didUnmuteVideo() {
        delegate?.didUnmuteVideo()
    }
}

extension TADCustomEventNative: GADMediationNativeAd {
    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 handlesUserClicks() -> Bool {
      return true
    }
    
    func handlesUserImpressions() -> Bool {
      return true
    }
    
    func didRender(in view: UIView, clickableAssetViews: [GADNativeAssetIdentifier : UIView], nonclickableAssetViews: [GADNativeAssetIdentifier : UIView], viewController: UIViewController) {
        guard let tadNativeAdView = tadNativeAdView else  { return }
        
        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 TADCustomEventNative {
    func fillSuperView(view: UIView) {
        view.frame = view.superview?.bounds ?? .zero
    }
}