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

Additional PIR opt out confirmation pixels #3119

Merged
merged 18 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions DuckDuckGo/DBP/DataBrokerProtectionPixelsHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ public class DataBrokerProtectionPixelsHandler: EventMapping<DataBrokerProtectio
.monthlyActiveUser,
.weeklyReportScanning,
.weeklyReportRemovals,
.optOutJobAt7DaysConfirmed,
.optOutJobAt7DaysUnconfirmed,
.optOutJobAt14DaysConfirmed,
.optOutJobAt14DaysUnconfirmed,
.optOutJobAt21DaysConfirmed,
.optOutJobAt21DaysUnconfirmed,
.scanningEventNewMatch,
.scanningEventReAppearance,
.webUILoadingFailed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,22 @@ protocol DataBrokerProtectionRepository {
func updatePreferredRunDate(_ date: Date?, brokerId: Int64, profileQueryId: Int64, extractedProfileId: Int64) throws
func updateLastRunDate(_ date: Date?, brokerId: Int64, profileQueryId: Int64) throws
func updateLastRunDate(_ date: Date?, brokerId: Int64, profileQueryId: Int64, extractedProfileId: Int64) throws
func updateSubmittedSuccessfullyDate(_ date: Date?,
forBrokerId brokerId: Int64,
profileQueryId: Int64,
extractedProfileId: Int64) throws
func updateSevenDaysConfirmationPixelFired(_ pixelFired: Bool,
forBrokerId brokerId: Int64,
profileQueryId: Int64,
extractedProfileId: Int64) throws
func updateFourteenDaysConfirmationPixelFired(_ pixelFired: Bool,
forBrokerId brokerId: Int64,
profileQueryId: Int64,
extractedProfileId: Int64) throws
func updateTwentyOneDaysConfirmationPixelFired(_ pixelFired: Bool,
forBrokerId brokerId: Int64,
profileQueryId: Int64,
extractedProfileId: Int64) throws
func updateRemovedDate(_ date: Date?, on extractedProfileId: Int64) throws

func add(_ historyEvent: HistoryEvent) throws
Expand Down Expand Up @@ -221,6 +237,86 @@ final class DataBrokerProtectionDatabase: DataBrokerProtectionRepository {
}
}

func updateSubmittedSuccessfullyDate(_ date: Date?,
forBrokerId brokerId: Int64,
profileQueryId: Int64,
extractedProfileId: Int64) throws {
do {
let vault = try self.vault ?? DataBrokerProtectionSecureVaultFactory.makeVault(reporter: secureVaultErrorReporter)

try vault.updateSubmittedSuccessfullyDate(
date,
forBrokerId: brokerId,
profileQueryId: profileQueryId,
extractedProfileId: extractedProfileId
)
} catch {
os_log("Database error: updateSubmittedSuccessfullyDate, error: %{public}@", log: .error, error.localizedDescription)
pixelHandler.fire(.generalError(error: error, functionOccurredIn: "DataBrokerProtectionDatabase.updateSubmittedSuccessfullyDate date forBrokerId profileQueryId extractedProfileId"))
throw error
}
}

func updateSevenDaysConfirmationPixelFired(_ pixelFired: Bool,
forBrokerId brokerId: Int64,
profileQueryId: Int64,
extractedProfileId: Int64) throws {
do {
let vault = try self.vault ?? DataBrokerProtectionSecureVaultFactory.makeVault(reporter: secureVaultErrorReporter)

try vault.updateSevenDaysConfirmationPixelFired(
pixelFired,
forBrokerId: brokerId,
profileQueryId: profileQueryId,
extractedProfileId: extractedProfileId
)
} catch {
os_log("Database error: updateSevenDaysConfirmationPixelFired, error: %{public}@", log: .error, error.localizedDescription)
pixelHandler.fire(.generalError(error: error, functionOccurredIn: "DataBrokerProtectionDatabase.updateSevenDaysConfirmationPixelFired pixelFired forBrokerId profileQueryId extractedProfileId"))
throw error
}
}

func updateFourteenDaysConfirmationPixelFired(_ pixelFired: Bool,
forBrokerId brokerId: Int64,
profileQueryId: Int64,
extractedProfileId: Int64) throws {
do {
let vault = try self.vault ?? DataBrokerProtectionSecureVaultFactory.makeVault(reporter: secureVaultErrorReporter)

try vault.updateFourteenDaysConfirmationPixelFired(
pixelFired,
forBrokerId: brokerId,
profileQueryId: profileQueryId,
extractedProfileId: extractedProfileId
)
} catch {
os_log("Database error: updateFourteenDaysConfirmationPixelFired, error: %{public}@", log: .error, error.localizedDescription)
pixelHandler.fire(.generalError(error: error, functionOccurredIn: "DataBrokerProtectionDatabase.updateFourteenDaysConfirmationPixelFired pixelFired forBrokerId profileQueryId extractedProfileId"))
throw error
}
}

func updateTwentyOneDaysConfirmationPixelFired(_ pixelFired: Bool,
forBrokerId brokerId: Int64,
profileQueryId: Int64,
extractedProfileId: Int64) throws {
do {
let vault = try self.vault ?? DataBrokerProtectionSecureVaultFactory.makeVault(reporter: secureVaultErrorReporter)

try vault.updateTwentyOneDaysConfirmationPixelFired(
pixelFired,
forBrokerId: brokerId,
profileQueryId: profileQueryId,
extractedProfileId: extractedProfileId
)
} catch {
os_log("Database error: updateTwentyOneDaysConfirmationPixelFired, error: %{public}@", log: .error, error.localizedDescription)
pixelHandler.fire(.generalError(error: error, functionOccurredIn: "DataBrokerProtectionDatabase.updateTwentyOneDaysConfirmationPixelFired pixelFired forBrokerId profileQueryId extractedProfileId"))
throw error
}
}

func updateRemovedDate(_ date: Date?, on extractedProfileId: Int64) throws {
do {
let vault = try self.vault ?? DataBrokerProtectionSecureVaultFactory.makeVault(reporter: secureVaultErrorReporter)
Expand Down Expand Up @@ -288,8 +384,13 @@ final class DataBrokerProtectionDatabase: DataBrokerProtectionRepository {
try vault.save(brokerId: optOut.brokerId,
profileQueryId: optOut.profileQueryId,
extractedProfile: extractedProfile,
createdDate: optOut.createdDate,
lastRunDate: optOut.lastRunDate,
preferredRunDate: optOut.preferredRunDate)
preferredRunDate: optOut.preferredRunDate,
submittedSuccessfullyDate: optOut.submittedSuccessfullyDate,
sevenDaysConfirmationPixelFired: optOut.sevenDaysConfirmationPixelFired,
fourteenDaysConfirmationPixelFired: optOut.fourteenDaysConfirmationPixelFired,
twentyOneDaysConfirmationPixelFired: optOut.twentyOneDaysConfirmationPixelFired)
} catch {
os_log("Database error: saveOptOutOperation, error: %{public}@", log: .error, error.localizedDescription)
pixelHandler.fire(.generalError(error: error, functionOccurredIn: "DataBrokerProtectionDatabase.saveOptOutOperation optOut extractedProfile"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,40 @@ struct ScanJobData: BrokerJobData, Sendable {
struct OptOutJobData: BrokerJobData, Sendable {
let brokerId: Int64
let profileQueryId: Int64
let createdDate: Date
let preferredRunDate: Date?
let historyEvents: [HistoryEvent]
let lastRunDate: Date?

// This was added in a later DB migration (V4), so will be nil for older entries submitted before the migration
let submittedSuccessfullyDate: Date?
Copy link
Contributor

Choose a reason for hiding this comment

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

👏🏼


let extractedProfile: ExtractedProfile
let sevenDaysConfirmationPixelFired: Bool
let fourteenDaysConfirmationPixelFired: Bool
let twentyOneDaysConfirmationPixelFired: Bool

init(brokerId: Int64,
profileQueryId: Int64,
createdDate: Date,
preferredRunDate: Date? = nil,
historyEvents: [HistoryEvent],
lastRunDate: Date? = nil,
extractedProfile: ExtractedProfile) {
submittedSuccessfullyDate: Date? = nil,
extractedProfile: ExtractedProfile,
sevenDaysConfirmationPixelFired: Bool = false,
fourteenDaysConfirmationPixelFired: Bool = false,
twentyOneDaysConfirmationPixelFired: Bool = false) {
self.brokerId = brokerId
self.profileQueryId = profileQueryId
self.createdDate = createdDate
self.preferredRunDate = preferredRunDate
self.historyEvents = historyEvents
self.lastRunDate = lastRunDate
self.submittedSuccessfullyDate = submittedSuccessfullyDate
self.extractedProfile = extractedProfile
self.sevenDaysConfirmationPixelFired = sevenDaysConfirmationPixelFired
self.fourteenDaysConfirmationPixelFired = fourteenDaysConfirmationPixelFired
self.twentyOneDaysConfirmationPixelFired = twentyOneDaysConfirmationPixelFired
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,15 @@ struct DataBrokerProfileQueryOperationManager: OperationsManager {
// we insert the opt-out operation, we do not want to do things separately in case creating an opt-out fails
// causing the extracted profile to be orphan.
let optOutJobData = OptOutJobData(brokerId: brokerId,
profileQueryId: profileQueryId,
preferredRunDate: preferredRunOperation,
historyEvents: [HistoryEvent](),
extractedProfile: extractedProfile)
profileQueryId: profileQueryId,
createdDate: Date(),
preferredRunDate: preferredRunOperation,
historyEvents: [HistoryEvent](),
submittedSuccessfullyDate: nil,
extractedProfile: extractedProfile,
sevenDaysConfirmationPixelFired: false,
fourteenDaysConfirmationPixelFired: false,
twentyOneDaysConfirmationPixelFired: false)

try database.saveOptOutJob(optOut: optOutJobData, extractedProfile: extractedProfile)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,15 @@ struct OperationPreferredDateUpdaterUseCase: OperationPreferredDateUpdater {
profileQueryId: profileQueryId,
extractedProfileId: extractedProfileId)
}

if let extractedProfileId = extractedProfileId,
let optOutJob = optOutJob,
let lastEvent = brokerProfileQuery.events.last,
lastEvent.type == .optOutRequested && optOutJob.submittedSuccessfullyDate == nil
{
let submittedSuccessfullyDate = SystemDate().now
try database.updateSubmittedSuccessfullyDate(submittedSuccessfullyDate, forBrokerId: brokerId, profileQueryId: profileQueryId, extractedProfileId: extractedProfileId)
}
}

private func returnMostRecentDate(_ date1: Date?, _ date2: Date?) -> Date? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,14 @@ public enum DataBrokerProtectionPixels {
case scanningEventNewMatch
case scanningEventReAppearance

// Additional opt out metrics
case optOutJobAt7DaysConfirmed(dataBroker: String)
case optOutJobAt7DaysUnconfirmed(dataBroker: String)
case optOutJobAt14DaysConfirmed(dataBroker: String)
case optOutJobAt14DaysUnconfirmed(dataBroker: String)
case optOutJobAt21DaysConfirmed(dataBroker: String)
case optOutJobAt21DaysUnconfirmed(dataBroker: String)

// Web UI - loading errors
case webUILoadingStarted(environment: String)
case webUILoadingFailed(errorCategory: String)
Expand Down Expand Up @@ -279,6 +287,14 @@ extension DataBrokerProtectionPixels: PixelKitEvent {
case .webUILoadingSuccess: return "m_mac_dbp_web_ui_loading_success"
case .webUILoadingFailed: return "m_mac_dbp_web_ui_loading_failed"

// Additional opt out metrics
case .optOutJobAt7DaysConfirmed: return "m_mac_dbp_optoutjob_at-7-days_confirmed"
case .optOutJobAt7DaysUnconfirmed: return "m_mac_dbp_optoutjob_at-7-days_unconfirmed"
case .optOutJobAt14DaysConfirmed: return "m_mac_dbp_optoutjob_at-14-days_confirmed"
case .optOutJobAt14DaysUnconfirmed: return "m_mac_dbp_optoutjob_at-14-days_unconfirmed"
case .optOutJobAt21DaysConfirmed: return "m_mac_dbp_optoutjob_at-21-days_confirmed"
case .optOutJobAt21DaysUnconfirmed: return "m_mac_dbp_optoutjob_at-21-days_unconfirmed"

// Backend service errors
case .generateEmailHTTPErrorDaily: return "m_mac_dbp_service_email-generate-http-error"
case .emptyAccessTokenDaily: return "m_mac_dbp_service_empty-auth-token"
Expand Down Expand Up @@ -376,6 +392,13 @@ extension DataBrokerProtectionPixels: PixelKitEvent {
return [Consts.hadNewMatch: hadNewMatch ? "1" : "0", Consts.hadReAppereance: hadReAppereance ? "1" : "0", Consts.scanCoverage: scanCoverage.description]
case .weeklyReportRemovals(let removals):
return [Consts.removals: String(removals)]
case .optOutJobAt7DaysConfirmed(let dataBroker),
.optOutJobAt7DaysUnconfirmed(let dataBroker),
.optOutJobAt14DaysConfirmed(let dataBroker),
.optOutJobAt14DaysUnconfirmed(let dataBroker),
.optOutJobAt21DaysConfirmed(let dataBroker),
.optOutJobAt21DaysUnconfirmed(let dataBroker):
return [Consts.dataBrokerParamKey: dataBroker]
case .webUILoadingStarted(let environment):
return [Consts.environmentKey: environment]
case .webUILoadingSuccess(let environment):
Expand Down Expand Up @@ -537,6 +560,12 @@ public class DataBrokerProtectionPixelsHandler: EventMapping<DataBrokerProtectio
.monthlyActiveUser,
.weeklyReportScanning,
.weeklyReportRemovals,
.optOutJobAt7DaysConfirmed,
.optOutJobAt7DaysUnconfirmed,
.optOutJobAt14DaysConfirmed,
.optOutJobAt14DaysUnconfirmed,
.optOutJobAt21DaysConfirmed,
.optOutJobAt21DaysUnconfirmed,
.scanningEventNewMatch,
.scanningEventReAppearance,
.webUILoadingFailed,
Expand Down
Loading
Loading