Skip to content

AdServices#1727

Merged
joshdholtz merged 25 commits into
mainfrom
ad-services-sdk
Aug 8, 2022
Merged

AdServices#1727
joshdholtz merged 25 commits into
mainfrom
ad-services-sdk

Conversation

@joshdholtz

@joshdholtz joshdholtz commented Jun 22, 2022

Copy link
Copy Markdown
Member

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
A563F589271E1DAD00246E0C /* MockBeginRefundRequestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A563F585271E072B00246E0C /* MockBeginRefundRequestHelper.swift */; };
A56C2E012819C33500995421 /* BackendPostAdServicesTokenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A56C2E002819C33500995421 /* BackendPostAdServicesTokenTests.swift */; };
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
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👍🏻

Comment thread Sources/Attribution/AttributionNetwork.swift
case .missing_advertiser_identifiers:
return "Attribution error: identifierForAdvertisers is missing"

case .unknown_sk2_product_discount_type(let rawValue):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good call

Comment thread Sources/Networking/Backend.swift
Comment thread Sources/Purchasing/Purchases/Attribution.swift Outdated
Comment thread Sources/Purchasing/Purchases/Attribution.swift
Comment thread Sources/Purchasing/Purchases/Purchases.swift
Comment thread Tests/APITesters/SwiftAPITester/SwiftAPITester/PurchasesAPI.swift
expect(invokedParameters.appUserID) == self.purchases?.appUserID
}

func testAttributionDataSendsNetworkAppUserId() throws {

Copy link
Copy Markdown
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
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bump?

Comment thread Tests/UnitTests/SubscriberAttributes/SubscriberAttributesManagerTests.swift Outdated

@NachoSoto NachoSoto left a comment

Copy link
Copy Markdown
Contributor

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"

Comment thread Tests/APITesters/ObjCAPITester/ObjCAPITester/RCPurchasesAPI.m Outdated
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 thread Sources/Misc/Deprecations.swift Outdated
Comment thread Sources/Caching/DeviceCache.swift Outdated
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
Copy Markdown
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 thread Sources/Caching/DeviceCache.swift Outdated
Comment on lines +300 to +303
let latestAdIdsByRawNetworkStringSent =
latestAdvertisingIdsByNetworkSent.reduce(into: [:]) { adIdsByRawNetworkString, adIdByNetwork in
adIdsByRawNetworkString[String(adIdByNetwork.key.rawValue)] = adIdByNetwork.value
}

Copy link
Copy Markdown
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
Copy Markdown
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()

@NachoSoto NachoSoto Jun 27, 2022

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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.

@NachoSoto NachoSoto left a comment

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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
Copy Markdown
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>
Comment thread Sources/Attribution/AfficheClientProxy.swift
Comment thread Sources/Attribution/AfficheClientProxy.swift
Comment thread Sources/Attribution/AfficheClientProxy.swift
Comment thread Sources/Attribution/AttributionFetcher.swift
Comment thread Sources/Attribution/AttributionFetcher.swift
Comment thread Sources/Attribution/AttributionPoster.swift
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
Copy Markdown
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.

Comment thread Tests/UnitTests/Mocks/MockAttributionTypeFactory.swift
Comment thread Tests/UnitTests/Mocks/MockAttributionTypeFactory.swift
@NachoSoto

Copy link
Copy Markdown
Contributor

Sorry I think I was reviewing the wrong diff 😕

@NachoSoto NachoSoto left a comment

Copy link
Copy Markdown
Contributor

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.

Comment thread Sources/Caching/DeviceCache.swift Outdated
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
Copy Markdown
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.

Comment thread Sources/Caching/DeviceCache.swift Outdated
func set(latestAdvertisingIdsByNetworkSent: [AttributionNetwork: String], appUserID: String) {
self.userDefaults.write {
$0.setValue(latestNetworkAndAdvertisingIdsSent,
// convert AttributionNetwork to Integer as String

Copy link
Copy Markdown
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.

Comment thread Tests/UnitTests/Mocks/MockDeviceCache.swift
@NachoSoto

Copy link
Copy Markdown
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

beylmk commented Jun 28, 2022

Copy link
Copy Markdown
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!

thanks for enduring all the confusion on this one 😬

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

beylmk commented Jun 28, 2022

Copy link
Copy Markdown
Contributor

@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.

@NachoSoto NachoSoto left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Awesome!

Comment thread Sources/Attribution/AttributionNetwork.swift
Comment on lines +131 to +134
let latestTokenSent = latestNetworkIdAndAdvertisingIdentifierSent(network: .adServices)
guard latestTokenSent == nil else {
return
}

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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

@NachoSoto NachoSoto left a comment

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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
Copy Markdown
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.

expect(invokedParameters.appUserID) == self.purchases?.appUserID
}

func testAttributionDataSendsNetworkAppUserId() throws {

Copy link
Copy Markdown
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