Skip to content

Commit

Permalink
Second CPM experiment (#3397)
Browse files Browse the repository at this point in the history
Task/Issue URL:
https://app.asana.com/0/1205142657210376/1208488711477099/f
Tech Design URL:
https://app.asana.com/0/1205142657210376/1208527766092596/f
CC:
BSK PR: duckduckgo/BrowserServicesKit#1017
Corresponding SERP PR:
https://dub.duckduckgo.com/duckduckgo/ddg/pull/35929 (deployed on
mtsoy.duckduckgo.com)

**Description**:

**Steps to test this PR**:
1. Run the browser
2. Change remote config URL to
https://jsonblob.com/api/1295841430403407872
3. Do a search
4. Observe a `cpme=1|0` query parameter in the search address
5. Reset the test cohort (Debug -> Reset Data -> Reset CPM Experiment
Cohort) to confirm that the value (1 or 0) is assigned randomly

<!--
Tagging instructions
If this PR isn't ready to be merged for whatever reason it should be
marked with the `DO NOT MERGE` label (particularly if it's a draft)
If it's pending Product Review/PFR, please add the `Pending Product
Review` label.

If at any point it isn't actively being worked on/ready for
review/otherwise moving forward (besides the above PR/PFR exception)
strongly consider closing it (or not opening it in the first place). If
you decide not to close it, make sure it's labelled to make it clear the
PRs state and comment with more information.
-->

**Definition of Done**:

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

---
###### Internal references:
[Pull Request Review
Checklist](https://app.asana.com/0/1202500774821704/1203764234894239/f)
[Software Engineering
Expectations](https://app.asana.com/0/59792373528535/199064865822552)
[Technical Design
Template](https://app.asana.com/0/59792373528535/184709971311943)
[Pull Request
Documentation](https://app.asana.com/0/1202500774821704/1204012835277482/f)
  • Loading branch information
muodov authored Oct 18, 2024
1 parent 8f77c5f commit 30b1747
Show file tree
Hide file tree
Showing 14 changed files with 73 additions and 78 deletions.
2 changes: 1 addition & 1 deletion DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14314,7 +14314,7 @@
repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit";
requirement = {
kind = exactVersion;
version = 199.3.1;
version = 199.4.0;
};
};
9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/BrowserServicesKit",
"state" : {
"revision" : "4e9ce77a747b16b4032823ceae9d5490a68ffd2b",
"version" : "199.3.1"
"revision" : "f1a033cc4b97ab6b4d845815e825ba179c02635a",
"version" : "199.4.0"
}
},
{
Expand Down Expand Up @@ -75,7 +75,7 @@
{
"identity" : "lottie-spm",
"kind" : "remoteSourceControl",
"location" : "https://github.com/airbnb/lottie-spm.git",
"location" : "https://github.com/airbnb/lottie-spm",
"state" : {
"revision" : "1d29eccc24cc8b75bff9f6804155112c0ffc9605",
"version" : "4.4.3"
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/Autoconsent/AutoconsentUserScript.swift
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ extension AutoconsentUserScript {
}
let remoteConfig = self.config.settings(for: .autoconsent)
let disabledCMPs = remoteConfig["disabledCMPs"] as? [String] ?? []
let isFilterListExperimentEnabled = config.isSubfeatureEnabled(AutoconsentSubfeature.filterlistExperiment)
let isFilterListExperimentEnabled = config.isSubfeatureEnabled(AutoconsentSubfeature.filterlistExperiment2)
let enableFilterList = isFilterListExperimentEnabled && AutoconsentFilterlistExperiment.cohort == AutoconsentFilterlistExperiment.test

replyHandler([
Expand Down
80 changes: 40 additions & 40 deletions DuckDuckGo/Autoconsent/autoconsent-bundle.js

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions DuckDuckGo/Common/Extensions/URLExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,12 @@ extension URL {
return nil
}

let privacyConfigurationManager = ContentBlocking.shared.privacyConfigurationManager
let isFilterListExperimentEnabled = privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(AutoconsentSubfeature.filterlistExperiment2)
var url = Self.duckDuckGo.appendingParameter(name: DuckDuckGoParameters.search.rawValue, value: trimmedQuery)
if isFilterListExperimentEnabled {
url = url.appendingParameter(name: "cpme", value: AutoconsentFilterlistExperiment.cohort == AutoconsentFilterlistExperiment.test ? "1" : "0")
}

// Add experimental atb parameter to SERP queries for internal users to display Privacy Reminder
// https://app.asana.com/0/1199230911884351/1205979030848528/f
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/Menus/MainMenu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ final class MainMenu: NSMenu {
NSMenuItem(title: "Reset Email Protection InContext Signup Prompt", action: #selector(MainViewController.resetEmailProtectionInContextPrompt))
NSMenuItem(title: "Reset Pixels Storage", action: #selector(MainViewController.resetDailyPixels))
NSMenuItem(title: "Reset Remote Messages", action: #selector(AppDelegate.resetRemoteMessages))
NSMenuItem(title: "Reset CPM Experiment Cohort (needs restart)", action: #selector(AppDelegate.resetCpmCohort))
NSMenuItem(title: "Reset CPM Experiment Cohort", action: #selector(AppDelegate.resetCpmCohort))
NSMenuItem(title: "Reset Duck Player Preferences", action: #selector(MainViewController.resetDuckPlayerPreferences))
NSMenuItem(title: "Reset Onboarding", action: #selector(MainViewController.resetOnboarding(_:)))
NSMenuItem(title: "Reset Contextual Onboarding", action: #selector(MainViewController.resetContextualOnboarding(_:)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ final class PrivacyDashboardViewController: NSViewController {
let privacyConfigurationManager = ContentBlocking.shared.privacyConfigurationManager
var updatedParameters = parameters
// do not enroll users who have CPM disabled
if CookiePopupProtectionPreferences.shared.isAutoconsentEnabled && privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(AutoconsentSubfeature.filterlistExperiment) {
if CookiePopupProtectionPreferences.shared.isAutoconsentEnabled && privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(AutoconsentSubfeature.filterlistExperiment2) {
updatedParameters["cpmExperiment"] = AutoconsentFilterlistExperiment.cohort == AutoconsentFilterlistExperiment.test ? "1" : "0"
}
PixelKit.fire(NonStandardEvent(NonStandardPixel.brokenSiteReport),
Expand Down
25 changes: 8 additions & 17 deletions DuckDuckGo/Tab/TabExtensions/AdClickAttributionTabExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ protocol AdClickLogicProtocol: AnyObject {

func applyInheritedAttribution(state: AdClickAttributionLogic.State?)
func onRulesChanged(latestRules: [ContentBlockerRulesManager.Rules])
func onRequestDetected(request: DetectedRequest, cpmExperimentOn: Bool?)
func onRequestDetected(request: DetectedRequest)

func onBackForwardNavigation(mainFrameURL: URL?)
func onProvisionalNavigation() async
Expand All @@ -79,12 +79,11 @@ extension ContentBlockerRulesUserScript: ContentBlockerScriptProtocol {}

final class AdClickAttributionTabExtension: TabExtension {

private static func makeAdClickAttributionDetection(with dependencies: any AdClickAttributionDependencies, delegate: AdClickAttributionLogic, cpmExperimentOn: Bool?) -> AdClickAttributionDetection {
private static func makeAdClickAttributionDetection(with dependencies: any AdClickAttributionDependencies, delegate: AdClickAttributionLogic) -> AdClickAttributionDetection {
let detection = AdClickAttributionDetection(feature: dependencies.adClickAttribution,
tld: dependencies.tld,
eventReporting: dependencies.attributionEvents,
errorReporting: dependencies.attributionDebugEvents,
cpmExperimentOn: cpmExperimentOn)
errorReporting: dependencies.attributionDebugEvents)
detection.delegate = delegate
return detection

Expand All @@ -98,9 +97,9 @@ final class AdClickAttributionTabExtension: TabExtension {
errorReporting: dependencies.attributionDebugEvents)
}

private static func makeAdClickAttribution(with dependencies: any AdClickAttributionDependencies, cpmExperimentOn: Bool?) -> (AdClickLogicProtocol, AdClickAttributionDetecting) {
private static func makeAdClickAttribution(with dependencies: any AdClickAttributionDependencies) -> (AdClickLogicProtocol, AdClickAttributionDetecting) {
let logic = makeAdClickAttributionLogic(with: dependencies)
let detection = makeAdClickAttributionDetection(with: dependencies, delegate: logic, cpmExperimentOn: cpmExperimentOn)
let detection = makeAdClickAttributionDetection(with: dependencies, delegate: logic)
return (logic, detection)
}

Expand All @@ -120,26 +119,18 @@ final class AdClickAttributionTabExtension: TabExtension {
}

private var cancellables = Set<AnyCancellable>()
private let cpmExperimentOn: Bool?

init(inheritedAttribution: AdClickAttributionLogic.State?,
userContentControllerFuture: some Publisher<some UserContentControllerProtocol, Never>,
contentBlockerRulesScriptPublisher: some Publisher<(any ContentBlockerScriptProtocol)?, Never>,
trackerInfoPublisher: some Publisher<DetectedRequest, Never>,
dependencies: some AdClickAttributionDependencies,
dateTimeProvider: @escaping () -> Date = Date.init,
logicsProvider: (AdClickAttributionDependencies, Bool?) -> (AdClickLogicProtocol, AdClickAttributionDetecting) = AdClickAttributionTabExtension.makeAdClickAttribution) {
logicsProvider: (AdClickAttributionDependencies) -> (AdClickLogicProtocol, AdClickAttributionDetecting) = AdClickAttributionTabExtension.makeAdClickAttribution) {

self.dependencies = dependencies
self.dateTimeProvider = dateTimeProvider

// do not enroll users who have CPM disabled
if !CookiePopupProtectionPreferences.shared.isAutoconsentEnabled || !dependencies.privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(AutoconsentSubfeature.filterlistExperiment) {
self.cpmExperimentOn = nil
} else {
self.cpmExperimentOn = AutoconsentFilterlistExperiment.cohort == AutoconsentFilterlistExperiment.test
}
(self.logic, self.detection) = logicsProvider(dependencies, self.cpmExperimentOn)
(self.logic, self.detection) = logicsProvider(dependencies)
self.logic.delegate = self

// delay firing up until UserContentController is published
Expand Down Expand Up @@ -172,7 +163,7 @@ final class AdClickAttributionTabExtension: TabExtension {

trackerInfoPublisher
.sink { [weak self] tracker in
self?.logic.onRequestDetected(request: tracker, cpmExperimentOn: self?.cpmExperimentOn)
self?.logic.onRequestDetected(request: tracker)
}
.store(in: &cancellables)
}
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/DataBrokerProtection/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ let package = Package(
targets: ["DataBrokerProtection"])
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "199.3.1"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "199.4.0"),
.package(path: "../SwiftUIExtensions"),
.package(path: "../XPCHelper"),
],
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/NetworkProtectionMac/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ let package = Package(
.library(name: "VPNAppLauncher", targets: ["VPNAppLauncher"]),
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "199.3.1"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "199.4.0"),
.package(url: "https://github.com/airbnb/lottie-spm", exact: "4.4.3"),
.package(path: "../AppLauncher"),
.package(path: "../UDSHelper"),
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/SubscriptionUI/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ let package = Package(
targets: ["SubscriptionUI"]),
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "199.3.1"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "199.4.0"),
.package(path: "../SwiftUIExtensions")
],
targets: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class AdClickAttributionTabExtensionTests: XCTestCase {
contentBlockerRulesScriptPublisher: self.contentBlockerRulesScriptSubj,
trackerInfoPublisher: self.trackerInfoPublisher,
dependencies: dependencies.privacyFeatures.contentBlocking,
dateTimeProvider: { self.now }) { _, _ in
dateTimeProvider: { self.now }) { _ in
(logic: self.logic, detection: self.detection)
}
}
Expand Down Expand Up @@ -671,7 +671,7 @@ class MockAdClickLogic: AdClickLogicProtocol {
}

var onRequestDetected: ((DetectedRequest) -> Void)!
func onRequestDetected(request: DetectedRequest, cpmExperimentOn: Bool? = nil) {
func onRequestDetected(request: DetectedRequest) {
onRequestDetected(request)
}

Expand Down
15 changes: 7 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@
"rollup-plugin-terser": "^7.0.2"
},
"dependencies": {
"@duckduckgo/autoconsent": "^10.13.0"
"@duckduckgo/autoconsent": "^10.16.0"
}
}

0 comments on commit 30b1747

Please sign in to comment.