Skip to content

[CF-106] Fetch AdServices Token#1519

Merged
beylmk merged 45 commits into
ad-services-sdkfrom
ad-services
May 2, 2022
Merged

[CF-106] Fetch AdServices Token#1519
beylmk merged 45 commits into
ad-services-sdkfrom
ad-services

Conversation

@beylmk

@beylmk beylmk commented Apr 20, 2022

Copy link
Copy Markdown
Contributor

AdServices token fetching and removal of old iAD code. Posting to the backend will be the next step.

  • deprecates old automaticAppleSearchAdsAttributionCollection
  • adds new automaticAdServicesAttributionTokenCollection
  • fetches attribution token

There is a follow-up ticket to investigate linking, and we will probably switch to weak-linking then.

Comment thread Sources/Attribution/AttributionFetcher.swift Outdated
Comment thread RevenueCat.xcodeproj/project.pbxproj Outdated
A563F586271E072B00246E0C /* MockBeginRefundRequestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A563F585271E072B00246E0C /* MockBeginRefundRequestHelper.swift */; };
A563F589271E1DAD00246E0C /* MockBeginRefundRequestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A563F585271E072B00246E0C /* MockBeginRefundRequestHelper.swift */; };
A56F9AB126990E9200AFC48F /* CustomerInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = A56F9AB026990E9200AFC48F /* CustomerInfo.swift */; };
A5B6CDD8280F3843007629D5 /* AdServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5B6CDD5280F3843007629D5 /* AdServices.framework */; };

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 this be weakly linked?

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.

In case I don't get to review this again, just wanted to point out that this is probably my most critical comment. I believe this has to be weakly linked so we don't make all users of the SDK implicitly link AdServices.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

+1 on this, this part is a very delicate change that we should research and test out thoroughly.
It might even be a red flag for privacy-minded folks who're looking into using our SDK. Perhaps we can do the extra work of calling this through the same "reflection" we did for iAd?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

are you both okay with me doing the linking research as the follow-up ticket i created? would definitely be before merging into main. this just feels like enough work to warrant a separate PR

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

absolutely! It's only important to get the linking right before merging to main, but it can totally be done as a separate thing

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

okay then that's the plan!


@available(iOS 14.3, *)
func adServicesToken(completion: @escaping (String?, Error?) -> Void) {
// TODO check for library?

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 canImport would help here too :)

return "This StoreProduct represents an SK1 product, the type of product cannot be determined, " +
"the value will be undefined. Use `StoreProduct.productCategory` instead."

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.

👍🏻

Comment thread Sources/Purchasing/Purchases.swift Outdated
* Enable automatic collection of AdServices attribution token. Defaults to `false`.
*/
@objc public static var automaticAppleSearchAdsAttributionCollection: Bool = false
@available(iOS 14.3, *)

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 will need the tvOS/macCatalyst (macOS too?) equivalents too

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yep good call. xcode never suggests the full checks for us, do they...

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.

Nope, only for the currently selected target unfortunately.

Comment thread Sources/Purchasing/Purchases.swift Outdated
* Enable automatic collection of Apple Search Ads attribution. Defaults to `false`.
*/
@available(*, deprecated, message: "use Purchases.automaticAdServicesAttributionTokenCollection for iOS 14.3+ instead")
@objc static var automaticAppleSearchAdsAttributionCollection: Bool = false

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.

Maybe move this to Deprecations.swift?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

is there a difference between methods in Deprecations.swift and those in the // MARK: Deprecated section of Purchases.swift?

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.

Oh I didn't realize we still had some there. The idea was to make the main file (which is already huge) smaller by only having the current API.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

makes sense to me! i can move the rest while i'm at it...

beylmk and others added 3 commits April 20, 2022 13:34
@beylmk beylmk force-pushed the ad-services branch 2 times, most recently from 2abd531 to 160efb4 Compare April 22, 2022 10:54
Comment thread Sources/Purchasing/Purchases.swift
@beylmk beylmk mentioned this pull request Apr 27, 2022
expect(MockAdClientProxy.requestAttributionDetailsCallCount) == 0
}

