Skip to content

Commit

Permalink
Remove ATB from attribution pixel (#3550)
Browse files Browse the repository at this point in the history
Task/Issue URL:
https://app.asana.com/0/1206226850447395/1208686056380205/f
Tech Design URL:
CC:

**Description**:

Removes ATB cohort information from attribution pixel. Adds information
about reinstall (returning user).

**Steps to test this PR**:
1. On a fresh install check if the parameter is included.

**Definition of Done (Internal Only)**:

* [ ] Does this PR satisfy our [Definition of
Done](https://app.asana.com/0/1202500774821704/1207634633537039/f)?

---
###### Internal references:
[Software Engineering
Expectations](https://app.asana.com/0/59792373528535/199064865822552)
[Technical Design
Template](https://app.asana.com/0/59792373528535/184709971311943)
  • Loading branch information
dus7 authored Nov 8, 2024
1 parent fec9005 commit 708bab3
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 9 deletions.
1 change: 1 addition & 0 deletions Core/Pixel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ public struct PixelParameters {
public static let adAttributionKeywordID = "keyword_id"
public static let adAttributionAdID = "ad_id"
public static let adAttributionToken = "attribution_token"
public static let adAttributionIsReinstall = "is_reinstall"

// Autofill
public static let countBucket = "count_bucket"
Expand Down
18 changes: 15 additions & 3 deletions DuckDuckGo/AdAttribution/AdAttributionPixelReporter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ final actor AdAttributionPixelReporter {
private let attributionFetcher: AdAttributionFetcher
private let featureFlagger: FeatureFlagger
private let privacyConfigurationManager: PrivacyConfigurationManaging
private let variantManager: VariantManager
private let pixelFiring: PixelFiringAsync.Type
private var isSendingAttribution: Bool = false

Expand All @@ -50,12 +51,14 @@ final actor AdAttributionPixelReporter {
attributionFetcher: AdAttributionFetcher = DefaultAdAttributionFetcher(),
featureFlagger: FeatureFlagger = AppDependencyProvider.shared.featureFlagger,
privacyConfigurationManager: PrivacyConfigurationManaging = ContentBlocking.shared.privacyConfigurationManager,
variantManager: VariantManager = AppDependencyProvider.shared.variantManager,
pixelFiring: PixelFiringAsync.Type = Pixel.self,
inconsistencyMonitoring: AdAttributionReporterInconsistencyMonitoring = StorageInconsistencyMonitor()) {
self.fetcherStorage = fetcherStorage
self.attributionFetcher = attributionFetcher
self.featureFlagger = featureFlagger
self.privacyConfigurationManager = privacyConfigurationManager
self.variantManager = variantManager
self.pixelFiring = pixelFiring
self.inconsistencyMonitoring = inconsistencyMonitoring
}
Expand Down Expand Up @@ -85,12 +88,14 @@ final actor AdAttributionPixelReporter {
if let (token, attributionData) = await self.attributionFetcher.fetch() {
if attributionData.attribution {
let settings = AdAttributionReporterSettings(privacyConfigurationManager.privacyConfig)
let parameters = self.pixelParametersForAttribution(attributionData, attributionToken: settings.includeToken ? token : nil)
let token = settings.includeToken ? token : nil
let isReinstall = variantManager.isIndicatingReturningUser
let parameters = self.pixelParametersForAttribution(attributionData, isReinstall: isReinstall, attributionToken: token)
do {
try await pixelFiring.fire(
pixel: .appleAdAttribution,
withAdditionalParameters: parameters,
includedParameters: [.appVersion, .atb]
includedParameters: [.appVersion]
)
} catch {
return false
Expand Down Expand Up @@ -127,7 +132,7 @@ final actor AdAttributionPixelReporter {
}
}

private func pixelParametersForAttribution(_ attribution: AdServicesAttributionResponse, attributionToken: String?) -> [String: String] {
private func pixelParametersForAttribution(_ attribution: AdServicesAttributionResponse, isReinstall: Bool, attributionToken: String?) -> [String: String] {
var params: [String: String] = [:]

params[PixelParameters.adAttributionAdGroupID] = attribution.adGroupId.map(String.init)
Expand All @@ -139,6 +144,7 @@ final actor AdAttributionPixelReporter {
params[PixelParameters.adAttributionKeywordID] = attribution.keywordId.map(String.init)
params[PixelParameters.adAttributionAdID] = attribution.adId.map(String.init)
params[PixelParameters.adAttributionToken] = attributionToken
params[PixelParameters.adAttributionIsReinstall] = isReinstall ? "1" : "0"

return params
}
Expand All @@ -161,3 +167,9 @@ private struct AdAttributionReporterSettings {
static let includeToken = "includeToken"
}
}

private extension VariantManager {
var isIndicatingReturningUser: Bool {
currentVariant?.name == VariantIOS.returningUser.name
}
}
28 changes: 22 additions & 6 deletions DuckDuckGoTests/AdAttributionPixelReporterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ final class AdAttributionPixelReporterTests: XCTestCase {
private var fetcherStorage: AdAttributionReporterStorageMock!
private var featureFlagger: MockFeatureFlagger!
private var privacyConfigurationManager: PrivacyConfigurationManagerMock!
private var variantManager: MockVariantManager!

private let fileMarker = BoolFileMarker(name: .init(rawValue: "ad-attribution-successful"))!

Expand All @@ -36,6 +37,7 @@ final class AdAttributionPixelReporterTests: XCTestCase {
fetcherStorage = AdAttributionReporterStorageMock()
featureFlagger = MockFeatureFlagger()
privacyConfigurationManager = PrivacyConfigurationManagerMock()
variantManager = MockVariantManager()

featureFlagger.enabledFeatureFlags.append(.adAttributionReporting)
fileMarker.unmark()
Expand Down Expand Up @@ -109,6 +111,19 @@ final class AdAttributionPixelReporterTests: XCTestCase {
XCTAssertEqual(pixelAttributes["keyword_id"], "4")
XCTAssertEqual(pixelAttributes["ad_id"], "5")
XCTAssertEqual(pixelAttributes["attribution_token"], "example")
XCTAssertEqual(pixelAttributes["is_reinstall"], "0")
}

func testReinstallTrueWhenReturningUserVariantPresent() async throws {
let sut = createSUT(with: .returningUser)
attributionFetcher.fetchResponse = ("example", AdServicesAttributionResponse(attribution: true))
(privacyConfigurationManager.privacyConfig as? PrivacyConfigurationMock)?.settings[.adAttributionReporting] = ["includeToken": true]

await sut.reportAttributionIfNeeded()

let pixelAttributes = try XCTUnwrap(PixelFiringMock.lastParams)

XCTAssertEqual(pixelAttributes["is_reinstall"], "1")
}

func testPixelAdditionalParameters() async throws {
Expand All @@ -119,7 +134,7 @@ final class AdAttributionPixelReporterTests: XCTestCase {

let pixelAttributes = try XCTUnwrap(PixelFiringMock.lastIncludedParams)

XCTAssertEqual(pixelAttributes, [.appVersion, .atb])
XCTAssertEqual(pixelAttributes, [.appVersion])
}

func testPixelAttributes_WhenPartialAttributionData() async throws {
Expand Down Expand Up @@ -220,25 +235,26 @@ final class AdAttributionPixelReporterTests: XCTestCase {
XCTAssertNotNil(pixelAttributes["attribution_token"])
}

private func createSUT() -> AdAttributionPixelReporter {
private func createSUT(with variant: VariantIOS? = nil) -> AdAttributionPixelReporter {
AdAttributionPixelReporter(fetcherStorage: fetcherStorage,
attributionFetcher: attributionFetcher,
featureFlagger: featureFlagger,
privacyConfigurationManager: privacyConfigurationManager,
variantManager: MockVariantManager(isSupportedReturns: false, currentVariant: variant),
pixelFiring: PixelFiringMock.self,
inconsistencyMonitoring: MockAdAttributionReporterInconsistencyMonitoring())
}
}

class AdAttributionReporterStorageMock: AdAttributionReporterStorage {
private class AdAttributionReporterStorageMock: AdAttributionReporterStorage {
func markAttributionReportSuccessful() async {
wasAttributionReportSuccessful = true
}

private(set) var wasAttributionReportSuccessful: Bool = false
}

class AdAttributionFetcherMock: AdAttributionFetcher {
private class AdAttributionFetcherMock: AdAttributionFetcher {
var wasFetchCalled: Bool = false

var fetchResponse: (String, AdServicesAttributionResponse)?
Expand All @@ -248,13 +264,13 @@ class AdAttributionFetcherMock: AdAttributionFetcher {
}
}

struct MockAdAttributionReporterInconsistencyMonitoring: AdAttributionReporterInconsistencyMonitoring {
private struct MockAdAttributionReporterInconsistencyMonitoring: AdAttributionReporterInconsistencyMonitoring {
func addAttributionReporter(hasFileMarker: Bool, hasCompletedFlag: Bool) {

}
}

extension AdServicesAttributionResponse {
private extension AdServicesAttributionResponse {
init(attribution: Bool) {
self.init(
attribution: attribution,
Expand Down

0 comments on commit 708bab3

Please sign in to comment.