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

Attach params to PPro pixels #3092

Merged
merged 53 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
39696ff
Add DefaultPrivacyProDataReporter
quanganhdo Jul 14, 2024
3ee785f
Save promo pixel attributes
quanganhdo Jul 14, 2024
b909e75
Get randomized subset
quanganhdo Jul 14, 2024
f62a2e2
Attach pixel params
quanganhdo Jul 15, 2024
b0010aa
Add tests
quanganhdo Jul 15, 2024
93e4a12
Add missing files
quanganhdo Jul 15, 2024
2510acc
Merge branch 'main' into anh/ppro/pixels
quanganhdo Jul 15, 2024
6868ddf
Fix a bug
quanganhdo Jul 16, 2024
4c117a2
Add tests
quanganhdo Jul 16, 2024
6616bef
Refactor + add debug menu option
quanganhdo Jul 16, 2024
171fba4
Use last session ended
quanganhdo Jul 16, 2024
3db63e4
Fire pixels with params
quanganhdo Jul 16, 2024
25cb9e4
Update BSK
quanganhdo Jul 16, 2024
8b6d01f
Update BSK
quanganhdo Jul 17, 2024
2f5598a
Fix Swiftlint
quanganhdo Jul 17, 2024
7b5afe9
Merge branch 'main' into anh/ppro/pixels
quanganhdo Jul 17, 2024
5f357bb
Clean up
quanganhdo Jul 17, 2024
e01da3f
Merge branch 'main' into anh/ppro/pixels
quanganhdo Jul 17, 2024
e3e64e1
Update BSK
quanganhdo Jul 17, 2024
4bf93c8
Attach to all the pixels
quanganhdo Jul 17, 2024
e210c0b
Add origin from remote config
quanganhdo Jul 17, 2024
7f1f6b9
Update tests
quanganhdo Jul 17, 2024
8d687e1
Update BSK
quanganhdo Jul 17, 2024
6583b39
Merge branch 'main' into anh/ppro/pixel-params
quanganhdo Jul 17, 2024
839ae9b
Fix Debug feature
quanganhdo Jul 17, 2024
09e007a
Fix tests
quanganhdo Jul 17, 2024
7023cc2
Add wait(for:)
quanganhdo Jul 17, 2024
25b8119
More wait(for:)
quanganhdo Jul 17, 2024
c4a2f1e
Refactor
quanganhdo Jul 18, 2024
1af9b54
Fix Swiftlint
quanganhdo Jul 18, 2024
4c10370
Refactor
quanganhdo Jul 18, 2024
32e4dc2
Refactor
quanganhdo Jul 18, 2024
31734a8
Merge branch 'main' into anh/ppro/pixel-params
quanganhdo Jul 19, 2024
7f05bee
Update fireproofed site check
quanganhdo Jul 19, 2024
7ecd7f7
Refactor
quanganhdo Jul 19, 2024
f4fffb3
Fix Swiftlint
quanganhdo Jul 19, 2024
9409f36
Merge branch 'main' into anh/ppro/pixel-params
quanganhdo Jul 19, 2024
d80baa4
Merge branch 'main' into anh/ppro/pixel-params
quanganhdo Jul 22, 2024
d30fefb
Merge branch 'main' into anh/ppro/pixel-params
quanganhdo Jul 22, 2024
62acff1
Update tests
quanganhdo Jul 22, 2024
fdbbbcd
Update BSK
quanganhdo Jul 22, 2024
0cf2722
Merge branch 'main' into anh/ppro/pixel-params
quanganhdo Jul 22, 2024
360ec8c
Fix Swiftlint
quanganhdo Jul 22, 2024
f56d6d1
Update BSK
quanganhdo Jul 22, 2024
d092d9f
Update threshold
quanganhdo Jul 22, 2024
a7e3f43
DI instead of singleton
quanganhdo Jul 23, 2024
8252828
Fewer optionals
quanganhdo Jul 23, 2024
5236acd
Update BSK
quanganhdo Jul 23, 2024
c217905
Refactor
quanganhdo Jul 23, 2024
64ce406
Merge branch 'main' into anh/ppro/pixel-params
quanganhdo Jul 23, 2024
d0172f2
Fix failing tests
quanganhdo Jul 23, 2024
ab9e202
Fix origin params
quanganhdo Jul 23, 2024
37cfab6
Fix Swiftlint
quanganhdo Jul 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Core/DefaultVariantManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public struct VariantIOS: Variant {
}

