-
Notifications
You must be signed in to change notification settings - Fork 316
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CF-106] Fetch AdServices Token #1519
Changes from 34 commits
f3131f9
d322c7c
dbcdc4c
c557ba5
882a936
21aa633
cc93cdb
9706097
c98031a
03357e7
bcd58a2
5c957b7
4c6332c
4a952c4
3811408
e02c0d2
81f2628
47ecfff
d51c37f
f2014f8
8923389
e5dea3a
10a073b
352de9e
bae8e3c
d4a552a
c181dc7
f29aedb
d6d3dc7
67b3e7a
4d800ac
2b21373
61c28a3
26b02f7
a11742a
6a7697b
60db73b
1df28a0
3e3d383
cc98cbe
839bc8d
2c16386
42bbabc
3de0061
d9f757b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,10 +19,16 @@ import UIKit | |
import WatchKit | ||
#endif | ||
|
||
#if canImport(AdServices) | ||
import AdServices | ||
#endif | ||
|
||
enum AttributionFetcherError: Error { | ||
|
||
case identifierForAdvertiserUnavailableForPlatform | ||
case identifierForAdvertiserFrameworksUnavailable | ||
case adServicesNotAvailable | ||
case adServicesTokenFetchError | ||
|
||
} | ||
|
||
|
@@ -67,35 +73,22 @@ class AttributionFetcher { | |
return nil | ||
} | ||
|
||
func afficheClientAttributionDetails(completion: @escaping ([String: NSObject]?, Error?) -> Void) { | ||
// Should match available platforms in | ||
// https://developer.apple.com/documentation/iad/adclient?language=swift | ||
#if os(iOS) | ||
guard let afficheClientProxy = attributionFactory.afficheClientProxy() else { | ||
Logger.warn(Strings.attribution.search_ads_attribution_cancelled_missing_ad_framework) | ||
completion(nil, AttributionFetcherError.identifierForAdvertiserFrameworksUnavailable) | ||
return | ||
// should match OS availability in https://developer.apple.com/documentation/ad_services | ||
@available(iOS 14.3, macOS 11.1, macCatalyst 14.3, *) | ||
func adServicesToken() -> String? { | ||
#if canImport(AdServices) | ||
if let attributionToken = try? AAAttribution.attributionToken() { | ||
return attributionToken | ||
} else { | ||
Logger.warn(Strings.attribution.adservices_token_fetch_failed) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe do a do/catch instead of |
||
return nil | ||
} | ||
afficheClientProxy.requestAttributionDetails(completion) | ||
#else | ||
completion(nil, AttributionFetcherError.identifierForAdvertiserUnavailableForPlatform) | ||
Logger.warn(Strings.attribution.adservices_not_supported) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice |
||
return nil | ||
#endif | ||
} | ||
|
||
var isAuthorizedToPostSearchAds: Bool { | ||
// Should match platforms that require permissions detailed in | ||
// https://developer.apple.com/app-store/user-privacy-and-data-use/ | ||
if !appTrackingTransparencyRequired { | ||
return true | ||
} | ||
|
||
if #available(iOS 14.0.0, tvOS 14.0.0, *) { | ||
return isAuthorizedToPostSearchAdsInATTRequiredOS | ||
} | ||
|
||
return true | ||
} | ||
|
||
var authorizationStatus: FakeTrackingManagerAuthorizationStatus { | ||
// should match OS availability here: https://rev.cat/app-tracking-transparency | ||
guard #available(iOS 14.0.0, tvOS 14.0.0, macOS 11.0.0, *) else { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,7 +35,6 @@ class AttributionPoster { | |
self.subscriberAttributesManager = subscriberAttributesManager | ||
} | ||
|
||
// swiftlint:disable:next function_body_length | ||
func post(attributionData data: [String: Any], | ||
fromNetwork network: AttributionNetwork, | ||
networkUserId: String?) { | ||
|
@@ -88,46 +87,27 @@ class AttributionPoster { | |
} | ||
|
||
if !newData.isEmpty { | ||
if network == .appleSearchAds { | ||
postSearchAds(newData: newData, | ||
network: network, | ||
appUserID: currentAppUserID, | ||
newDictToCache: newDictToCache) | ||
} else { | ||
postSubscriberAttributes(newData: newData, | ||
network: network, | ||
appUserID: currentAppUserID, | ||
newDictToCache: newDictToCache) | ||
} | ||
postSubscriberAttributes(newData: newData, | ||
network: network, | ||
appUserID: currentAppUserID, | ||
newDictToCache: newDictToCache) | ||
} | ||
} | ||
|
||
func postAppleSearchAdsAttributionIfNeeded() { | ||
guard attributionFetcher.isAuthorizedToPostSearchAds else { | ||
// should match OS availability in https://developer.apple.com/documentation/ad_services | ||
@available(iOS 14.3, macOS 11.1, macCatalyst 14.3, *) | ||
func postAdServicesTokenIfNeeded() { | ||
let latestTokenSent = latestNetworkIdAndAdvertisingIdentifierSent(network: .adServices) | ||
guard latestTokenSent == nil else { | ||
return | ||
} | ||
|
||
let latestIdsSent = latestNetworkIdAndAdvertisingIdentifierSent(network: .appleSearchAds) | ||
guard latestIdsSent == nil else { | ||
guard let attributionToken = attributionFetcher.adServicesToken() else { | ||
return | ||
} | ||
|
||
attributionFetcher.afficheClientAttributionDetails { attributionDetails, error in | ||
guard let attributionDetails = attributionDetails, | ||
error == nil else { | ||
return | ||
} | ||
|
||
let attributionDetailsValues = Array(attributionDetails.values) | ||
let firstAttributionDict = attributionDetailsValues.first as? [String: NSObject] | ||
|
||
guard let hasIad = firstAttributionDict?["iad-attribution"] as? NSNumber, | ||
hasIad.boolValue == true else { | ||
return | ||
} | ||
|
||
self.post(attributionData: attributionDetails, fromNetwork: .appleSearchAds, networkUserId: nil) | ||
} | ||
Logger.debug("Logging attribution token for now to avoid lint warning: \(attributionToken)") | ||
// post | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe leave this as a |
||
} | ||
|
||
func postPostponedAttributionDataIfNeeded() { | ||
|
@@ -162,19 +142,6 @@ class AttributionPoster { | |
return cachedDict[networkID] | ||
} | ||
|
||
private func postSearchAds(newData: [String: Any], | ||
network: AttributionNetwork, | ||
appUserID: String, | ||
newDictToCache: [String: String]) { | ||
backend.post(attributionData: newData, network: network, appUserID: appUserID) { error in | ||
guard error == nil else { | ||
return | ||
} | ||
|
||
self.deviceCache.set(latestNetworkAndAdvertisingIdsSent: newDictToCache, appUserID: appUserID) | ||
} | ||
} | ||
|
||
private func postSubscriberAttributes(newData: [String: Any], | ||
network: AttributionNetwork, | ||
appUserID: String, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would be better as a property: