Skip to content
Closed
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
54 changes: 52 additions & 2 deletions mobile/android/fenix/app/metrics.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9221,6 +9221,12 @@ top_sites:
type: event
description: |
A user opened a default top site
extra_keys:
source: &top_sites_source
type: string
description: |
The surface where the top site interaction occurred.
One of "homepage" or "shortcuts_library".
bugs:
- https://github.com/mozilla-mobile/fenix/issues/8125
data_reviews:
Expand All @@ -9241,6 +9247,8 @@ top_sites:
type: event
description: |
A user opened the google top site
extra_keys:
source: *top_sites_source
bugs:
- https://github.com/mozilla-mobile/fenix/issues/17418
data_reviews:
Expand Down Expand Up @@ -9281,6 +9289,8 @@ top_sites:
type: event
description: |
A user opened a frecency top site
extra_keys:
source: *top_sites_source
bugs:
- https://github.com/mozilla-mobile/fenix/issues/14565
data_reviews:
Expand All @@ -9301,6 +9311,8 @@ top_sites:
type: event
description: |
A user opened a pinned top site
extra_keys:
source: *top_sites_source
bugs:
- https://github.com/mozilla-mobile/fenix/issues/14565
data_reviews:
Expand Down Expand Up @@ -9352,6 +9364,7 @@ top_sites:
description: |
The type of top site. Options are: "FRECENCY", "DEFAULT",
"PINNED", or "PROVIDED"
source: *top_sites_source
bugs:
- https://github.com/mozilla-mobile/fenix/issues/14565
- https://github.com/mozilla-mobile/fenix/issues/23526
Expand All @@ -9374,6 +9387,8 @@ top_sites:
type: event
description: |
A user opens a new tab based on a top site item
extra_keys:
source: *top_sites_source
bugs:
- https://github.com/mozilla-mobile/fenix/issues/6757
data_reviews:
Expand All @@ -9394,6 +9409,8 @@ top_sites:
type: event
description: |
A user opens a new private tab based on a top site item
extra_keys:
source: *top_sites_source
bugs:
- https://github.com/mozilla-mobile/fenix/issues/6757
data_reviews:
Expand All @@ -9414,6 +9431,8 @@ top_sites:
type: event
description: |
A user removes a top site item
extra_keys:
source: *top_sites_source
bugs:
- https://github.com/mozilla-mobile/fenix/issues/6757
data_reviews:
Expand All @@ -9434,6 +9453,8 @@ top_sites:
type: event
description: |
A user removed the default Google top site
extra_keys:
source: *top_sites_source
bugs:
- https://github.com/mozilla-mobile/fenix/issues/21841
data_reviews:
Expand Down Expand Up @@ -9466,6 +9487,8 @@ top_sites:
type: event
description: |
A user has opened a contile top site.
extra_keys:
source: *top_sites_source
bugs:
- https://github.com/mozilla-mobile/fenix/issues/23526
data_reviews:
Expand All @@ -9482,6 +9505,8 @@ top_sites:
description: |
A user has opened a contile top site in a private tab via the long
press context menu.
extra_keys:
source: *top_sites_source
bugs:
- https://github.com/mozilla-mobile/fenix/issues/23526
data_reviews:
Expand All @@ -9498,6 +9523,8 @@ top_sites:
description: |
A user has selected "Settings" via the contile top sites
longpress context menu.
extra_keys:
source: *top_sites_source
bugs:
- https://github.com/mozilla-mobile/fenix/issues/23526
data_reviews:
Expand All @@ -9514,6 +9541,8 @@ top_sites:
description: |
A user has selected "Our sponsors & your privacy" via the
contile top sites longpress context menu.
extra_keys:
source: *top_sites_source
bugs:
- https://github.com/mozilla-mobile/fenix/issues/23526
data_reviews:
Expand Down Expand Up @@ -9618,7 +9647,9 @@ top_sites:
A user saw a Contile top site
extra_keys:
source:
description: The source of the event, example "newtab", "urlbar"
description: |
The surface where the Contile top site was shown.
One of "homepage" or "shortcuts_library".
type: string
position:
description: The tile placement (1-based)
Expand All @@ -9645,7 +9676,9 @@ top_sites:
A user clicked a Contile top site
extra_keys:
source:
description: The source of the event, example "newtab", "urlbar"
description: |
The surface where the Contile top site was clicked.
One of "homepage" or "shortcuts_library".
type: string
position:
description: The tile placement (1-based)
Expand Down Expand Up @@ -9736,6 +9769,12 @@ pocket:
type: event
description: |
The Pocket recommended stories are shown on the home screen.
extra_keys:
source:
type: string
description: |
Where the stories impression was recorded.
One of "homepage" or "stories_screen".
bugs:
- https://github.com/mozilla-mobile/fenix/issues/21593
data_reviews:
Expand Down Expand Up @@ -9764,6 +9803,11 @@ pocket:
description: |
Position of the clicked story in the list shown.
Uses the [row x column] matrix notation.
source:
type: string
description: |
Where the clicked story was shown.
One of "homepage" or "stories_screen".
bugs:
- https://github.com/mozilla-mobile/fenix/issues/21593
data_reviews:
Expand Down Expand Up @@ -15357,6 +15401,11 @@ home.content.article:
topic: &topic
description: The topic of the recommendation. Like "entertainment".
type: string
source: &source_pocket
description: >
The surface where the article was shown.
One of "homepage" or "stories_screen".
type: string
send_in_pings:
- home

Expand All @@ -15382,6 +15431,7 @@ home.content.article:
received_rank: *received_rank
recommended_at: *recommended_at
topic: *topic
source: *source_pocket
send_in_pings:
- home

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import org.mozilla.fenix.home.bookmarks.Bookmark
import org.mozilla.fenix.home.pocket.PocketImpression
import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesCategory
import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesSelectedCategory
import org.mozilla.fenix.home.pocket.controller.StoriesImpressionSource
import org.mozilla.fenix.home.recentsyncedtabs.RecentSyncedTab
import org.mozilla.fenix.home.recentsyncedtabs.RecentSyncedTabState
import org.mozilla.fenix.home.recenttabs.RecentTab
Expand Down Expand Up @@ -598,10 +599,12 @@ sealed class AppAction : Action {
*
* @property recommendation The [ContentRecommendation] that was clicked.
* @property position The position (0-index) of the [ContentRecommendation].
* @property source The surface where the clicked recommendation was shown.
*/
data class ContentRecommendationClicked(
val recommendation: ContentRecommendation,
val position: Int,
val source: StoriesImpressionSource,
) : ContentRecommendationsAction()

/**
Expand All @@ -621,9 +624,12 @@ sealed class AppAction : Action {
*
* @property impressions A list of [PocketImpression]s detailing the story shown and
* their respective position.
* @property source The surface where the stories were shown.
*/
data class PocketStoriesShown(val impressions: List<PocketImpression>) :
ContentRecommendationsAction()
data class PocketStoriesShown(
val impressions: List<PocketImpression>,
val source: StoriesImpressionSource,
) : ContentRecommendationsAction()

/**
* Cleans all in-memory data about Pocket stories and categories.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ import org.mozilla.fenix.home.toolbar.HomeToolbarComposable.Companion.DirectToSe
import org.mozilla.fenix.home.topsites.DefaultTopSitesView
import org.mozilla.fenix.home.topsites.TopSitesBinding
import org.mozilla.fenix.home.topsites.controller.DefaultTopSiteController
import org.mozilla.fenix.home.topsites.controller.TopSitesSource
import org.mozilla.fenix.home.topsites.getTopSitesConfig
import org.mozilla.fenix.home.ui.Homepage
import org.mozilla.fenix.home.ui.WallpaperBackground
Expand Down Expand Up @@ -1339,6 +1340,7 @@ class HomeFragment : Fragment() {
marsUseCases = requireComponents.useCases.marsUseCases,
mozAdsUseCases = requireComponents.useCases.mozAdsUseCases,
viewLifecycleScope = viewLifecycleOwner.lifecycleScope,
source = TopSitesSource.HOMEPAGE,
)

private fun initController() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import org.mozilla.fenix.home.collections.CollectionsState
import org.mozilla.fenix.home.interactor.HomepageInteractor
import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesCategory
import org.mozilla.fenix.home.pocket.PocketState
import org.mozilla.fenix.home.pocket.controller.StoriesImpressionSource
import org.mozilla.fenix.home.pocket.interactor.PocketStoriesInteractor
import org.mozilla.fenix.home.privatebrowsing.interactor.PrivateBrowsingInteractor
import org.mozilla.fenix.home.recentsyncedtabs.RecentSyncedTab
Expand Down Expand Up @@ -140,13 +141,17 @@ internal object FakeHomepagePreview {
storyPosition: Triple<Int, Int, Int>,
) { /* no op */ }

override fun onStoriesShown(storiesShown: List<PocketStory>) { /* no op */ }
override fun onStoriesShown(
storiesShown: List<PocketStory>,
source: StoriesImpressionSource,
) { /* no op */ }

override fun onCategoryClicked(categoryClicked: PocketRecommendedStoriesCategory) { /* no op */ }

override fun onStoryClicked(
storyClicked: PocketStory,
storyPosition: Triple<Int, Int, Int>,
source: StoriesImpressionSource,
) { /* no op */ }

override fun onDiscoverMoreClicked() { /* no op */ }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class HomeTelemetryMiddleware : Middleware<AppState, AppAction> {
scheduledCorpusItemId = recommendation.scheduledCorpusItemId,
tileId = recommendation.tileId.toInt(),
topic = recommendation.topic,
source = action.source.sourceName,
),
)

Expand All @@ -60,6 +61,7 @@ class HomeTelemetryMiddleware : Middleware<AppState, AppAction> {
scheduledCorpusItemId = story.scheduledCorpusItemId,
tileId = story.tileId.toInt(),
topic = story.topic,
source = action.source.sourceName,
),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ import java.lang.ref.WeakReference

private const val POCKET_CATEGORIES_SELECTED_AT_A_TIME_COUNT = 8

/**
* The surface where a Pocket stories impression was recorded. Used as the `source` extra on the
* `pocket.home_recs_shown` Glean event.
*/
enum class StoriesImpressionSource(val sourceName: String) {
HOMEPAGE("homepage"),
STORIES_SCREEN("stories_screen"),
}

/**
* Contract for how all user interactions with the Pocket stories feature are to be handled.
*/
Expand All @@ -49,8 +58,9 @@ interface PocketStoriesController {
* Callback to decide what should happen as an effect of a new list of stories being shown.
*
* @param storiesShown the new list of [PocketStory]es shown to the user.
* @param source the surface where the stories were shown.
*/
fun handleStoriesShown(storiesShown: List<PocketStory>)
fun handleStoriesShown(storiesShown: List<PocketStory>, source: StoriesImpressionSource)

/**
* Callback allowing to handle a specific [PocketRecommendedStoriesCategory] being clicked by the user.
Expand All @@ -65,8 +75,13 @@ interface PocketStoriesController {
* @param storyClicked The just clicked [PocketStory].
* @param storyPosition `row x column x index` matrix representing the grid and index position
* of the clicked story.
* @param source the surface where the clicked story was shown.
*/
fun handleStoryClicked(storyClicked: PocketStory, storyPosition: Triple<Int, Int, Int>)
fun handleStoryClicked(
storyClicked: PocketStory,
storyPosition: Triple<Int, Int, Int>,
source: StoriesImpressionSource,
)

/**
* Callback for when the user clicks on the "Discover more" button.
Expand Down Expand Up @@ -114,6 +129,7 @@ internal class DefaultPocketStoriesController(
position = storyPosition.third,
),
),
source = StoriesImpressionSource.HOMEPAGE,
),
)

Expand All @@ -138,18 +154,24 @@ internal class DefaultPocketStoriesController(
}
}

override fun handleStoriesShown(storiesShown: List<PocketStory>) {
override fun handleStoriesShown(
storiesShown: List<PocketStory>,
source: StoriesImpressionSource,
) {
// Only report here the impressions for recommended stories.
// Sponsored stories use a different API for more accurate tracking.
appStore.dispatch(
ContentRecommendationsAction.PocketStoriesShown(
impressions = storiesShown
.filter { it is ContentRecommendation || it is PocketRecommendedStory }
.map { PocketImpression(story = it, position = storiesShown.indexOf(it)) },
source = source,
),
)

Pocket.homeRecsShown.record(NoExtras())
Pocket.homeRecsShown.record(
Pocket.HomeRecsShownExtra(source = source.sourceName),
)
}

override fun handleCategoryClick(categoryClicked: PocketRecommendedStoriesCategory) {
Expand Down Expand Up @@ -196,6 +218,7 @@ internal class DefaultPocketStoriesController(
override fun handleStoryClicked(
storyClicked: PocketStory,
storyPosition: Triple<Int, Int, Int>,
source: StoriesImpressionSource,
) {
val storyUrl = when (navController.currentDestination?.id) {
R.id.storiesFragment -> storyClicked.url.markAsOpenedFromStoriesScreen()
Expand All @@ -216,6 +239,7 @@ internal class DefaultPocketStoriesController(
Pocket.HomeRecsStoryClickedExtra(
position = "${storyPosition.first}x${storyPosition.second}",
timesShown = storyClicked.timesShown.inc().toString(),
source = source.sourceName,
),
)
}
Expand All @@ -225,6 +249,7 @@ internal class DefaultPocketStoriesController(
ContentRecommendationsAction.ContentRecommendationClicked(
recommendation = storyClicked,
position = storyPosition.third,
source = source,
),
)
}
Expand Down
Loading
Loading