/// This variant is used for returning users to separate them from really new users.
static let returningUser = VariantIOS(name: "ru", weight: doNotAllocate, isIncluded: When.always, features: [])
public static let returningUser = VariantIOS(name: "ru", weight: doNotAllocate, isIncluded: When.always, features: [])

static let doNotAllocate = 0

Expand Down
8 changes: 8 additions & 0 deletions DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,8 @@
BD862E0B2B30F9300073E2EE /* VPNFeedbackFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD862E0A2B30F9300073E2EE /* VPNFeedbackFormView.swift */; };
BDC234F72B27F51100D3C798 /* UniquePixel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDC234F62B27F51100D3C798 /* UniquePixel.swift */; };
BDD3B3552B8EF8DB005857A8 /* NetworkProtectionUNNotificationPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE3766DD2AC5945500AAB575 /* NetworkProtectionUNNotificationPresenter.swift */; };
BDE219E62C406D19005D5884 /* PrivacyProDataReporting.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDE219E52C406D19005D5884 /* PrivacyProDataReporting.swift */; };
BDE219EA2C457B46005D5884 /* PrivacyProDataReporterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDE219E92C457B46005D5884 /* PrivacyProDataReporterTests.swift */; };
BDF8D0022C1B87F4003E3B27 /* NetworkProtectionDNSSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDF8D0012C1B87F4003E3B27 /* NetworkProtectionDNSSettingsViewModel.swift */; };
BDFF031D2BA3D2BD00F324C9 /* DefaultNetworkProtectionVisibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDFF031C2BA3D2BD00F324C9 /* DefaultNetworkProtectionVisibility.swift */; };
BDFF03212BA3D3CF00F324C9 /* NetworkProtectionVisibilityForTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDFF03202BA3D3CF00F324C9 /* NetworkProtectionVisibilityForTunnelProvider.swift */; };
Expand Down Expand Up @@ -2401,6 +2403,8 @@
BD862E082B30F63E0073E2EE /* VPNMetadataCollector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNMetadataCollector.swift; sourceTree = "<group>"; };
BD862E0A2B30F9300073E2EE /* VPNFeedbackFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNFeedbackFormView.swift; sourceTree = "<group>"; };
BDC234F62B27F51100D3C798 /* UniquePixel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UniquePixel.swift; sourceTree = "<group>"; };
BDE219E52C406D19005D5884 /* PrivacyProDataReporting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyProDataReporting.swift; sourceTree = "<group>"; };
BDE219E92C457B46005D5884 /* PrivacyProDataReporterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrivacyProDataReporterTests.swift; sourceTree = "<group>"; };
BDF8D0012C1B87F4003E3B27 /* NetworkProtectionDNSSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionDNSSettingsViewModel.swift; sourceTree = "<group>"; };
BDFF03192BA39C5A00F324C9 /* NetworkProtectionFeatureVisibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionFeatureVisibility.swift; sourceTree = "<group>"; };
BDFF031C2BA3D2BD00F324C9 /* DefaultNetworkProtectionVisibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultNetworkProtectionVisibility.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4753,6 +4757,7 @@
D664C7B02B289AA000CBFA76 /* UserScripts */,
D664C7962B289AA000CBFA76 /* Extensions */,
D65CEA6F2B6AC6C9008A759B /* Subscription.xcassets */,
BDE219E52C406D19005D5884 /* PrivacyProDataReporting.swift */,
);
path = Subscription;
sourceTree = "<group>";
Expand Down Expand Up @@ -5501,6 +5506,7 @@
F1BDDBFC2C340D9C00459306 /* Subscription */ = {
isa = PBXGroup;
children = (
BDE219E92C457B46005D5884 /* PrivacyProDataReporterTests.swift */,
F1BDDBF92C340D9C00459306 /* SubscriptionContainerViewModelTests.swift */,
F1BDDBFA2C340D9C00459306 /* SubscriptionFlowViewModelTests.swift */,
F1BDDBFB2C340D9C00459306 /* SubscriptionPagesUseSubscriptionFeatureTests.swift */,
Expand Down Expand Up @@ -7057,6 +7063,7 @@
F1D796F01E7B07610019D451 /* BookmarksViewControllerCells.swift in Sources */,
9F9EE4D42C37BB1300D4118E /* OnboardingView+Landing.swift in Sources */,
85058369219F424500ED4EDB /* UIColorExtension.swift in Sources */,
BDE219E62C406D19005D5884 /* PrivacyProDataReporting.swift in Sources */,
D6E83C312B1EA309006C8AFB /* SettingsCell.swift in Sources */,
85058368219C49E000ED4EDB /* HomeViewSectionRenderers.swift in Sources */,
1DEAADEE2BA45DFE00E25A97 /* SettingsDataClearingView.swift in Sources */,
Expand Down Expand Up @@ -7221,6 +7228,7 @@
F1134EBC1F40D45700B73467 /* MockStatisticsStore.swift in Sources */,
983C52E72C2C0ACB007B5747 /* BookmarkStateRepairTests.swift in Sources */,
31C138AC27A403CB00FFD4B2 /* DownloadManagerTests.swift in Sources */,
BDE219EA2C457B46005D5884 /* PrivacyProDataReporterTests.swift in Sources */,
EEFE9C732A603CE9005B0A26 /* NetworkProtectionStatusViewModelTests.swift in Sources */,
F13B4BF91F18CA0600814661 /* TabsModelTests.swift in Sources */,
F1BDDBFD2C340D9C00459306 /* SubscriptionContainerViewModelTests.swift in Sources */,
Expand Down
20 changes: 18 additions & 2 deletions DuckDuckGo/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ import WebKit

private var autofillPixelReporter: AutofillPixelReporter?

var privacyProDataReporter: PrivacyProDataReporting!

// MARK: lifecycle

@UserDefaultsWrapper(key: .privacyConfigCustomURL, defaultValue: nil)
Expand Down Expand Up @@ -272,6 +274,8 @@ import WebKit
syncService.initializeIfNeeded()
self.syncService = syncService

privacyProDataReporter = PrivacyProDataReporter()

isSyncInProgressCancellable = syncService.isSyncInProgressPublisher
.filter { $0 }
.sink { [weak syncService] _ in
Expand All @@ -297,12 +301,15 @@ import WebKit
remoteMessagingClient.registerBackgroundRefreshTaskHandler()

homePageConfiguration = HomePageConfiguration(variantManager: AppDependencyProvider.shared.variantManager,
remoteMessagingClient: remoteMessagingClient)
remoteMessagingClient: remoteMessagingClient,
privacyProDataReporter: privacyProDataReporter)

let previewsSource = TabPreviewsSource()
let historyManager = makeHistoryManager()
let tabsModel = prepareTabsModel(previewsSource: previewsSource)

privacyProDataReporter.injectTabsModel(tabsModel)

let main = MainViewController(bookmarksDatabase: bookmarksDatabase,
bookmarksDatabaseCleaner: syncDataProviders.bookmarksAdapter.databaseCleaner,
historyManager: historyManager,
Expand All @@ -312,7 +319,8 @@ import WebKit
appSettings: AppDependencyProvider.shared.appSettings,
previewsSource: previewsSource,
tabsModel: tabsModel,
syncPausedStateManager: syncErrorHandler)
syncPausedStateManager: syncErrorHandler,
privacyProDataReporter: privacyProDataReporter)

main.loadViewIfNeeded()
syncErrorHandler.alertPresenter = main
Expand Down Expand Up @@ -510,6 +518,9 @@ import WebKit
}

syncService.scheduler.notifyAppLifecycleEvent()

privacyProDataReporter.injectSyncService(syncService)

fireFailedCompilationsPixelIfNeeded()

#if NETWORK_PROTECTION
Expand All @@ -536,6 +547,10 @@ import WebKit

let importPasswordsStatusHandler = ImportPasswordsStatusHandler(syncService: syncService)
importPasswordsStatusHandler.checkSyncSuccessStatus()

Task {
await privacyProDataReporter.saveWidgetAdded()
}
}

private func stopAndRemoveVPNIfNotAuthenticated() async {
Expand Down Expand Up @@ -646,6 +661,7 @@ import WebKit
AppDependencyProvider.shared.autofillLoginSession.endSession()
suspendSync()
syncDataProviders.bookmarksAdapter.cancelFaviconsFetching(application)
privacyProDataReporter.saveApplicationLastSessionEnded()
}

private func suspendSync() {
Expand Down
3 changes: 2 additions & 1 deletion DuckDuckGo/HomeCollectionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ class HomeCollectionView: UICollectionView {
renderers.install(renderer: renderer)

case .homeMessage:
renderers.install(renderer: HomeMessageViewSectionRenderer(homePageConfiguration: homePageConfiguration))
renderers.install(renderer: HomeMessageViewSectionRenderer(homePageConfiguration: homePageConfiguration,
privacyProDataReporter: controller.privacyProDataReporter))
}

}
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/HomeMessageCollectionViewCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ final class HomeMessageCollectionViewCell: SwiftUICollectionViewCell<HomeMessage
static let maximumWidthPad: CGFloat = 455

static var reuseIdentifier = "HomeMessageCell"

func configure(with viewModel: HomeMessageViewModel, parent: UIViewController) {
embed(in: parent, withView: HomeMessageView(viewModel: viewModel))
host?.view.frame = contentView.bounds
Expand Down
18 changes: 9 additions & 9 deletions DuckDuckGo/HomeMessageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,12 @@ struct HomeMessageView: View {
.padding([.bottom], Const.Padding.buttonVerticalInset)
.sheet(item: $activityItem) { activityItem in
ActivityViewController(activityItems: [activityItem.item]) { _, result, _, _ in

Pixel.fire(pixel: .remoteMessageSheet, withAdditionalParameters: [
var additionalParameters = [
PixelParameters.message: "\(viewModel.messageId)",
PixelParameters.sheetResult: "\(result)"
])

]
additionalParameters = viewModel.onAttachAdditionalParameters?(.messageID(viewModel.messageId), additionalParameters) ?? additionalParameters
Pixel.fire(pixel: .remoteMessageSheet, withAdditionalParameters: additionalParameters)
}
.modifier(ActivityViewPresentationModifier())
}
Expand Down Expand Up @@ -329,27 +329,27 @@ struct HomeMessageView_Previews: PreviewProvider {
HomeMessageView(viewModel: HomeMessageViewModel(messageId: "Small",
sendPixels: false,
modelType: small,
onDidClose: { _ in }, onDidAppear: {}))
onDidClose: { _ in }, onDidAppear: {}, onAttachAdditionalParameters: { _, params in params }))

HomeMessageView(viewModel: HomeMessageViewModel(messageId: "Critical",
sendPixels: false,
modelType: critical,
onDidClose: { _ in }, onDidAppear: {}))
onDidClose: { _ in }, onDidAppear: {}, onAttachAdditionalParameters: { _, params in params }))

HomeMessageView(viewModel: HomeMessageViewModel(messageId: "Big Single",
sendPixels: false,
modelType: bigSingle,
onDidClose: { _ in }, onDidAppear: {}))
onDidClose: { _ in }, onDidAppear: {}, onAttachAdditionalParameters: { _, params in params }))

HomeMessageView(viewModel: HomeMessageViewModel(messageId: "Big Two",
sendPixels: false,
modelType: bigTwo,
onDidClose: { _ in }, onDidAppear: {}))
onDidClose: { _ in }, onDidAppear: {}, onAttachAdditionalParameters: { _, params in params }))

