Commit 3d527ae8 by Shailesh Aher

[IOS-127]: Tercept SDK manager imaplementd using Tercept SDK

parent 3df923be
...@@ -253,6 +253,8 @@ ...@@ -253,6 +253,8 @@
F2D8A706269D88D10060F36A /* x86_64.swiftinterface in Resources */ = {isa = PBXBuildFile; fileRef = F2D8A6DF269D88D10060F36A /* x86_64.swiftinterface */; }; F2D8A706269D88D10060F36A /* x86_64.swiftinterface in Resources */ = {isa = PBXBuildFile; fileRef = F2D8A6DF269D88D10060F36A /* x86_64.swiftinterface */; };
F2D8A707269D88D10060F36A /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = F2D8A6E0269D88D10060F36A /* README.md */; }; F2D8A707269D88D10060F36A /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = F2D8A6E0269D88D10060F36A /* README.md */; };
F2D8A708269D88D10060F36A /* TerceptSDK.podspec in Resources */ = {isa = PBXBuildFile; fileRef = F2D8A6E1269D88D10060F36A /* TerceptSDK.podspec */; }; F2D8A708269D88D10060F36A /* TerceptSDK.podspec in Resources */ = {isa = PBXBuildFile; fileRef = F2D8A6E1269D88D10060F36A /* TerceptSDK.podspec */; };
F2D8A70D269D93210060F36A /* TerceptSDKManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2D8A70C269D93210060F36A /* TerceptSDKManager.swift */; };
F2D8A722269F05200060F36A /* Dependency.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2D8A721269F05200060F36A /* Dependency.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
...@@ -549,6 +551,8 @@ ...@@ -549,6 +551,8 @@
F2D8A6DF269D88D10060F36A /* x86_64.swiftinterface */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = x86_64.swiftinterface; sourceTree = "<group>"; }; F2D8A6DF269D88D10060F36A /* x86_64.swiftinterface */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = x86_64.swiftinterface; sourceTree = "<group>"; };
F2D8A6E0269D88D10060F36A /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; }; F2D8A6E0269D88D10060F36A /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
F2D8A6E1269D88D10060F36A /* TerceptSDK.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TerceptSDK.podspec; sourceTree = "<group>"; }; F2D8A6E1269D88D10060F36A /* TerceptSDK.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TerceptSDK.podspec; sourceTree = "<group>"; };
F2D8A70C269D93210060F36A /* TerceptSDKManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerceptSDKManager.swift; sourceTree = "<group>"; };
F2D8A721269F05200060F36A /* Dependency.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dependency.swift; sourceTree = "<group>"; };
FD761FE0D947B3A79121A941 /* Pods-OneWeatherNotificationServiceExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OneWeatherNotificationServiceExtension.release.xcconfig"; path = "Target Support Files/Pods-OneWeatherNotificationServiceExtension/Pods-OneWeatherNotificationServiceExtension.release.xcconfig"; sourceTree = "<group>"; }; FD761FE0D947B3A79121A941 /* Pods-OneWeatherNotificationServiceExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OneWeatherNotificationServiceExtension.release.xcconfig"; path = "Target Support Files/Pods-OneWeatherNotificationServiceExtension/Pods-OneWeatherNotificationServiceExtension.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
...@@ -640,6 +644,7 @@ ...@@ -640,6 +644,7 @@
CD1237C1255D5C5900C98139 /* 1Weather */ = { CD1237C1255D5C5900C98139 /* 1Weather */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
F2D8A720269F05150060F36A /* Dependency */,
CD615FCA2655297B00B717DB /* Extensions */, CD615FCA2655297B00B717DB /* Extensions */,
CEC7D8EC2639FE1B00B8836D /* InApps */, CEC7D8EC2639FE1B00B8836D /* InApps */,
CE14445D2638B6A8008E2162 /* 1Weather.entitlements */, CE14445D2638B6A8008E2162 /* 1Weather.entitlements */,
...@@ -1373,6 +1378,7 @@ ...@@ -1373,6 +1378,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
F2D8A6B6269D88D10060F36A /* lib */, F2D8A6B6269D88D10060F36A /* lib */,
F2D8A70C269D93210060F36A /* TerceptSDKManager.swift */,
); );
path = TerceptSDK; path = TerceptSDK;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -1441,6 +1447,14 @@ ...@@ -1441,6 +1447,14 @@
path = Project; path = Project;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
F2D8A720269F05150060F36A /* Dependency */ = {
isa = PBXGroup;
children = (
F2D8A721269F05200060F36A /* Dependency.swift */,
);
path = Dependency;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
...@@ -1495,7 +1509,7 @@ ...@@ -1495,7 +1509,7 @@
CD1237B7255D5C5900C98139 /* Project object */ = { CD1237B7255D5C5900C98139 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 1240; LastSwiftUpdateCheck = 1250;
LastUpgradeCheck = 1250; LastUpgradeCheck = 1250;
TargetAttributes = { TargetAttributes = {
CD1237BE255D5C5900C98139 = { CD1237BE255D5C5900C98139 = {
...@@ -1772,6 +1786,7 @@ ...@@ -1772,6 +1786,7 @@
CDDE8D7F262EED4D00267931 /* MapLegendWeatherView.swift in Sources */, CDDE8D7F262EED4D00267931 /* MapLegendWeatherView.swift in Sources */,
87C171F425FF7A4000DA3464 /* PopularCitiesManager.swift in Sources */, 87C171F425FF7A4000DA3464 /* PopularCitiesManager.swift in Sources */,
CD85797326721DD400CC4CDA /* UIColor+Highlight.swift in Sources */, CD85797326721DD400CC4CDA /* UIColor+Highlight.swift in Sources */,
F2D8A722269F05200060F36A /* Dependency.swift in Sources */,
CD67616A262575CD0079D273 /* MapLegendGradientView.swift in Sources */, CD67616A262575CD0079D273 /* MapLegendGradientView.swift in Sources */,
CD593BCC2608A4F200C93428 /* ForecastDailyCell.swift in Sources */, CD593BCC2608A4F200C93428 /* ForecastDailyCell.swift in Sources */,
CD866A72260F6A5300E96A5C /* SettingsDetailsCell.swift in Sources */, CD866A72260F6A5300E96A5C /* SettingsDetailsCell.swift in Sources */,
...@@ -1804,6 +1819,7 @@ ...@@ -1804,6 +1819,7 @@
CE6BE4942634170800626822 /* USStateCode.swift in Sources */, CE6BE4942634170800626822 /* USStateCode.swift in Sources */,
CD37D3F3260DF4FB002669D6 /* SettingsCoordinator.swift in Sources */, CD37D3F3260DF4FB002669D6 /* SettingsCoordinator.swift in Sources */,
CD1237C3255D5C5900C98139 /* AppDelegate.swift in Sources */, CD1237C3255D5C5900C98139 /* AppDelegate.swift in Sources */,
F2D8A70D269D93210060F36A /* TerceptSDKManager.swift in Sources */,
CD39F2F225DE94C4009FE398 /* SunPhaseCell.swift in Sources */, CD39F2F225DE94C4009FE398 /* SunPhaseCell.swift in Sources */,
CD6B304325726AD1004B34B3 /* DefaultTheme.swift in Sources */, CD6B304325726AD1004B34B3 /* DefaultTheme.swift in Sources */,
CEC8FBB2263976240001A6BF /* OnboardingCoordinator.swift in Sources */, CEC8FBB2263976240001A6BF /* OnboardingCoordinator.swift in Sources */,
......
...@@ -80,8 +80,16 @@ public class AdView: UIView { ...@@ -80,8 +80,16 @@ public class AdView: UIView {
guard let placementName = self.placementName else { return nil } guard let placementName = self.placementName else { return nil }
return configManager.adConfig.placement(named: placementName) return configManager.adConfig.placement(named: placementName)
} }
private lazy var terceptManager: TerceptSDKManager = {
return Dependency.shared.getDependency()
}()
private var adTracker : CustomTargetedAdLifeCycleTrackable? {
guard let adUnitID = placement?.adUnitId else { return nil }
return terceptManager.getTracker(with: adUnitID)
}
internal var configManager: AdConfigManager { internal var configManager: AdConfigManager {
return AdConfigManager.shared return AdConfigManager.shared
} }
...@@ -138,8 +146,7 @@ public class AdView: UIView { ...@@ -138,8 +146,7 @@ public class AdView: UIView {
log.warning("failed to guess the top view controller.") log.warning("failed to guess the top view controller.")
return return
} }
bannerView = NativeBannerContainerView(adUnitId: placement.adUnitId, adType: adType, rootViewController: topViewController) bannerView = NativeBannerContainerView(adUnitId: placement.adUnitId, adType: adType, adLifeCycleTracker: adTracker, rootViewController: topViewController)
if let bannerView = bannerView { if let bannerView = bannerView {
bannerView.loggingAlias = logName bannerView.loggingAlias = logName
...@@ -328,6 +335,14 @@ extension AdView { ...@@ -328,6 +335,14 @@ extension AdView {
self.updateA9BidObject(requestAdWhenDone: false) self.updateA9BidObject(requestAdWhenDone: false)
} }
let addTrackerKeys = adTracker?.getCustomTrackableKeys()
if addTrackerKeys?.isEmpty == false {
keywords = keywords ?? [:]
for keyValue in addTrackerKeys ?? [:] {
keywords?[keyValue.key] = keyValue.value
}
}
return keywords return keywords
} }
} }
......
...@@ -23,7 +23,7 @@ class NativeBannerContainerView: UIView { ...@@ -23,7 +23,7 @@ class NativeBannerContainerView: UIView {
private var adLoader: NativeAdLoader private var adLoader: NativeAdLoader
private let adType: AdType private let adType: AdType
private var adLifeCycleTracker: AdLifeCycleTrackable?
weak var delegate: NativeBannerContainerViewDelegate? weak var delegate: NativeBannerContainerViewDelegate?
public var loggingAlias: String? { public var loggingAlias: String? {
...@@ -32,9 +32,13 @@ class NativeBannerContainerView: UIView { ...@@ -32,9 +32,13 @@ class NativeBannerContainerView: UIView {
} }
} }
init(adUnitId: String, adType: AdType, rootViewController: UIViewController) { init(adUnitId: String,
adType: AdType,
adLifeCycleTracker: AdLifeCycleTrackable? = nil,
rootViewController: UIViewController) {
self.adType = adType self.adType = adType
self.adLoader = NativeAdLoader(adUnitId: adUnitId, rootViewController: rootViewController, adTypes: [.native, .gamBanner]) self.adLoader = NativeAdLoader(adUnitId: adUnitId, rootViewController: rootViewController, adTypes: [.native, .gamBanner])
self.adLifeCycleTracker = adLifeCycleTracker
super.init(frame: .zero) super.init(frame: .zero)
self.adLoader.delegate = self self.adLoader.delegate = self
} }
...@@ -85,10 +89,12 @@ extension NativeBannerContainerView: NativeAdLoaderDelegate { ...@@ -85,10 +89,12 @@ extension NativeBannerContainerView: NativeAdLoaderDelegate {
addAsSubview(view: adView) addAsSubview(view: adView)
print("native ad loader: \(String(describing: nativeAd.headline))") print("native ad loader: \(String(describing: nativeAd.headline))")
delegate?.adLoader(adLoader, didReceive: nativeAd) delegate?.adLoader(adLoader, didReceive: nativeAd)
adLifeCycleTracker?.recordAdState(.adLoaded)
} }
func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: Error) { func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: Error) {
delegate?.adLoader(adLoader, didFailToReceiveAdWithError: error) delegate?.adLoader(adLoader, didFailToReceiveAdWithError: error)
adLifeCycleTracker?.recordAdState(.adFailedToLoad)
} }
func adLoader(_ adLoader: GADAdLoader, didReceived bannerView: GAMBannerView) { func adLoader(_ adLoader: GADAdLoader, didReceived bannerView: GAMBannerView) {
...@@ -97,6 +103,7 @@ extension NativeBannerContainerView: NativeAdLoaderDelegate { ...@@ -97,6 +103,7 @@ extension NativeBannerContainerView: NativeAdLoaderDelegate {
addAsSubview(view: bannerView) addAsSubview(view: bannerView)
delegate?.adLoader(adLoader, didReceived: bannerView) delegate?.adLoader(adLoader, didReceived: bannerView)
adLifeCycleTracker?.recordAdState(.adLoaded)
} }
} }
...@@ -105,15 +112,26 @@ extension NativeBannerContainerView: GADBannerViewDelegate { ...@@ -105,15 +112,26 @@ extension NativeBannerContainerView: GADBannerViewDelegate {
func bannerViewDidRecordImpression(_ bannerView: GADBannerView) { func bannerViewDidRecordImpression(_ bannerView: GADBannerView) {
log.info("Impression") log.info("Impression")
analytics(log: .ANALYTICS_AD_IMPRESSION) analytics(log: .ANALYTICS_AD_IMPRESSION)
adLifeCycleTracker?.recordAdState(.adImpression)
} }
func bannerViewWillPresentScreen(_ bannerView: GADBannerView) { func bannerViewWillPresentScreen(_ bannerView: GADBannerView) {
log.info("Click (will present screen)") log.info("Click (will present screen)")
analytics(log: .ANALYTICS_AD_CLICKED) analytics(log: .ANALYTICS_AD_CLICKED)
adLifeCycleTracker?.recordAdState(.adOpened)
} }
func adViewWillLeaveApplication(_ bannerView: GADBannerView) { func adViewWillLeaveApplication(_ bannerView: GADBannerView) {
log.info("Click (will leave application)") log.info("Click (will leave application)")
analytics(log: .ANALYTICS_AD_CLICKED) analytics(log: .ANALYTICS_AD_CLICKED)
adLifeCycleTracker?.recordAdState(.adLeftApplication)
}
func bannerViewDidRecordClick(_ bannerView: GADBannerView) {
adLifeCycleTracker?.recordAdState(.adClicked)
}
func bannerViewWillDismissScreen(_ bannerView: GADBannerView) {
adLifeCycleTracker?.recordAdState(.adClosed)
} }
} }
//
// Dependency.swift
// 1Weather
//
// Created by Shailesh on 14/07/21.
//
import Foundation
/*
Adding the class, to reduce use of single instances
whichever thing that we can use this to provide as and when dependency values and functionalities needed
*/
protocol DependencyRepresentable {
init()
}
class Dependency {
static var shared = Dependency()
private init() { }
private var dependencyMap: [String: DependencyRepresentable] = [:]
func getDependency<T: DependencyRepresentable>() -> T {
guard let dependency: T = dependencyMap[String(describing: T.self)] as? T else {
let dependency = T()
dependencyMap[String(describing: T.self)] = dependency
return dependency
}
return dependency
}
}
...@@ -356,7 +356,7 @@ class CCPAHelper { ...@@ -356,7 +356,7 @@ class CCPAHelper {
//MARK: - Models //MARK: - Models
private struct CCPAInitialConsent: Encodable, CustomDebugStringConvertible { struct CCPAInitialConsent: Encodable, CustomDebugStringConvertible {
var id: String = "" var id: String = ""
var advertisingId = "" var advertisingId = ""
var appVersion = "" var appVersion = ""
......
//
// TerceptSDKManager.swift
// 1Weather
//
// Created by Shailesh on 13/07/21.
//
import UIKit
import TerceptSDK
protocol TerceptOpimizable: AdEventLoggable {
func fetch(_ adunits: [String]?)
func setCustomParameters(_ params: [String : String])
func sendEventsData()
func getCustomTargetingKeys(_ adunit: String?) -> [String : String?]
func initParams(_ IDFA: String, _ IDFV: String, _ params: [String : Any]?)
}
protocol AdEventLoggable {
@discardableResult func logEvent(_ adunit: String?, _ event: String?, _ customParams: [String : Any]) -> Bool
}
extension TerceptOptimization: TerceptOpimizable { }
final class TerceptSDKManager: AdEventLoggable, DependencyRepresentable {
private let optimizable: TerceptOpimizable
private struct Constants {
static let DFPCode: String = "120348554"
static var IDFA: String {
CCPAInitialConsent.getInstance().advertisingId
}
static var IDFV: String {
CCPAInitialConsent.getInstance().id
}
static var version: String {
CCPAInitialConsent.getInstance().appVersion
}
}
required init() {
optimizable = TerceptOptimization(Constants.DFPCode)
updateKeys()
registerNotifications()
fetchIfAvailable()
}
init(optimizable: TerceptOpimizable = TerceptOptimization(Constants.DFPCode), adUnitIDs: [String]) {
self.optimizable = optimizable
updateKeys()
optimizable.fetch(adUnitIDs)
registerNotifications()
fetchIfAvailable()
}
private func updateKeys() {
optimizable.initParams(Constants.IDFA, Constants.IDFV, ["appVersion": Constants.version])
}
private func registerNotifications() {
NotificationCenter.default.addObserver(self,
selector: #selector(handleSwitchToBackground),
name: UIApplication.didEnterBackgroundNotification,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(fetchIfAvailable),
name: .adConfigChanged,
object: nil)
}
@objc private func fetchIfAvailable() {
guard let placements = ConfigManager.shared.config.adConfig.placements,
!placements.isEmpty else { return }
//TODO: Check what happens if we register more ads than what we show
register(adUnitIDs: placements.values.map { $0.adUnitId })
}
private func register(adUnitIDs: [String]) {
optimizable.fetch(adUnitIDs)
}
func getTracker(with adUnitId: String) -> TerceptAdTracker {
return TerceptAdTracker(adUnitId: adUnitId,
logger: self,
customKeys: optimizable.getCustomTargetingKeys(adUnitId))
}
func setCustomParameters(_ params: [String : String]) {
optimizable.setCustomParameters(params)
}
@discardableResult func logEvent(_ adunit: String?, _ event: String?, _ customParams: [String : Any]) -> Bool {
return optimizable.logEvent(adunit, event, customParams)
}
@objc private func handleSwitchToBackground() {
optimizable.sendEventsData()
}
}
enum AdLifeCycleState: String {
case adClicked = "onAdClicked"
case adClosed = "onAdClosed"
case adFailedToLoad = "onAdFailedToLoad"
case adImpression = "onAdImpression"
case adLeftApplication = "onAdLeftApplication"
case adLoaded = "onAdLoaded"
case adOpened = "onAdOpened"
}
protocol CustomTargetProvidable {
func getCustomTrackableKeys() -> [String: String?]
}
protocol AdLifeCycleTrackable {
func recordAdState(_ state: AdLifeCycleState)
}
typealias CustomTargetedAdLifeCycleTrackable = CustomTargetProvidable & AdLifeCycleTrackable
/// Get instance of TerceptAdTracker from TerceptSDKManager, using func getTracker(with adUnitId: String) method.
final class TerceptAdTracker: CustomTargetedAdLifeCycleTrackable {
private let adUnitId: String
private let customKeys: [String: String?]
private let logger: AdEventLoggable
fileprivate init(adUnitId: String, logger: AdEventLoggable, customKeys: [String: String?]) {
self.adUnitId = adUnitId
self.customKeys = customKeys
self.logger = logger
}
func getCustomTrackableKeys() -> [String: String?] {
return customKeys
}
func recordAdState(_ state: AdLifeCycleState) {
logger.logEvent(adUnitId, state.rawValue, [:])
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment