Skip to content
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

AdServices #1727

Merged
merged 25 commits into from
Aug 8, 2022
Merged

AdServices #1727

merged 25 commits into from
Aug 8, 2022

Conversation

joshdholtz
Copy link
Member

@joshdholtz joshdholtz commented Jun 22, 2022

Motivation

@beylmk did all of the hard work on this so she gets credit for this PR 😊

Description

New API

Purchases.shared.attribution.enableAdServicesAttributionTokenCollection()

⚠️ This was originally planned as Purchases.automaticAdServicesAttributionTokenCollection = true but changed when #1693 was introduced

💭 Any thoughts on this public API would be appreciated! Not sure if this feels too hidden or too long? 🤷‍♂️

Behavior

  • Will attempt to collect and post the AdServices token when enableAdServicesAttributionTokenCollection is called
  • Will attempt to send when app enters foreground
  • Will only send the token once

beylmk and others added 8 commits May 2, 2022 09:38
Co-authored-by: NachoSoto <NachoSoto@users.noreply.github.com>
Co-authored-by: Josh Holtz <me@joshholtz.com>
# Conflicts:
#	RevenueCat.xcodeproj/project.pbxproj
# Conflicts:
#	Gemfile.lock
#	RevenueCat.xcodeproj/project.pbxproj
#	Sources/Logging/Strings/StoreKitStrings.swift
#	Sources/Misc/Deprecations.swift
#	Tests/UnitTests/Purchasing/PurchasesTests.swift
# Conflicts:
#	Tests/APITesters/SwiftAPITester/SwiftAPITester/PurchasesAPI.swift
#	Tests/UnitTests/Purchasing/Purchases/PurchasesTests.swift
Co-authored-by: NachoSoto <NachoSoto@users.noreply.github.com>
Co-authored-by: Josh Holtz <me@joshholtz.com>
@joshdholtz joshdholtz requested a review from a team June 22, 2022 04:26
@joshdholtz joshdholtz marked this pull request as ready for review June 22, 2022 04:28
A56F9AB126990E9200AFC48F /* CustomerInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = A56F9AB026990E9200AFC48F /* CustomerInfo.swift */; };
A5B6CDD8280F3843007629D5 /* AdServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5B6CDD5280F3843007629D5 /* AdServices.framework */; platformFilters = (ios, maccatalyst, macos, ); settings = {ATTRIBUTES = (Weak, ); }; };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻

