Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 6 additions & 0 deletions mobile/android/fenix/app/metrics.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9736,6 +9736,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
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,7 +141,10 @@ 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 */ }

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 Down Expand Up @@ -138,7 +148,10 @@ 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(
Expand All @@ -149,7 +162,9 @@ internal class DefaultPocketStoriesController(
),
)

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

override fun handleCategoryClick(categoryClicked: PocketRecommendedStoriesCategory) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import mozilla.components.service.pocket.PocketStory
import mozilla.components.service.pocket.PocketStory.PocketRecommendedStory
import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesCategory
import org.mozilla.fenix.home.pocket.controller.PocketStoriesController
import org.mozilla.fenix.home.pocket.controller.StoriesImpressionSource

/**
* Contract for all possible user interactions with the Pocket recommended stories feature.
Expand All @@ -26,8 +27,9 @@ interface PocketStoriesInteractor {
* Callback for then new stories are shown to the user.
*
* @param storiesShown The new list of [PocketRecommendedStory]es shown to the user.
* @param source the surface where the stories were shown.
Comment thread
devotaaabel marked this conversation as resolved.
Outdated
*/
fun onStoriesShown(storiesShown: List<PocketStory>)
fun onStoriesShown(storiesShown: List<PocketStory>, source: StoriesImpressionSource)

/**
* Callback for when the user clicks a specific category.
Expand Down Expand Up @@ -66,8 +68,8 @@ class DefaultPocketStoriesInteractor(
controller.handleStoryShown(storyShown, storyPosition)
}

override fun onStoriesShown(storiesShown: List<PocketStory>) {
controller.handleStoriesShown(storiesShown)
override fun onStoriesShown(storiesShown: List<PocketStory>, source: StoriesImpressionSource) {
controller.handleStoriesShown(storiesShown, source)
}

override fun onCategoryClicked(categoryClicked: PocketRecommendedStoriesCategory) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.compose.home.HomeSectionHeader
import org.mozilla.fenix.home.fake.FakeHomepagePreview
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.theme.FirefoxTheme
import org.mozilla.fenix.wallpapers.WallpaperState
Expand All @@ -45,7 +46,10 @@ fun PocketSection(
// We should report back when a certain story is actually being displayed.
// Cannot do it reliably so for now we'll just mass report everything as being displayed.
state.stories.let {
interactor.onStoriesShown(storiesShown = it)
interactor.onStoriesShown(
storiesShown = it,
source = StoriesImpressionSource.HOMEPAGE,
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import mozilla.components.compose.base.utils.BackInvokedHandler
import org.mozilla.fenix.R
import org.mozilla.fenix.components.appstate.recommendations.ContentRecommendationsState
import org.mozilla.fenix.home.fake.FakeHomepagePreview
import org.mozilla.fenix.home.pocket.controller.StoriesImpressionSource
import org.mozilla.fenix.home.pocket.interactor.PocketStoriesInteractor
import org.mozilla.fenix.home.ui.LeftChevronPillButton
import org.mozilla.fenix.theme.FirefoxTheme
Expand All @@ -54,6 +55,15 @@ fun StoriesScreen(
interactor.onDiscoverMoreScreenViewed()
}

// We should report back when a certain story is actually being displayed.
// Cannot do it reliably so for now we'll just mass report everything as being displayed.
LaunchedEffect(state.pocketStories) {
Comment thread
devotaaabel marked this conversation as resolved.
interactor.onStoriesShown(
storiesShown = state.pocketStories,
source = StoriesImpressionSource.STORIES_SCREEN,
)
}

BackInvokedHandler {
onNavigationIconClick()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import org.mozilla.fenix.home.logo.LogoController
import org.mozilla.fenix.home.logo.TrackingProtectionController
import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesCategory
import org.mozilla.fenix.home.pocket.controller.PocketStoriesController
import org.mozilla.fenix.home.pocket.controller.StoriesImpressionSource
import org.mozilla.fenix.home.privatebrowsing.controller.PrivateBrowsingController
import org.mozilla.fenix.home.recentsyncedtabs.RecentSyncedTab
import org.mozilla.fenix.home.recentsyncedtabs.controller.RecentSyncedTabController
Expand Down Expand Up @@ -381,8 +382,8 @@ class SessionControlInteractor(
pocketStoriesController.handleStoryShown(storyShown, storyPosition)
}

override fun onStoriesShown(storiesShown: List<PocketStory>) {
pocketStoriesController.handleStoriesShown(storiesShown)
override fun onStoriesShown(storiesShown: List<PocketStory>, source: StoriesImpressionSource) {
pocketStoriesController.handleStoriesShown(storiesShown, source)
}

override fun onCategoryClicked(categoryClicked: PocketRecommendedStoriesCategory) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import org.mozilla.fenix.home.logo.LogoController
import org.mozilla.fenix.home.logo.TrackingProtectionController
import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesCategory
import org.mozilla.fenix.home.pocket.controller.PocketStoriesController
import org.mozilla.fenix.home.pocket.controller.StoriesImpressionSource
import org.mozilla.fenix.home.privatebrowsing.controller.PrivateBrowsingController
import org.mozilla.fenix.home.recentsyncedtabs.RecentSyncedTab
import org.mozilla.fenix.home.recentsyncedtabs.controller.RecentSyncedTabController
Expand Down Expand Up @@ -245,9 +246,11 @@ class SessionControlInteractorTest {
fun `GIVEN a PocketStoriesInteractor WHEN stories are shown THEN handle it in a PocketStoriesController`() {
val shownStories: List<PocketStory> = emptyList()

interactor.onStoriesShown(shownStories)
interactor.onStoriesShown(shownStories, StoriesImpressionSource.HOMEPAGE)

verify { pocketStoriesController.handleStoriesShown(shownStories) }
verify {
pocketStoriesController.handleStoriesShown(shownStories, StoriesImpressionSource.HOMEPAGE)
}
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import org.mozilla.fenix.helpers.FenixGleanTestRule
import org.mozilla.fenix.home.HomeFragmentDirections
import org.mozilla.fenix.home.mars.MARSUseCases
import org.mozilla.fenix.home.pocket.controller.DefaultPocketStoriesController
import org.mozilla.fenix.home.pocket.controller.StoriesImpressionSource
import org.mozilla.fenix.utils.Settings
import org.mozilla.fenix.utils.Stories.markAsOpenedFromHomeScreen
import org.mozilla.fenix.utils.Stories.markAsOpenedFromStoriesScreen
Expand Down Expand Up @@ -282,7 +283,7 @@ class DefaultPocketStoriesControllerTest {

assertNull(Pocket.homeRecsShown.testGetValue())

controller.handleStoriesShown(storiesShown)
controller.handleStoriesShown(storiesShown, StoriesImpressionSource.HOMEPAGE)

verify {
store.dispatch(
Expand All @@ -297,7 +298,10 @@ class DefaultPocketStoriesControllerTest {

assertNotNull(Pocket.homeRecsShown.testGetValue())
assertEquals(1, Pocket.homeRecsShown.testGetValue()!!.size)
assertNull(Pocket.homeRecsShown.testGetValue()!!.single().extra)
assertEquals(
"homepage",
Pocket.homeRecsShown.testGetValue()!!.single().extra?.get("source"),
)
}

@Test
Expand Down