Skip to content

Commit

Permalink
Fixes duplicate Refresh Pixel
Browse files Browse the repository at this point in the history
  • Loading branch information
afterxleep committed Nov 13, 2024
1 parent 32c8eff commit b1b4b0f
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 16 deletions.
14 changes: 13 additions & 1 deletion DuckDuckGo/DuckPlayer/DuckPlayerNavigationHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,7 @@ extension DuckPlayerNavigationHandler: DuckPlayerNavigationHandling {
// Overlay Usage Pixel handling
if let url = webView.url {
duckPlayerOverlayUsagePixels?.handleNavigationAndFirePixels(url: url, duckPlayerMode: duckPlayerMode)
lastURLChangeHandling = Date()
}

// Check if DuckPlayer feature is enabled
Expand Down Expand Up @@ -835,6 +836,17 @@ extension DuckPlayerNavigationHandler: DuckPlayerNavigationHandling {
// Reset allowFirstVideo
duckPlayer.settings.allowFirstVideo = false

// Overlay Usage Pixel handling for Direct Navigation
if let url = webView.url, !url.isYoutube {
duckPlayerOverlayUsagePixels?.handleNavigationAndFirePixels(url: url, duckPlayerMode: duckPlayerMode)
}
// Reset Overlay Last Fired pixel after the page is loaded
// A delay is required as Youtube sometimes performs an extra redirect on load
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
self.duckPlayerOverlayUsagePixels?.lastFiredPixel = nil
}


}

/// Resets settings when the web view starts loading a new page.
Expand Down Expand Up @@ -892,7 +904,7 @@ extension DuckPlayerNavigationHandler: DuckPlayerNavigationHandling {
guard isDuckPlayerFeatureEnabled else {
return false
}

// Only account for in 'Always' mode
if duckPlayerMode == .disabled {
return false
Expand Down
34 changes: 19 additions & 15 deletions DuckDuckGo/DuckPlayer/DuckPlayerOverlayUsagePixels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ protocol DuckPlayerOverlayPixelFiring {

var pixelFiring: PixelFiring.Type { get set }
var navigationHistory: [URL] { get set }
var lastFiredPixel: Pixel.Event? { get set }

func handleNavigationAndFirePixels(url: URL?, duckPlayerMode: DuckPlayerMode)
}
Expand All @@ -31,6 +32,7 @@ final class DuckPlayerOverlayUsagePixels: DuckPlayerOverlayPixelFiring {

var pixelFiring: PixelFiring.Type
var navigationHistory: [URL] = []
var lastFiredPixel: Pixel.Event?

private var idleTimer: Timer?
private var idleTimeInterval: TimeInterval
Expand All @@ -42,12 +44,6 @@ final class DuckPlayerOverlayUsagePixels: DuckPlayerOverlayPixelFiring {
self.idleTimeInterval = timeoutInterval
}

// Method to reset the idle timer
private func resetIdleTimer() {
idleTimer?.invalidate()
idleTimer = nil
}

func handleNavigationAndFirePixels(url: URL?, duckPlayerMode: DuckPlayerMode) {
guard let url = url else { return }
let comparisonURL = url.forComparison()
Expand All @@ -72,31 +68,39 @@ final class DuckPlayerOverlayUsagePixels: DuckPlayerOverlayPixelFiring {

// Fire the reload pixel if this is a reload navigation
if isReload {
pixelFiring.fire(.duckPlayerYouTubeOverlayNavigationRefresh, withAdditionalParameters: [:])
firePixel(.duckPlayerYouTubeOverlayNavigationRefresh)
} else {
// Determine if it’s a back navigation by looking further back in history
let isBackNavigation = navigationHistory.count > 2 &&
navigationHistory[navigationHistory.count - 3].forComparison() == currentURL.forComparison()

// Fire the appropriate pixel based on navigation type
if isBackNavigation {
pixelFiring.fire(.duckPlayerYouTubeOverlayNavigationBack, withAdditionalParameters: [:])
firePixel(.duckPlayerYouTubeOverlayNavigationBack)
} else if previousURL.isYoutubeWatch && currentURL.isYoutube {
// Forward navigation within YouTube (including non-video URLs)
pixelFiring.fire(.duckPlayerYouTubeNavigationWithinYouTube, withAdditionalParameters: [:])
firePixel(.duckPlayerYouTubeNavigationWithinYouTube)
} else if previousURL.isYoutubeWatch && !currentURL.isYoutube && !currentURL.isDuckPlayer {
// Navigation outside YouTube
pixelFiring.fire(.duckPlayerYouTubeOverlayNavigationOutsideYoutube, withAdditionalParameters: [:])
firePixel(.duckPlayerYouTubeOverlayNavigationOutsideYoutube)
navigationHistory.removeAll()
}
}

// Truncation logic: Remove all URLs up to the last occurrence of the current URL in normalized form
if let lastOccurrenceIndex = (0..<navigationHistory.count - 1).last(where: { navigationHistory[$0].forComparison() == comparisonURL }) {
navigationHistory = Array(navigationHistory.prefix(upTo: lastOccurrenceIndex + 1))
if navigationHistory.count > 0 {
if let lastOccurrenceIndex = (0..<navigationHistory.count - 1).last(where: { navigationHistory[$0].forComparison() == comparisonURL }) {
navigationHistory = Array(navigationHistory.prefix(upTo: lastOccurrenceIndex + 1))
}
}

// Cancel and reset the idle timer whenever a new navigation occurs
resetIdleTimer()
}

private func firePixel(_ pixel: Pixel.Event) {
if lastFiredPixel == .duckPlayerYouTubeOverlayNavigationRefresh && pixel == .duckPlayerYouTubeOverlayNavigationRefresh {
return
}
lastFiredPixel = pixel
pixelFiring.fire(pixel, withAdditionalParameters: [:])
}


Expand Down

0 comments on commit b1b4b0f

Please sign in to comment.