Sources/Attribution/AttributionNetwork.swift Show resolved Hide resolved
@@ -115,8 +119,21 @@ extension AttributionStrings: CustomStringConvertible {
case .missing_advertiser_identifiers:
return "Attribution error: identifierForAdvertisers is missing"

case .unknown_sk2_product_discount_type(let rawValue):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call

Sources/Networking/Backend.swift Outdated Show resolved Hide resolved
Sources/Purchasing/Purchases/Attribution.swift Outdated Show resolved Hide resolved
Sources/Purchasing/Purchases/Purchases.swift Show resolved Hide resolved
@@ -73,74 +56,4 @@ class PurchasesAttributionDataTests: BasePurchasesTests {
expect(invokedParameters.appUserID) == self.purchases?.appUserID
}

func testAttributionDataSendsNetworkAppUserId() throws {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these have the equivalent tests now?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bump?

Copy link
Contributor

@NachoSoto NachoSoto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main issue is the old API still being available but "broken"

NachoSoto added a commit that referenced this pull request Jun 23, 2022
Fixes [CSDK-105].

This came up in #1534 (comment) and will simplify some of the code in #1727.
@beylmk beylmk mentioned this pull request Jun 27, 2022
NachoSoto added a commit that referenced this pull request Jun 27, 2022
Fixes [CSDK-105].

This came up in #1534 (comment) and will simplify some of the code in #1727.
Comment on lines 283 to 291
let latestSent: [AttributionNetwork: String] =
latestAdvertisingIdsByRawNetworkSent.reduce(into: [:]) { adIdsByNetwork, adIdByRawNetworkString in
if let networkRawValue = Int(adIdByRawNetworkString.key),
let attributionNetwork = AttributionNetwork(rawValue: networkRawValue) {
adIdsByNetwork[attributionNetwork] = adIdByRawNetworkString.value
} else {
Logger.error(Strings.attribution.latest_attribution_sent_user_defaults_invalid)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#1734 is in main now so this can be simplified:

Suggested change
let latestSent: [AttributionNetwork: String] =
latestAdvertisingIdsByRawNetworkSent.reduce(into: [:]) { adIdsByNetwork, adIdByRawNetworkString in
if let networkRawValue = Int(adIdByRawNetworkString.key),
let attributionNetwork = AttributionNetwork(rawValue: networkRawValue) {
adIdsByNetwork[attributionNetwork] = adIdByRawNetworkString.value
} else {
Logger.error(Strings.attribution.latest_attribution_sent_user_defaults_invalid)
}
}
let latestSent: [AttributionNetwork: String] =
latestAdvertisingIdsByRawNetworkSent.compactMapKeys {
guard let networkRawValue = Int(adIdByRawNetworkString.key),
let attributionNetwork = AttributionNetwork(rawValue: networkRawValue) else {
Logger.error(Strings.attribution.latest_attribution_sent_user_defaults_invalid)
return nil
}
return attributionNetwork
}

Comment on lines 300 to 303
let latestAdIdsByRawNetworkStringSent =
latestAdvertisingIdsByNetworkSent.reduce(into: [:]) { adIdsByRawNetworkString, adIdByNetwork in
adIdsByRawNetworkString[String(adIdByNetwork.key.rawValue)] = adIdByNetwork.value
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto:

Suggested change
let latestAdIdsByRawNetworkStringSent =
latestAdvertisingIdsByNetworkSent.reduce(into: [:]) { adIdsByRawNetworkString, adIdByNetwork in
adIdsByRawNetworkString[String(adIdByNetwork.key.rawValue)] = adIdByNetwork.value
}
let latestAdIdsByRawNetworkStringSent = latestAdvertisingIdsByNetworkSent.mapKeys { $0.key.rawValue }

Comment on lines 55 to 57
@available(iOS 14.3, macOS 11.1, macCatalyst 14.3, *)
@available(tvOS, unavailable)
@available(watchOS, unavailable)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would put these in the extension to avoid repeating them in both methods.

Comment on lines 68 to 71
guard self.automaticAdServicesAttributionTokenCollection else {
return
}
attributionPoster.postAdServicesTokenIfNeeded()
Copy link
Contributor

@NachoSoto NachoSoto Jun 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: this is more my opinion, but I think guard doesn't really add anything compared to a normal if:

Suggested change
guard self.automaticAdServicesAttributionTokenCollection else {
return
}
attributionPoster.postAdServicesTokenIfNeeded()
if self.automaticAdServicesAttributionTokenCollection {
self.attributionPoster.postAdServicesTokenIfNeeded()
}

Then we don't need that return.


#if canImport(AdServices)
@available(iOS 14.3, macOS 11.1, macCatalyst 14.3, *)
class AdServicesAttributionPosterTests: BaseAttributionPosterTests {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto this needs an availability check in setUpWithError.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doing the availability check in setUpWithError leads to the "redundant availability check" error... and it seems like we've avoided making more specific checks in the AvailabilityChecks class?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think without it these tests will fail on iOS 13 though (which won't be caught until this is merged in main.

Copy link
Contributor

@NachoSoto NachoSoto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just noticed this re-added PurchasesTests. If there are new tests there, you can put them in one of the subclasses or create another BasePurchasesTest subclass.


@testable import RevenueCat

class PurchasesTests: BasePurchasesTests {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ this file was split starting from #1609, but looks like it got re-added here!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops! removed, it shouldn't have had anything new...

Co-authored-by: NachoSoto <NachoSoto@users.noreply.github.com>
Sources/Attribution/AfficheClientProxy.swift Outdated Show resolved Hide resolved
Sources/Attribution/AfficheClientProxy.swift Outdated Show resolved Hide resolved
Sources/Attribution/AfficheClientProxy.swift Outdated Show resolved Hide resolved
Sources/Attribution/AttributionFetcher.swift Outdated Show resolved Hide resolved
Sources/Attribution/AttributionFetcher.swift Outdated Show resolved Hide resolved
Sources/Attribution/AttributionPoster.swift Outdated Show resolved Hide resolved
let newValueForNetwork = "\(identifierForAdvertisers ?? "(null)")_\(networkUserId ?? "(null)")"
guard latestSentToNetwork != newValueForNetwork else {
Logger.debug(Strings.attribution.skip_same_attributes)
guard let newDictToCache = getNewDictToCache(currentAppUserID: currentAppUserID,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: explicit self per the style guide.

Tests/UnitTests/Mocks/MockAttributionTypeFactory.swift Outdated Show resolved Hide resolved
Tests/UnitTests/Mocks/MockAttributionTypeFactory.swift Outdated Show resolved Hide resolved
@NachoSoto
Copy link
Contributor

Sorry I think I was reviewing the wrong diff 😕

Copy link
Contributor

@NachoSoto NachoSoto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is looking good!
The main thing left is the PurchasesTests file being re-added.

latestAdvertisingIdsByRawNetworkSent.compactMapKeys { network in
guard let networkRawValue = Int(network),
let attributionNetwork = AttributionNetwork(rawValue: networkRawValue) else {
Logger.error(Strings.attribution.latest_attribution_sent_user_defaults_invalid)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would include the network string in the error, so if we get a report with this message we can figure out why.

self.userDefaults.write {
$0.setValue(latestNetworkAndAdvertisingIdsSent,
// convert AttributionNetwork to Integer as String
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this comment doesn't add anything, that's implied in the types.

Tests/UnitTests/Mocks/MockDeviceCache.swift Show resolved Hide resolved
@NachoSoto
Copy link
Contributor

I see what happened, I reviewed a bunch of (old) code that was simply re-added. You can ignore all those comments since that's existing code!

@beylmk
Copy link
Contributor

beylmk commented Jun 28, 2022

I see what happened, I reviewed a bunch of (old) code that was simply re-added. You can ignore all those comments since that's existing code!

thanks for enduring all the confusion on this one 😬

@beylmk beylmk changed the title AdServices [DO NOT MERGE] AdServices Jun 28, 2022
@beylmk
Copy link
Contributor

beylmk commented Jun 28, 2022

@NachoSoto i believe all updates are done/replied to... we won't actually merge this btw, we are going to use this branch to release a beta.

Copy link
Contributor

@NachoSoto NachoSoto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

Sources/Attribution/AttributionNetwork.swift Show resolved Hide resolved
Comment on lines 131 to 134
let latestTokenSent = latestNetworkIdAndAdvertisingIdentifierSent(network: .adServices)
guard latestTokenSent == nil else {
return
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since latestTokenSent isn't used in the method we don't need a variable for it (it's kind of confusing because it's always going to be nil. I'd change this to:

Suggested change
let latestTokenSent = latestNetworkIdAndAdvertisingIdentifierSent(network: .adServices)
guard latestTokenSent == nil else {
return
}
guard self.latestNetworkIdAndAdvertisingIdentifierSent(network: .adServices) == nil else {
return
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bump

@@ -1,16 +0,0 @@
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect this file is still needed to make iOS 12 tests pass.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yes, my bad. updating

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wonder why the CI tests passed..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only run iOS 12 in main

Copy link
Contributor

@NachoSoto NachoSoto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is ready except for the iOS 12/13 issue with availability checks. We can add a new method in AvailabilityChecks to deal with that.

Comment on lines 131 to 134
let latestTokenSent = latestNetworkIdAndAdvertisingIdentifierSent(network: .adServices)
guard latestTokenSent == nil else {
return
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bump


#if canImport(AdServices)
@available(iOS 14.3, macOS 11.1, macCatalyst 14.3, *)
class AdServicesAttributionPosterTests: BaseAttributionPosterTests {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think without it these tests will fail on iOS 13 though (which won't be caught until this is merged in main.

@@ -73,74 +56,4 @@ class PurchasesAttributionDataTests: BasePurchasesTests {
expect(invokedParameters.appUserID) == self.purchases?.appUserID
}

func testAttributionDataSendsNetworkAppUserId() throws {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bump?

@joshdholtz joshdholtz changed the title [DO NOT MERGE] AdServices AdServices Aug 4, 2022
@joshdholtz joshdholtz merged commit 343ba7e into main Aug 8, 2022
@joshdholtz joshdholtz deleted the ad-services-sdk branch August 8, 2022 12:42
This was referenced Aug 8, 2022
NachoSoto added a commit that referenced this pull request Aug 13, 2022
This removes this unnecessary type in the global namespace.
Also removed 2 `cases` introduced in #1727 that aren't actually used.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants