From 1f17371df6d5f3e2c5c9ffd5dd7c52d7e2ab644a Mon Sep 17 00:00:00 2001 From: Sawyer Blatz Date: Wed, 16 Sep 2020 07:14:06 -0700 Subject: [PATCH] For #14565: Add telemetry for top sites --- app/metrics.yaml | 60 +++++++++++++++++++ .../mozilla/fenix/components/metrics/Event.kt | 14 +++++ .../components/metrics/GleanMetricsService.kt | 14 +++++ .../SessionControlController.kt | 11 ++-- .../SessionControlInteractor.kt | 8 +-- .../viewholders/TopSitePagerViewHolder.kt | 8 +++ .../topsites/TopSiteItemViewHolder.kt | 6 +- .../DefaultSessionControlControllerTest.kt | 5 +- .../topsites/TopSiteItemViewHolderTest.kt | 2 +- docs/metrics.md | 4 ++ 10 files changed, 119 insertions(+), 13 deletions(-) diff --git a/app/metrics.yaml b/app/metrics.yaml index ab3a3cddb..11bd45857 100644 --- a/app/metrics.yaml +++ b/app/metrics.yaml @@ -3195,6 +3195,66 @@ top_sites: notification_emails: - fenix-core@mozilla.com expires: "2020-11-15" + open_frecency: + type: event + description: | + A user opened a frecency top site + bugs: + - https://github.com/mozilla-mobile/fenix/issues/14565 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/15136 + data_sensitivity: + - interaction + notification_emails: + - fenix-core@mozilla.com + expires: "2021-03-15" + open_pinned: + type: event + description: | + A user opened a pinned top site + bugs: + - https://github.com/mozilla-mobile/fenix/issues/14565 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/15136 + data_sensitivity: + - interaction + notification_emails: + - fenix-core@mozilla.com + expires: "2021-03-15" + swipe_carousel: + type: event + description: | + A user swiped to change the page of the top sites carousel + extra_keys: + page: + description: | + The page number the carousel is now on + bugs: + - https://github.com/mozilla-mobile/fenix/issues/14565 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/15136 + data_sensitivity: + - interaction + notification_emails: + - fenix-core@mozilla.com + expires: "2021-03-15" + long_press: + type: event + description: | + A user long pressed on a top site + extra_keys: + type: + description: | + The type of top site. Options are: "FRECENCY," "DEFAULT," or "PINNED." + bugs: + - https://github.com/mozilla-mobile/fenix/issues/14565 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/15136 + data_sensitivity: + - interaction + notification_emails: + - fenix-core@mozilla.com + expires: "2021-03-15" open_in_new_tab: type: event description: | diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt index db78aa466..1a3be9a71 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt @@ -7,6 +7,7 @@ package org.mozilla.fenix.components.metrics import android.content.Context import mozilla.components.browser.errorpages.ErrorType import mozilla.components.browser.search.SearchEngine +import mozilla.components.feature.top.sites.TopSite import org.mozilla.fenix.GleanMetrics.Addons import org.mozilla.fenix.GleanMetrics.AppTheme import org.mozilla.fenix.GleanMetrics.Autoplay @@ -21,6 +22,7 @@ import org.mozilla.fenix.GleanMetrics.ProgressiveWebApp import org.mozilla.fenix.GleanMetrics.SearchShortcuts import org.mozilla.fenix.GleanMetrics.Tip import org.mozilla.fenix.GleanMetrics.ToolbarSettings +import org.mozilla.fenix.GleanMetrics.TopSites import org.mozilla.fenix.GleanMetrics.TrackingProtection import org.mozilla.fenix.R import java.util.Locale @@ -121,6 +123,8 @@ sealed class Event { object NotificationMediaPlay : Event() object NotificationMediaPause : Event() object TopSiteOpenDefault : Event() + object TopSiteOpenFrecent : Event() + object TopSiteOpenPinned : Event() object TopSiteOpenInNewTab : Event() object TopSiteOpenInPrivateTab : Event() object TopSiteRemoved : Event() @@ -191,6 +195,16 @@ sealed class Event { // Interaction events with extras + data class TopSiteSwipeCarousel(val page: Int) : Event() { + override val extras: Map? + get() = hashMapOf(TopSites.swipeCarouselKeys.page to page.toString()) + } + + data class TopSiteLongPress(val type: TopSite.Type) : Event() { + override val extras: Map? + get() = hashMapOf(TopSites.longPressKeys.type to type.name) + } + data class ProgressiveWebAppForeground(val timeForegrounded: Long) : Event() { override val extras: Map? get() = mapOf(ProgressiveWebApp.foregroundKeys.timeMs to timeForegrounded.toString()) diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt index 219a7fd19..ff71896e1 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt @@ -517,6 +517,12 @@ private val Event.wrapper: EventWrapper<*>? is Event.TopSiteOpenDefault -> EventWrapper( { TopSites.openDefault.record(it) } ) + is Event.TopSiteOpenFrecent -> EventWrapper( + { TopSites.openFrecency.record(it) } + ) + is Event.TopSiteOpenPinned -> EventWrapper( + { TopSites.openPinned.record(it) } + ) is Event.TopSiteOpenInNewTab -> EventWrapper( { TopSites.openInNewTab.record(it) } ) @@ -526,6 +532,14 @@ private val Event.wrapper: EventWrapper<*>? is Event.TopSiteRemoved -> EventWrapper( { TopSites.remove.record(it) } ) + is Event.TopSiteLongPress -> EventWrapper( + { TopSites.longPress.record(it) }, + { TopSites.longPressKeys.valueOf(it) } + ) + is Event.TopSiteSwipeCarousel -> EventWrapper( + { TopSites.swipeCarousel.record(it) }, + { TopSites.swipeCarouselKeys.valueOf(it) } + ) is Event.SupportTapped -> EventWrapper( { AboutPage.supportTapped.record(it) } ) diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt index db4ada0e0..3ad615f26 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt @@ -98,7 +98,7 @@ interface SessionControlController { /** * @see [TopSiteInteractor.onSelectTopSite] */ - fun handleSelectTopSite(url: String, isDefault: Boolean) + fun handleSelectTopSite(url: String, type: TopSite.Type) /** * @see [OnboardingInteractor.onStartBrowsingClicked] @@ -302,11 +302,14 @@ class DefaultSessionControlController( metrics.track(Event.CollectionRenamePressed) } - override fun handleSelectTopSite(url: String, isDefault: Boolean) { + override fun handleSelectTopSite(url: String, type: TopSite.Type) { metrics.track(Event.TopSiteOpenInNewTab) - if (isDefault) { - metrics.track(Event.TopSiteOpenDefault) + when (type) { + TopSite.Type.DEFAULT -> metrics.track(Event.TopSiteOpenDefault) + TopSite.Type.FRECENT -> metrics.track(Event.TopSiteOpenFrecent) + TopSite.Type.PINNED -> metrics.track(Event.TopSiteOpenPinned) } + if (url == SupportUtils.POCKET_TRENDING_URL) { metrics.track(Event.PocketTopSiteClicked) } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt index b33b97699..b600d0983 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt @@ -167,9 +167,9 @@ interface TopSiteInteractor { * Selects the given top site. Called when a user clicks on a top site. * * @param url The URL of the top site. - * @param isDefault Whether or not the top site is a default one. + * @param type The type of the top site. */ - fun onSelectTopSite(url: String, isDefault: Boolean) + fun onSelectTopSite(url: String, type: TopSite.Type) } /** @@ -218,8 +218,8 @@ class SessionControlInteractor( controller.handleRenameCollectionTapped(collection) } - override fun onSelectTopSite(url: String, isDefault: Boolean) { - controller.handleSelectTopSite(url, isDefault) + override fun onSelectTopSite(url: String, type: TopSite.Type) { + controller.handleSelectTopSite(url, type) } override fun onStartBrowsingClicked() { diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TopSitePagerViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TopSitePagerViewHolder.kt index ab0142fa1..06affb026 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TopSitePagerViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TopSitePagerViewHolder.kt @@ -11,6 +11,8 @@ import androidx.viewpager2.widget.ViewPager2 import kotlinx.android.synthetic.main.component_top_sites_pager.view.* import mozilla.components.feature.top.sites.TopSite import org.mozilla.fenix.R +import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.ext.components import org.mozilla.fenix.home.sessioncontrol.TopSiteInteractor import org.mozilla.fenix.home.sessioncontrol.viewholders.topsites.TopSitesPagerAdapter @@ -21,10 +23,16 @@ class TopSitePagerViewHolder( private val topSitesPagerAdapter = TopSitesPagerAdapter(interactor) private val pageIndicator = view.page_indicator + private var currentPage = 0 private val topSitesPageChangeCallback = object : ViewPager2.OnPageChangeCallback() { override fun onPageSelected(position: Int) { + if (currentPage != position) { + pageIndicator.context.components.analytics.metrics.track(Event.TopSiteSwipeCarousel(position)) + } + pageIndicator.setSelection(position) + currentPage = position } } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolder.kt index ff7df347f..0b6fe85f7 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolder.kt @@ -14,10 +14,10 @@ import kotlinx.android.synthetic.main.top_site_item.* import mozilla.components.browser.menu.BrowserMenuBuilder import mozilla.components.browser.menu.item.SimpleBrowserMenuItem import mozilla.components.feature.top.sites.TopSite -import mozilla.components.feature.top.sites.TopSite.Type.DEFAULT import mozilla.components.feature.top.sites.TopSite.Type.FRECENT import mozilla.components.feature.top.sites.TopSite.Type.PINNED import org.mozilla.fenix.R +import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.loadIntoView import org.mozilla.fenix.home.sessioncontrol.TopSiteInteractor @@ -32,10 +32,12 @@ class TopSiteItemViewHolder( init { top_site_item.setOnClickListener { - interactor.onSelectTopSite(topSite.url, topSite.type === DEFAULT) + interactor.onSelectTopSite(topSite.url, topSite.type) } top_site_item.setOnLongClickListener { + it.context.components.analytics.metrics.track(Event.TopSiteLongPress(topSite.type)) + val topSiteMenu = TopSiteItemMenu(view.context, topSite.type != FRECENT) { item -> when (item) { is TopSiteItemMenu.Item.OpenInPrivateTab -> interactor.onOpenInPrivateTabClicked( diff --git a/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt b/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt index d114f5002..6ad511775 100644 --- a/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt @@ -18,6 +18,7 @@ import mozilla.components.browser.session.SessionManager import mozilla.components.concept.engine.Engine import mozilla.components.feature.tab.collections.TabCollection import mozilla.components.feature.tabs.TabsUseCases +import mozilla.components.feature.top.sites.TopSite import mozilla.components.support.test.rule.MainCoroutineRule import org.junit.Before import org.junit.Rule @@ -279,7 +280,7 @@ class DefaultSessionControlControllerTest { fun handleSelectDefaultTopSite() { val topSiteUrl = "mozilla.org" - controller.handleSelectTopSite(topSiteUrl, true) + controller.handleSelectTopSite(topSiteUrl, TopSite.Type.DEFAULT) verify { metrics.track(Event.TopSiteOpenInNewTab) } verify { metrics.track(Event.TopSiteOpenDefault) } verify { @@ -296,7 +297,7 @@ class DefaultSessionControlControllerTest { fun handleSelectNonDefaultTopSite() { val topSiteUrl = "mozilla.org" - controller.handleSelectTopSite(topSiteUrl, false) + controller.handleSelectTopSite(topSiteUrl, TopSite.Type.FRECENT) verify { metrics.track(Event.TopSiteOpenInNewTab) } verify { tabsUseCases.addTab.invoke( diff --git a/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolderTest.kt index 321bad7a9..54d1b91f0 100644 --- a/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolderTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolderTest.kt @@ -42,6 +42,6 @@ class TopSiteItemViewHolderTest { TopSiteItemViewHolder(view, interactor).bind(pocket) view.top_site_item.performClick() - verify { interactor.onSelectTopSite("https://getpocket.com", isDefault = true) } + verify { interactor.onSelectTopSite("https://getpocket.com", TopSite.Type.DEFAULT) } } } diff --git a/docs/metrics.md b/docs/metrics.md index db27d96ac..197643258 100644 --- a/docs/metrics.md +++ b/docs/metrics.md @@ -213,10 +213,14 @@ The following metrics are added to the ping: | tip.displayed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The tip was displayed |[1](https://github.com/mozilla-mobile/fenix/pull/9836)|
  • identifier: The identifier of the tip displayed
|2020-11-15 |2 | | tip.pressed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The tip's button was pressed |[1](https://github.com/mozilla-mobile/fenix/pull/9836)|
  • identifier: The identifier of the tip the action was taken on
|2020-11-15 |2 | | toolbar_settings.changed_position |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user selected a new position for the toolbar |[1](https://github.com/mozilla-mobile/fenix/pull/6608)|
  • position: A string that indicates the new position of the toolbar TOP or BOTTOM
|2020-11-15 |2 | +| top_sites.long_press |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user long pressed on a top site |[1](https://github.com/mozilla-mobile/fenix/pull/15136)|
  • type: The type of top site. Options are: "FRECENCY," "DEFAULT," or "PINNED."
|2021-03-15 |2 | | top_sites.open_default |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a default top site |[1](https://github.com/mozilla-mobile/fenix/pull/10752)||2020-11-15 |2 | +| top_sites.open_frecency |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a frecency top site |[1](https://github.com/mozilla-mobile/fenix/pull/15136)||2021-03-15 |2 | | top_sites.open_in_new_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opens a new tab based on a top site item |[1](https://github.com/mozilla-mobile/fenix/pull/7523)||2020-11-15 |2 | | top_sites.open_in_private_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opens a new private tab based on a top site item |[1](https://github.com/mozilla-mobile/fenix/pull/7523)||2020-11-15 |2 | +| top_sites.open_pinned |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a pinned top site |[1](https://github.com/mozilla-mobile/fenix/pull/15136)||2021-03-15 |2 | | top_sites.remove |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user removes a top site item |[1](https://github.com/mozilla-mobile/fenix/pull/7523)||2020-11-15 |2 | +| top_sites.swipe_carousel |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user swiped to change the page of the top sites carousel |[1](https://github.com/mozilla-mobile/fenix/pull/15136)|
  • page: The page number the carousel is now on
|2021-03-15 |2 | | tracking_protection.etp_setting_changed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user changed their tracking protection level setting to either strict, standard, or custom. |[1](https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188), [2](https://github.com/mozilla-mobile/fenix/pull/11383)|
  • etp_setting: The new setting for ETP: strict, standard, custom
|2020-11-15 |2 | | tracking_protection.etp_settings |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened tracking protection settings through settings. |[1](https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188)||2020-11-15 |2 | | tracking_protection.etp_shield |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the tracking protection shield icon in toolbar. |[1](https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188)||2020-11-15 |2 |