Skip to content
This repository was archived by the owner on Feb 20, 2023. It is now read-only.

(Uplift to 86) For #17418 - Added telemetry for Google Default Top Site (#17637) #18021

Merged
merged 1 commit into from
Feb 16, 2021
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
2 changes: 1 addition & 1 deletion app/metrics.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -910,7 +910,7 @@ metrics:
https://github.com/mozilla-mobile/fenix/issues/1607) the value will be
`custom`.

`source` will be: `action`, `suggestion`, `widget` or `shortcut`
`source` will be: `action`, `suggestion`, `widget`, `shortcut`, `topsite`
(depending on the source from which the search started). Also added the
`other` option for the source but it should never enter on this case.
send_in_pings:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ sealed class Event {
data class Action(override val engineSource: EngineSource) : EventSource(engineSource)
data class Widget(override val engineSource: EngineSource) : EventSource(engineSource)
data class Shortcut(override val engineSource: EngineSource) : EventSource(engineSource)
data class TopSite(override val engineSource: EngineSource) : EventSource(engineSource)
data class Other(override val engineSource: EngineSource) : EventSource(engineSource)

private val label: String
Expand All @@ -455,6 +456,7 @@ sealed class Event {
is Action -> "action"
is Widget -> "widget"
is Shortcut -> "shortcut"
is TopSite -> "topsite"
is Other -> "other"
}

Expand All @@ -466,7 +468,7 @@ sealed class Event {
}

enum class SearchAccessPoint {
SUGGESTION, ACTION, WIDGET, SHORTCUT, NONE
SUGGESTION, ACTION, WIDGET, SHORTCUT, TOPSITE, NONE
}

override val extras: Map<Events.performedSearchKeys, String>?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.support.base.log.logger.Logger
import org.mozilla.fenix.components.metrics.Event.PerformedSearch.SearchAccessPoint
import org.mozilla.fenix.ext.components
import java.io.IOException
import java.security.NoSuchAlgorithmException
import java.security.spec.InvalidKeySpecException
Expand Down Expand Up @@ -58,6 +57,11 @@ object MetricsUtils {
engineSource
)
)
SearchAccessPoint.TOPSITE -> Event.PerformedSearch(
Event.PerformedSearch.EventSource.TopSite(
engineSource
)
)
SearchAccessPoint.NONE -> Event.PerformedSearch(
Event.PerformedSearch.EventSource.Other(
engineSource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ package org.mozilla.fenix.home.sessioncontrol

import android.view.LayoutInflater
import android.widget.EditText
import androidx.annotation.VisibleForTesting
import androidx.appcompat.app.AlertDialog
import androidx.navigation.NavController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import mozilla.components.browser.state.selector.getNormalOrPrivateTabs
import mozilla.components.browser.state.state.searchEngines
import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.Engine
Expand Down Expand Up @@ -378,6 +380,20 @@ class DefaultSessionControlController(
metrics.track(Event.PocketTopSiteClicked)
}

if (SupportUtils.GOOGLE_URL.equals(url, true)) {
val availableEngines = getAvailableSearchEngines()

val searchAccessPoint = Event.PerformedSearch.SearchAccessPoint.TOPSITE
val event =
availableEngines.firstOrNull { engine -> engine.suggestUrl?.contains(url) == true }
?.let { searchEngine ->
searchAccessPoint.let { sap ->
MetricsUtils.createSearchEvent(searchEngine, store, sap)
}
}
event?.let { activity.metrics.track(it) }
}

addTabUseCase.invoke(
url = appendSearchAttributionToUrlIfNeeded(url),
selectTab = true,
Expand All @@ -386,6 +402,15 @@ class DefaultSessionControlController(
activity.openToBrowser(BrowserDirection.FromHome)
}

@VisibleForTesting
internal fun getAvailableSearchEngines() = activity
.components
.core
.store
.state
.search
.searchEngines

/**
* Append a search attribution query to any provided search engine URL based on the
* user's current region.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ class InContentTelemetry(private val metrics: MetricController) : BaseSearchTele

// For Bing if it didn't have a valid cookie and for all the other search engines
if (resultNotComputedFromCookies(trackKey) && hasValidCode(code, provider)) {
val channel = uri.getQueryParameter(CHANNEL_KEY)
val type = getSapType(provider.followOnParams, paramSet)
trackKey = TrackKeyInfo(provider.name, type, code)
trackKey = TrackKeyInfo(provider.name, type, code, channel)
}
}

Expand Down Expand Up @@ -145,5 +146,7 @@ class InContentTelemetry(private val metrics: MetricController) : BaseSearchTele
private const val SEARCH_TYPE_ORGANIC = "organic"
private const val SEARCH_TYPE_SAP = "sap"
private const val SEARCH_TYPE_SAP_FOLLOW_ON = "sap-follow-on"

private const val CHANNEL_KEY = "channel"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ import java.util.Locale
internal data class TrackKeyInfo(
var providerName: String,
var type: String,
var code: String?
var code: String?,
var channel: String? = null
) {
fun createTrackKey(): String {
return "${providerName.toLowerCase(Locale.ROOT)}.in-content" +
".${type.toLowerCase(Locale.ROOT)}" +
".${code?.toLowerCase(Locale.ROOT) ?: "none"}"
".${code?.toLowerCase(Locale.ROOT) ?: "none"}" +
if (!channel?.toLowerCase(Locale.ROOT).isNullOrBlank())
".${channel?.toLowerCase(Locale.ROOT)}"
else ""
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import androidx.navigation.NavController
import androidx.navigation.NavDirections
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.spyk
import io.mockk.unmockkStatic
import io.mockk.verify
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineDispatcher
Expand All @@ -21,6 +24,7 @@ import mozilla.components.browser.state.state.ReaderState
import mozilla.components.browser.state.state.SearchState
import mozilla.components.browser.state.state.createTab
import mozilla.components.browser.state.state.recover.RecoverableTab
import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.Engine
import mozilla.components.feature.session.SessionUseCases
Expand All @@ -39,6 +43,7 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.components.Analytics
import org.mozilla.fenix.components.TabCollectionStorage
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.Event.PerformedSearch.EngineSource
import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.components.tips.Tip
import org.mozilla.fenix.ext.components
Expand Down Expand Up @@ -86,6 +91,16 @@ class DefaultSessionControlControllerTest {
type = SearchEngine.Type.BUNDLED,
resultUrls = listOf("https://example.org/?q={searchTerms}")
)

private val googleSearchEngine = SearchEngine(
id = "googleTest",
name = "Google Test Engine",
icon = mockk(relaxed = true),
type = SearchEngine.Type.BUNDLED,
resultUrls = listOf("https://www.google.com/?q={searchTerms}"),
suggestUrl = "https://www.google.com/"
)

private lateinit var store: BrowserStore
private lateinit var controller: DefaultSessionControlController

Expand Down Expand Up @@ -117,7 +132,7 @@ class DefaultSessionControlControllerTest {

val restoreUseCase: TabsUseCases.RestoreUseCase = mockk(relaxed = true)

controller = DefaultSessionControlController(
controller = spyk(DefaultSessionControlController(
activity = activity,
store = store,
settings = settings,
Expand All @@ -136,7 +151,7 @@ class DefaultSessionControlControllerTest {
showDeleteCollectionPrompt = showDeleteCollectionPrompt,
showTabTray = showTabTray,
handleSwipedItemDeletionCancel = handleSwipedItemDeletionCancel
)
))
}

@After
Expand Down Expand Up @@ -392,6 +407,7 @@ class DefaultSessionControlControllerTest {
@Test
fun handleSelectGoogleDefaultTopSiteUS() {
val topSiteUrl = SupportUtils.GOOGLE_URL
every { controller.getAvailableSearchEngines() } returns listOf(searchEngine)

store.dispatch(SearchAction.SetRegionAction(RegionState("US", "US"))).joinBlocking()

Expand All @@ -412,6 +428,7 @@ class DefaultSessionControlControllerTest {
@Test
fun handleSelectGoogleDefaultTopSiteXX() {
val topSiteUrl = SupportUtils.GOOGLE_URL
every { controller.getAvailableSearchEngines() } returns listOf(searchEngine)

store.dispatch(SearchAction.SetRegionAction(RegionState("DE", "FR"))).joinBlocking()

Expand All @@ -429,9 +446,36 @@ class DefaultSessionControlControllerTest {
verify { activity.openToBrowser(BrowserDirection.FromHome) }
}

@Test
fun handleSelectGoogleDefaultTopSite_EventPerformedSearchTopSite() {
val topSiteUrl = SupportUtils.GOOGLE_URL
val engineSource = EngineSource.Default(googleSearchEngine, false)
every { controller.getAvailableSearchEngines() } returns listOf(googleSearchEngine)
try {
mockkStatic("mozilla.components.browser.state.state.SearchStateKt")

every { any<SearchState>().selectedOrDefaultSearchEngine } returns googleSearchEngine

controller.handleSelectTopSite(topSiteUrl, TopSite.Type.DEFAULT)

verify {
metrics.track(
Event.PerformedSearch(
Event.PerformedSearch.EventSource.TopSite(
engineSource
)
)
)
}
} finally {
unmockkStatic(SearchState::class)
}
}

@Test
fun handleSelectGooglePinnedTopSiteUS() {
val topSiteUrl = SupportUtils.GOOGLE_URL
every { controller.getAvailableSearchEngines() } returns listOf(searchEngine)

store.dispatch(SearchAction.SetRegionAction(RegionState("US", "US"))).joinBlocking()

Expand All @@ -452,6 +496,7 @@ class DefaultSessionControlControllerTest {
@Test
fun handleSelectGooglePinnedTopSiteXX() {
val topSiteUrl = SupportUtils.GOOGLE_URL
every { controller.getAvailableSearchEngines() } returns listOf(searchEngine)

store.dispatch(SearchAction.SetRegionAction(RegionState("DE", "FR"))).joinBlocking()

Expand All @@ -472,6 +517,7 @@ class DefaultSessionControlControllerTest {
@Test
fun handleSelectGoogleFrecentTopSiteUS() {
val topSiteUrl = SupportUtils.GOOGLE_URL
every { controller.getAvailableSearchEngines() } returns listOf(searchEngine)

store.dispatch(SearchAction.SetRegionAction(RegionState("US", "US"))).joinBlocking()

Expand All @@ -492,6 +538,7 @@ class DefaultSessionControlControllerTest {
@Test
fun handleSelectGoogleFrecentTopSiteXX() {
val topSiteUrl = SupportUtils.GOOGLE_URL
every { controller.getAvailableSearchEngines() } returns listOf(searchEngine)

store.dispatch(SearchAction.SetRegionAction(RegionState("DE", "FR"))).joinBlocking()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,15 @@ class InContentTelemetryTest {
verify { metrics.track(Event.SearchInContent("google.in-content.sap-follow-on.firefox-b-m")) }
}

@Test
fun `track google sap-follow-on and topSite metric`() {
val url = "https://www.google.com/search?q=aaa&client=firefox-b-m&channel=ts&oq=random"

telemetry.trackPartnerUrlTypeMetric(url, listOf())

verify { metrics.track(Event.SearchInContent("google.in-content.sap-follow-on.firefox-b-m.ts")) }
}

@Test
fun `track baidu sap-follow-on metric`() {
val url = "https://www.baidu.com/from=844b/s?wd=aaa&tn=34046034_firefox&oq=random"
Expand Down
2 changes: 1 addition & 1 deletion docs/metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ The following metrics are added to the ping:
| metrics.mobile_bookmarks_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter that indicates how many bookmarks a user has in the mobile folder. This value will only be set if the user has at least *one* bookmark. If they have 0, this ping will not get sent, resulting in a null value. To disambiguate between a failed `mobile_bookmarks_count` ping and 0 bookmarks, please see `has_mobile_bookmarks`. |[1](https://github.com/mozilla-mobile/fenix/pull/16942), [2](https://github.com/mozilla-mobile/fenix/pull/16942#issuecomment-742794701)||2021-08-01 |2 |
| metrics.mozilla_products |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |A list of all the Mozilla products installed on device. We currently scan for: Firefox, Firefox Beta, Firefox Aurora, Firefox Nightly, Firefox Fdroid, Firefox Lite, Reference Browser, Reference Browser Debug, Fenix, Focus, and Lockwise. |[1](https://github.com/mozilla-mobile/fenix/pull/1953/), [2](https://github.com/mozilla-mobile/fenix/pull/5216), [3](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |1, 2 |
| metrics.recently_used_pwa_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter that indicates how many PWAs a user has recently used. Threshold for "recency" set in HomeActivity#PWA_RECENTLY_USED_THRESHOLD. Currently we are not told by the OS when a PWA is removed by the user, so we use the "recently used" heuristic to judge how many PWAs are still active, as a proxy for "installed". This value will only be set if the user has at least *one* recently used PWA. If they have 0, this metric will not be sent, resulting in a null value during analysis on the server-side. To disambiguate between a failed `recently_used_pwa_count` metric and 0 recent PWAs, please see `has_recent_pwas`. |[1](https://github.com/mozilla-mobile/fenix/pull/11982#pullrequestreview-437963817), [2](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| metrics.search_count |[labeled_counter](https://mozilla.github.io/glean/book/user/metrics/labeled_counters.html) |The labels for this counter are `<search-engine-name>.<source>`. If the search engine is bundled with Fenix `search-engine-name` will be the name of the search engine. If it's a custom search engine (defined: https://github.com/mozilla-mobile/fenix/issues/1607) the value will be `custom`. `source` will be: `action`, `suggestion`, `widget` or `shortcut` (depending on the source from which the search started). Also added the `other` option for the source but it should never enter on this case. |[1](https://github.com/mozilla-mobile/fenix/pull/1677), [2](https://github.com/mozilla-mobile/fenix/pull/5216), [3](https://github.com/mozilla-mobile/fenix/pull/7310), [4](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |1, 2 |
| metrics.search_count |[labeled_counter](https://mozilla.github.io/glean/book/user/metrics/labeled_counters.html) |The labels for this counter are `<search-engine-name>.<source>`. If the search engine is bundled with Fenix `search-engine-name` will be the name of the search engine. If it's a custom search engine (defined: https://github.com/mozilla-mobile/fenix/issues/1607) the value will be `custom`. `source` will be: `action`, `suggestion`, `widget`, `shortcut`, `topsite` (depending on the source from which the search started). Also added the `other` option for the source but it should never enter on this case. |[1](https://github.com/mozilla-mobile/fenix/pull/1677), [2](https://github.com/mozilla-mobile/fenix/pull/5216), [3](https://github.com/mozilla-mobile/fenix/pull/7310), [4](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |1, 2 |
| metrics.search_widget_installed |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the search widget is installed |[1](https://github.com/mozilla-mobile/fenix/pull/10958), [2](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| metrics.tab_view_setting |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string that indicates the setting for tab view: GRID, LIST |[1](https://github.com/mozilla-mobile/fenix/pull/15811#issuecomment-706402952)||2021-08-01 |2 |
| metrics.tabs_open_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter that indicates how many NORMAL tabs a user has open. This value will only be set if the user has at least *one* open tab. If they have 0, this ping will not get sent, resulting in a null value. To disambiguate between a failed `tabs_open_count` ping and 0 open tabs, please see `has_open_tabs`. |[1](https://github.com/mozilla-mobile/fenix/pull/12024), [2](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
Expand Down