func testPostAppleSearchAdsAttributionIfNeededSkipsIfAlreadySent() throws {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i'll add back related tests in the post PR

@beylmk beylmk requested a review from a team April 28, 2022 15:56
@beylmk

beylmk commented Apr 28, 2022

Copy link
Copy Markdown
Contributor Author

need to figure out why build-tv-watch-and-macos is failing, but otherwise this is ready for re-review

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

Looks good! Just a few minor comments.
Let me know if I can help figuring out the watchOS issue, might be because AdServices isn't available, so maybe weak linking might fix that?

afficheClientProxy.requestAttributionDetails(completion)
#else
completion(nil, AttributionFetcherError.identifierForAdvertiserUnavailableForPlatform)
Logger.warn(Strings.attribution.adservices_not_supported)

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.

Nice

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? {

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 would be better as a property:

Suggested change
func adServicesToken() -> String? {
var adServicesToken: String? {

if let attributionToken = try? AAAttribution.attributionToken() {
return attributionToken
} else {
Logger.warn(Strings.attribution.adservices_token_fetch_failed)

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.

Maybe do a do/catch instead of try? to add the underlying error to this?
Also I wonder if it should be Logger.appleError

Comment thread Sources/Purchasing/Purchases.swift Outdated
Comment thread Sources/Purchasing/Purchases.swift Outdated
postAppleSearchAddsAttributionCollectionIfNeeded()

// should match OS availability in https://developer.apple.com/documentation/ad_services
if #available(iOS 14.3, macOS 11.1, macCatalyst 14.3, *) { postAdServicesTokenIfNeeded()

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.

Formatting here is weird, did you mean to put it in a new line?

Suggested change
if #available(iOS 14.3, macOS 11.1, macCatalyst 14.3, *) { postAdServicesTokenIfNeeded()
if #available(iOS 14.3, macOS 11.1, macCatalyst 14.3, *) {
postAdServicesTokenIfNeeded()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

oh woops yes. was on a tiny screen this day and didn't realize, good catch

return .promotional
default:
Logger.warn(Strings.attribution.unknown_sk2_product_discount_type(rawValue: sk2Discount.type.rawValue))
Logger.warn(Strings.storeKit.unknown_sk2_product_discount_type(rawValue: sk2Discount.type.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.

:+1


class MockAttributionFetcher: AttributionFetcher {

var adServicesTokenCollectionCalled = false

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: maybe move this right on top of adServicesToken? I think that's what other mocks do

@@ -1,16 +0,0 @@
{
"headers" : {

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.

Thanks for removing these too!

@beylmk

beylmk commented Apr 28, 2022

Copy link
Copy Markdown
Contributor Author

Does this have to be optional?

that was me trying to weak link the framework. i'm not seeing very clear guidance on how to do that in an initial google search...

@beylmk

beylmk commented Apr 28, 2022

Copy link
Copy Markdown
Contributor Author

Looks good! Just a few minor comments. Let me know if I can help figuring out the watchOS issue, might be because AdServices isn't available, so maybe weak linking might fix that?

if you have time to look that'd be great 🙏

objects = {

/* Begin PBXBuildFile section */
2C396F5E281C64B700669657 /* AdServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C396F5D281C64B700669657 /* AdServices.framework */; };

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 we shouldn't do this. The fact that APITesters needs it is a sign that users will need to add it as well, which isn't good. I'm guessing the actual problem was this: #1554.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

agreed. promise i won't forget this before merging to main.

This fixes the watchOS and tvOS compilation (yay CI test coverage catching this!)
Now the framework is only linked for the rest of the platforms.
@beylmk

beylmk commented Apr 29, 2022

Copy link
Copy Markdown
Contributor Author

@NachoSoto thanks for your help!! i think this finally passed everything if you have time to review :)

@beylmk beylmk merged commit fd2fb2d into ad-services-sdk May 2, 2022
@beylmk beylmk deleted the ad-services branch May 2, 2022 16:38
self.post(attributionData: attributionDetails, fromNetwork: .appleSearchAds, networkUserId: nil)
}
Logger.debug("Logging attribution token for now to avoid lint warning: \(attributionToken)")
// post

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.

Maybe leave this as a TODO? it's okay if lint fails since we're not merging this in main yet. That way we ensure it doesn't slip through the cracks.

* Should match OS availability in https://developer.apple.com/documentation/ad_services
*/
@objc public static var automaticAppleSearchAdsAttributionCollection: Bool = false
@available(iOS 14.3, macOS 11.1, macCatalyst 14.3, *)

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 is being implicitly marked as available for any version of tvOS and watchOS. You need to add this:

@available(tvOS, unavailable)
@available(watchOS, unavailable)

private func postAppleSearchAddsAttributionCollectionIfNeeded() {
guard Self.automaticAppleSearchAdsAttributionCollection else {
// should match OS availability in https://developer.apple.com/documentation/ad_services
@available(iOS 14.3, macOS 11.1, macCatalyst 14.3, *)

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 here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

oops missed this, will get into the post PR

joshdholtz added a commit that referenced this pull request Aug 8, 2022
* [CF-106] Fetch AdServices Token (#1519)

Co-authored-by: NachoSoto <NachoSoto@users.noreply.github.com>
Co-authored-by: Josh Holtz <me@joshholtz.com>

* [CF-553] Post AdServices token (#1534)

Co-authored-by: NachoSoto <NachoSoto@users.noreply.github.com>
Co-authored-by: Josh Holtz <me@joshholtz.com>

* Update ios 14 snapshots tets

* Reworked adservices to use new Purchases.shared.attribution API

* Updated with some comments from PR

* Add iAd code back (#1739)

Co-authored-by: NachoSoto <NachoSoto@users.noreply.github.com>

* use new mapKeys dictionary extension for device cache

* update for some pr comments

* remove purchasestests

* generate missing snapshots

* fix deprecation messages to clarify method now called on shared instance

* Fix for inserting nonstring into userdefaults

* Add tests for bug

* fix lint

* Added availablility checks for tests and removed unused varialbes

* Whoops... wrong class

Co-authored-by: beylmk <maddie@revenuecat.com>
Co-authored-by: NachoSoto <NachoSoto@users.noreply.github.com>
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