Skip to content

Commit

Permalink
FXIOS-11121 #24248 [Sponsored tiles] Ensure we send to both places fo…
Browse files Browse the repository at this point in the history
…r telemetry (#24257)

* Ensure we send to both places for telemetry

* Add tests, remove static from SponsoredTileTelemetry todo so

* Fix

* Remove savedEvent and replace with SavedEvents

* Add event check on array

* Adjust for latest main
  • Loading branch information
lmarceau authored Jan 21, 2025
1 parent b478956 commit 999680a
Show file tree
Hide file tree
Showing 14 changed files with 274 additions and 140 deletions.
2 changes: 1 addition & 1 deletion firefox-ios/Client/AdjustTelemetryHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
// telemetry.record(network: network)
// }
//
// gleanWrapper.submitPing()
// gleanWrapper.submit(GleanMetrics.Pings.shared.firstSession)
// }
//}
// swiftlint:enable comment_spacing file_header
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ final class TopSiteState: Hashable, Equatable {
// Only sending sponsored tile impressions for now
guard let tile = site as? SponsoredTile else { return }

SponsoredTileTelemetry.sendImpressionTelemetry(tile: tile, position: position)
DefaultSponsoredTileTelemetry().sendImpressionTelemetry(tile: tile, position: position)
}

func getTelemetrySiteType() -> String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,30 @@ protocol UnifiedAdsCallbackTelemetry {
}

final class DefaultUnifiedAdsCallbackTelemetry: UnifiedAdsCallbackTelemetry {
private var networking: ContileNetworking
private var logger: Logger
private let networking: ContileNetworking
private let logger: Logger
private let sponsoredTileTelemetry: SponsoredTileTelemetry

init(
networking: ContileNetworking = DefaultContileNetwork(with: NetworkUtils.defaultURLSession()),
logger: Logger = DefaultLogger.shared
logger: Logger = DefaultLogger.shared,
sponsoredTileTelemetry: SponsoredTileTelemetry = DefaultSponsoredTileTelemetry()
) {
self.networking = networking
self.logger = logger
self.sponsoredTileTelemetry = sponsoredTileTelemetry
}

func sendImpressionTelemetry(tile: SponsoredTile, position: Int) {
let impressionURL = tile.impressionURL
sendTelemetry(urlString: impressionURL, position: position)
sendLegacyImpressionTelemetry(tile: tile, position: position)
}

func sendClickTelemetry(tile: SponsoredTile, position: Int) {
let clickURL = tile.clickURL
sendTelemetry(urlString: clickURL, position: position)
sendLegacyClickTelemetry(tile: tile, position: position)
}

private func sendTelemetry(urlString: String, position: Int) {
Expand Down Expand Up @@ -67,4 +72,16 @@ final class DefaultUnifiedAdsCallbackTelemetry: UnifiedAdsCallbackTelemetry {
}
}
}

// MARK: Legacy telemetry
// FXIOS-11121 While we are migrating to the new Unified Ads telemetry system, we should
// keep sending the legacy telemetry Glean pings

private func sendLegacyImpressionTelemetry(tile: SponsoredTile, position: Int) {
sponsoredTileTelemetry.sendImpressionTelemetry(tile: tile, position: position, isUnifiedAdsEnabled: true)
}

private func sendLegacyClickTelemetry(tile: SponsoredTile, position: Int) {
sponsoredTileTelemetry.sendClickTelemetry(tile: tile, position: position, isUnifiedAdsEnabled: true)
}
}
11 changes: 0 additions & 11 deletions firefox-ios/Client/Frontend/Home/TopSites/TopSite.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,6 @@ final class TopSite: FeatureFlaggable {

// MARK: Telemetry

func impressionTracking(position: Int, unifiedAdsTelemetry: UnifiedAdsCallbackTelemetry) {
// Only sending sponsored tile impressions for now
guard let tile = site as? SponsoredTile else { return }

if featureFlags.isFeatureEnabled(.unifiedAds, checking: .buildOnly) {
unifiedAdsTelemetry.sendImpressionTelemetry(tile: tile, position: position)
} else {
SponsoredTileTelemetry.sendImpressionTelemetry(tile: tile, position: position)
}
}

func getTelemetrySiteType() -> String {
if isPinned && isGoogleGUID {
return "google"
Expand Down
15 changes: 13 additions & 2 deletions firefox-ios/Client/Frontend/Home/TopSites/TopSitesViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ class TopSitesViewModel {
private let googleTopSiteManager: GoogleTopSiteManager
private var wallpaperManager: WallpaperManager
private let unifiedAdsTelemetry: UnifiedAdsCallbackTelemetry
private let sponsoredTileTelemetry: SponsoredTileTelemetry

init(profile: Profile,
isZeroSearch: Bool = false,
theme: Theme,
wallpaperManager: WallpaperManager,
sponsoredTileTelemetry: SponsoredTileTelemetry = DefaultSponsoredTileTelemetry(),
unifiedAdsTelemetry: UnifiedAdsCallbackTelemetry = DefaultUnifiedAdsCallbackTelemetry()) {
self.profile = profile
self.isZeroSearch = isZeroSearch
Expand All @@ -52,6 +54,7 @@ class TopSitesViewModel {
topSitesDataAdaptor = adaptor
self.wallpaperManager = wallpaperManager
self.unifiedAdsTelemetry = unifiedAdsTelemetry
self.sponsoredTileTelemetry = sponsoredTileTelemetry
adaptor.delegate = self
}

Expand All @@ -64,7 +67,15 @@ class TopSitesViewModel {

func sendImpressionTelemetry(_ homeTopSite: TopSite, position: Int) {
guard !hasSentImpressionForTile(homeTopSite) else { return }
homeTopSite.impressionTracking(position: position, unifiedAdsTelemetry: unifiedAdsTelemetry)

// Only sending sponsored tile impressions for now
guard let tile = homeTopSite.site as? SponsoredTile else { return }

if featureFlags.isFeatureEnabled(.unifiedAds, checking: .buildOnly) {
unifiedAdsTelemetry.sendImpressionTelemetry(tile: tile, position: position)
} else {
sponsoredTileTelemetry.sendImpressionTelemetry(tile: tile, position: position)
}
}

private func topSitePressTracking(homeTopSite: TopSite, position: Int) {
Expand Down Expand Up @@ -95,7 +106,7 @@ class TopSitesViewModel {
if featureFlags.isFeatureEnabled(.unifiedAds, checking: .buildOnly) {
unifiedAdsTelemetry.sendClickTelemetry(tile: tile, position: position)
} else {
SponsoredTileTelemetry.sendClickTelemetry(tile: tile, position: position)
sponsoredTileTelemetry.sendClickTelemetry(tile: tile, position: position)
}
}
}
Expand Down
20 changes: 15 additions & 5 deletions firefox-ios/Client/Telemetry/GleanWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import Glean
protocol GleanWrapper {
func handleDeeplinkUrl(url: URL)
func setUpload(isEnabled: Bool)
func submitPing()

// MARK: Glean Metrics

Expand All @@ -20,6 +19,7 @@ protocol GleanWrapper {
func recordLabel(for metric: LabeledMetricType<CounterMetricType>, label: String)
func setBoolean(for metric: BooleanMetricType, value: Bool)
func recordQuantity(for metric: QuantityMetricType, value: Int64)
func recordUrl(for metric: UrlMetricType, value: String)

func incrementNumerator(for metric: RateMetricType, amount: Int32)
func incrementDenominator(for metric: RateMetricType, amount: Int32)
Expand All @@ -31,6 +31,10 @@ protocol GleanWrapper {
timerId: GleanTimerId)
func stopAndAccumulateTiming(for metric: TimingDistributionMetricType,
timerId: GleanTimerId)

// MARK: Pings

func submit<ReasonCodesEnum>(ping: Ping<ReasonCodesEnum>) where ReasonCodesEnum: ReasonCodes
}

/// Glean wrapper to abstract Glean from our application
Expand All @@ -49,10 +53,6 @@ struct DefaultGleanWrapper: GleanWrapper {
glean.setCollectionEnabled(isEnabled)
}

func submitPing() {
GleanMetrics.Pings.shared.firstSession.submit()
}

// MARK: Glean Metrics

func recordEvent<ExtraObject>(for metric: EventMetricType<ExtraObject>,
Expand Down Expand Up @@ -88,6 +88,10 @@ struct DefaultGleanWrapper: GleanWrapper {
metric.set(value)
}

func recordUrl(for metric: UrlMetricType, value: String) {
metric.set(value)
}

// MARK: RateMetricType

func incrementNumerator(for metric: RateMetricType, amount: Int32) {
Expand All @@ -113,4 +117,10 @@ struct DefaultGleanWrapper: GleanWrapper {
timerId: GleanTimerId) {
metric.stopAndAccumulate(timerId)
}

// MARK: Pings

func submit<ReasonCodesEnum>(ping: Ping<ReasonCodesEnum>) where ReasonCodesEnum: ReasonCodes {
ping.submit()
}
}
86 changes: 71 additions & 15 deletions firefox-ios/Client/Telemetry/SponsoredTileTelemetry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,89 @@ import Glean

// Telemetry for the Sponsored tiles located in the Top sites on the Firefox home page
// Using Pings to send the telemetry events
struct SponsoredTileTelemetry {
protocol SponsoredTileTelemetry {
func sendImpressionTelemetry(tile: SponsoredTile,
position: Int,
isUnifiedAdsEnabled: Bool)
func sendClickTelemetry(tile: SponsoredTile,
position: Int,
isUnifiedAdsEnabled: Bool)
}

extension SponsoredTileTelemetry {
func sendImpressionTelemetry(tile: SponsoredTile,
position: Int,
isUnifiedAdsEnabled: Bool = false) {
sendImpressionTelemetry(tile: tile, position: position, isUnifiedAdsEnabled: isUnifiedAdsEnabled)
}

func sendClickTelemetry(tile: SponsoredTile,
position: Int,
isUnifiedAdsEnabled: Bool = false) {
sendClickTelemetry(tile: tile, position: position, isUnifiedAdsEnabled: isUnifiedAdsEnabled)
}
}

struct DefaultSponsoredTileTelemetry: SponsoredTileTelemetry {
// Source is only new tab at the moment, more source could be added later
static let source = "newtab"
private let gleanWrapper: GleanWrapper

init(gleanWrapper: GleanWrapper = DefaultGleanWrapper()) {
self.gleanWrapper = gleanWrapper
}

static func sendImpressionTelemetry(tile: SponsoredTile, position: Int) {
/// Send Sponsored tile impression telemetry with Glean Pings
/// - Parameters:
/// - tile: The sponsored tile
/// - position: The position of the sponsored tile in the top sites collection view
/// - isUnifiedAdsEnabled: Whether the unified ads is enabled, if enabled some information isn't set on the ping
func sendImpressionTelemetry(tile: SponsoredTile,
position: Int,
isUnifiedAdsEnabled: Bool = false) {
let extra = GleanMetrics.TopSites.ContileImpressionExtra(
position: Int32(position),
source: SponsoredTileTelemetry.source
source: DefaultSponsoredTileTelemetry.source
)
GleanMetrics.TopSites.contileImpression.record(extra)
gleanWrapper.recordEvent(for: GleanMetrics.TopSites.contileImpression, extras: extra)

GleanMetrics.TopSites.contileTileId.set(Int64(tile.tileId))
GleanMetrics.TopSites.contileAdvertiser.set(tile.title)
GleanMetrics.TopSites.contileReportingUrl.set(tile.impressionURL)
GleanMetrics.Pings.shared.topsitesImpression.submit()
// Some information isn't set on the ping when unified ads is enabled
if !isUnifiedAdsEnabled {
gleanWrapper.recordQuantity(for: GleanMetrics.TopSites.contileTileId,
value: Int64(tile.tileId))
gleanWrapper.recordUrl(for: GleanMetrics.TopSites.contileReportingUrl,
value: tile.impressionURL)
}

gleanWrapper.recordString(for: GleanMetrics.TopSites.contileAdvertiser,
value: tile.title)
gleanWrapper.submit(ping: GleanMetrics.Pings.shared.topsitesImpression)
}

static func sendClickTelemetry(tile: SponsoredTile, position: Int) {
/// Send Sponsored tile click telemetry with Glean Pings
/// - Parameters:
/// - tile: The sponsored tile
/// - position: The position of the sponsored tile in the top sites collection view
/// - isUnifiedAdsEnabled: Whether the unified ads is enabled, if enabled some information isn't set on the ping
func sendClickTelemetry(tile: SponsoredTile,
position: Int,
isUnifiedAdsEnabled: Bool = false) {
let extra = GleanMetrics.TopSites.ContileClickExtra(
position: Int32(position),
source: SponsoredTileTelemetry.source
source: DefaultSponsoredTileTelemetry.source
)
GleanMetrics.TopSites.contileClick.record(extra)
gleanWrapper.recordEvent(for: GleanMetrics.TopSites.contileClick, extras: extra)

// Some information isn't set on the ping when unified ads is enabled
if !isUnifiedAdsEnabled {
gleanWrapper.recordQuantity(for: GleanMetrics.TopSites.contileTileId,
value: Int64(tile.tileId))
gleanWrapper.recordUrl(for: GleanMetrics.TopSites.contileReportingUrl,
value: tile.clickURL)
}

GleanMetrics.TopSites.contileTileId.set(Int64(tile.tileId))
GleanMetrics.TopSites.contileAdvertiser.set(tile.title)
GleanMetrics.TopSites.contileReportingUrl.set(tile.clickURL)
GleanMetrics.Pings.shared.topsitesImpression.submit()
gleanWrapper.recordString(for: GleanMetrics.TopSites.contileAdvertiser,
value: tile.title)
gleanWrapper.submit(ping: GleanMetrics.Pings.shared.topsitesImpression)
}
}
Loading

0 comments on commit 999680a

Please sign in to comment.