HomeMessageView(viewModel: HomeMessageViewModel(messageId: "Promo",
sendPixels: false,
modelType: promo,
onDidClose: { _ in }, onDidAppear: {}))
onDidClose: { _ in }, onDidAppear: {}, onAttachAdditionalParameters: { _, params in params }))
}
.frame(height: 200)
.padding(.horizontal)
Expand Down
1 change: 1 addition & 0 deletions DuckDuckGo/HomeMessageViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ struct HomeMessageViewModel {

let onDidClose: (ButtonAction?) -> Void
let onDidAppear: () -> Void
let onAttachAdditionalParameters: ((_ useCase: PrivacyProDataReportingUseCase, _ params: [String: String]) -> [String: String])?

func mapActionToViewModel(remoteAction: RemoteAction,
buttonAction: HomeMessageViewModel.ButtonAction,
Expand Down
6 changes: 5 additions & 1 deletion DuckDuckGo/HomeMessageViewModelBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct HomeMessageViewModelBuilder {
}

static func build(for remoteMessage: RemoteMessageModel,
with privacyProDataReporter: PrivacyProDataReporting?,
onDidClose: @escaping (HomeMessageViewModel.ButtonAction?) -> Void,
onDidAppear: @escaping () -> Void) -> HomeMessageViewModel? {
guard let content = remoteMessage.content else { return nil }
Expand All @@ -42,7 +43,10 @@ struct HomeMessageViewModelBuilder {
sendPixels: remoteMessage.isMetricsEnabled,
modelType: content,
onDidClose: onDidClose,
onDidAppear: onDidAppear
onDidAppear: onDidAppear,
onAttachAdditionalParameters: { useCase, params in
privacyProDataReporter?.mergeRandomizedParameters(for: useCase, with: params) ?? params
}
)
}

Expand Down
31 changes: 20 additions & 11 deletions DuckDuckGo/HomeMessageViewSectionRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@ class HomeMessageViewSectionRenderer: NSObject, HomeViewSectionRenderer {
private weak var controller: HomeViewController?

private let homePageConfiguration: HomePageConfiguration

init(homePageConfiguration: HomePageConfiguration) {
private let privacyProDataReporter: PrivacyProDataReporting?

init(homePageConfiguration: HomePageConfiguration, privacyProDataReporter: PrivacyProDataReporting?) {
self.homePageConfiguration = homePageConfiguration
self.privacyProDataReporter = privacyProDataReporter
super.init()
}

func install(into controller: HomeViewController) {
self.controller = controller
hideLogoIfThereAreMessagesToDisplay()
Expand Down Expand Up @@ -113,12 +115,13 @@ class HomeMessageViewSectionRenderer: NSObject, HomeViewSectionRenderer {
self?.dismissHomeMessage(message, at: indexPath, in: collectionView)
} onDidAppear: {
// no-op
} onAttachAdditionalParameters: { _, params in
params
}
case .remoteMessage(let remoteMessage):
return HomeMessageViewModelBuilder.build(for: remoteMessage) { [weak self] action in

return HomeMessageViewModelBuilder.build(for: remoteMessage, with: privacyProDataReporter) { [weak self] action in
guard let action,
let self else { return }
let self else { return }

switch action {

Expand All @@ -128,7 +131,7 @@ class HomeMessageViewSectionRenderer: NSObject, HomeViewSectionRenderer {
}
if remoteMessage.isMetricsEnabled {
Pixel.fire(pixel: .remoteMessageActionClicked,
withAdditionalParameters: [PixelParameters.message: "\(remoteMessage.id)"])
withAdditionalParameters: self.additionalParameters(for: remoteMessage.id))
}

case .primaryAction(let isSharing):
Expand All @@ -137,7 +140,7 @@ class HomeMessageViewSectionRenderer: NSObject, HomeViewSectionRenderer {
}
if remoteMessage.isMetricsEnabled {
Pixel.fire(pixel: .remoteMessagePrimaryActionClicked,
withAdditionalParameters: [PixelParameters.message: "\(remoteMessage.id)"])
withAdditionalParameters: self.additionalParameters(for: remoteMessage.id))
}

case .secondaryAction(let isSharing):
Expand All @@ -146,14 +149,14 @@ class HomeMessageViewSectionRenderer: NSObject, HomeViewSectionRenderer {
}
if remoteMessage.isMetricsEnabled {
Pixel.fire(pixel: .remoteMessageSecondaryActionClicked,
withAdditionalParameters: [PixelParameters.message: "\(remoteMessage.id)"])
withAdditionalParameters: self.additionalParameters(for: remoteMessage.id))
}

case .close:
self.dismissHomeMessage(message, at: indexPath, in: collectionView)
if remoteMessage.isMetricsEnabled {
Pixel.fire(pixel: .remoteMessageDismissed,
withAdditionalParameters: [PixelParameters.message: "\(remoteMessage.id)"])
withAdditionalParameters: self.additionalParameters(for: remoteMessage.id))
}

}
Expand All @@ -162,7 +165,13 @@ class HomeMessageViewSectionRenderer: NSObject, HomeViewSectionRenderer {
}
}
}


private func additionalParameters(for messageID: String) -> [String: String] {
let defaultParameters = [PixelParameters.message: "\(messageID)"]
return privacyProDataReporter?.mergeRandomizedParameters(for: .messageID(messageID),
with: defaultParameters) ?? defaultParameters
}

private func dismissHomeMessage(_ message: HomeMessage,
at indexPath: IndexPath,
in collectionView: UICollectionView) {
Expand Down
Loading
Loading