diff --git a/app/metrics.yaml b/app/metrics.yaml index dc1e4f58bd8b..168ba0ceecff 100644 --- a/app/metrics.yaml +++ b/app/metrics.yaml @@ -480,7 +480,6 @@ metrics: notification_emails: - fenix-core@mozilla.com expires: "2020-09-01" - toolbar_position: type: string lifetime: application @@ -495,7 +494,20 @@ metrics: notification_emails: - fenix-core@mozilla.com expires: "2020-09-01" - + search_widget_installed: + type: boolean + lifetime: application + description: | + Whether or not the search widget is installed + send_in_pings: + - metrics + bugs: + - https://github.com/mozilla-mobile/fenix/issues/9488 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/10958 + notification_emails: + - fenix-core@mozilla.com + expires: "2020-09-01" search.default_engine: code: @@ -1356,6 +1368,53 @@ search_widget: - fenix-core@mozilla.com expires: "2020-09-01" +search_widget_cfr: + displayed: + type: event + description: | + The search widget cfr was displayed. + bugs: + - https://github.com/mozilla-mobile/fenix/issues/9488 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/10958 + notification_emails: + - fenix-core@mozilla.com + expires: "2020-09-01" + add_widget_pressed: + type: event + description: | + The user pressed the "add widget" button. + bugs: + - https://github.com/mozilla-mobile/fenix/issues/9488 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/10958 + notification_emails: + - fenix-core@mozilla.com + expires: "2020-09-01" + not_now_pressed: + type: event + description: | + The user pressed the "not now" button. + bugs: + - https://github.com/mozilla-mobile/fenix/issues/9488 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/10958 + notification_emails: + - fenix-core@mozilla.com + expires: "2020-09-01" + canceled: + type: event + description: | + The user dismissed the search widget cfr by + tapping outside of the prompt + bugs: + - https://github.com/mozilla-mobile/fenix/issues/9488 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/10958 + notification_emails: + - fenix-core@mozilla.com + expires: "2020-09-01" + private_browsing_mode: garbage_icon: type: event diff --git a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt index d539cdecd7c7..9f3dbf6794dc 100644 --- a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt +++ b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt @@ -53,4 +53,10 @@ object FeatureFlags { * Enables new voice search feature */ val voiceSearch = Config.channel.isNightlyOrDebug + + /** + * Allows search widget CFR to be displayed. + * This is a placeholder for the experimentation framework determining cohorts. + */ + val searchWidgetCFR = Config.channel.isDebug } diff --git a/app/src/main/java/org/mozilla/fenix/cfr/SearchWidgetCFR.kt b/app/src/main/java/org/mozilla/fenix/cfr/SearchWidgetCFR.kt index 884e7c11fafa..00f0c084f1f5 100644 --- a/app/src/main/java/org/mozilla/fenix/cfr/SearchWidgetCFR.kt +++ b/app/src/main/java/org/mozilla/fenix/cfr/SearchWidgetCFR.kt @@ -17,8 +17,11 @@ import androidx.core.view.marginTop import kotlinx.android.synthetic.main.search_widget_cfr.view.* import kotlinx.android.synthetic.main.tracking_protection_onboarding_popup.view.drop_down_triangle import kotlinx.android.synthetic.main.tracking_protection_onboarding_popup.view.pop_up_triangle +import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.R import org.mozilla.fenix.components.SearchWidgetCreator +import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import org.mozilla.fenix.utils.Settings @@ -30,9 +33,8 @@ class SearchWidgetCFR( private val getToolbar: () -> View ) { - // TODO: Based on pref && is in the bucket...? fun displayIfNecessary() { - if (!context.settings().shouldDisplaySearchWidgetCFR()) { return } + if (!context.settings().shouldDisplaySearchWidgetCFR() || !FeatureFlags.searchWidgetCFR) { return } showSearchWidgetCFR() } @@ -57,15 +59,16 @@ class SearchWidgetCFR( } layout.cfr_neg_button.setOnClickListener { + context.components.analytics.metrics.track(Event.SearchWidgetCFRNotNowPressed) searchWidgetCFRDialog.dismiss() context.settings().manuallyDismissSearchWidgetCFR() } layout.cfr_pos_button.setOnClickListener { - //context.components.analytics.metrics.track(Event.) + context.components.analytics.metrics.track(Event.SearchWidgetCFRAddWidgetPressed) SearchWidgetCreator.createSearchWidget(context) searchWidgetCFRDialog.dismiss() - //context.settings().manuallyDismissSearchWidgetCFR() + context.settings().manuallyDismissSearchWidgetCFR() } searchWidgetCFRDialog.apply { @@ -81,10 +84,15 @@ class SearchWidgetCFR( it.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) } + searchWidgetCFRDialog.setOnCancelListener { + context.components.analytics.metrics.track(Event.SearchWidgetCFRCanceled) + } + searchWidgetCFRDialog.setOnDismissListener { context.settings().incrementSearchWidgetCFRDismissed() } searchWidgetCFRDialog.show() + context.components.analytics.metrics.track(Event.SearchWidgetCFRDisplayed) } } diff --git a/app/src/main/java/org/mozilla/fenix/components/SearchWidgetCreator.kt b/app/src/main/java/org/mozilla/fenix/components/SearchWidgetCreator.kt index f16cc4eef29a..41734d7549e6 100644 --- a/app/src/main/java/org/mozilla/fenix/components/SearchWidgetCreator.kt +++ b/app/src/main/java/org/mozilla/fenix/components/SearchWidgetCreator.kt @@ -12,7 +12,7 @@ import android.os.Build import org.mozilla.gecko.search.SearchWidgetProvider /** - * Handles the creation of search widget. + * Handles the creation of the pinning search widget dialog. */ object SearchWidgetCreator { 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 bb3e09f11716..7989e6ce1a53 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 @@ -36,6 +36,7 @@ import org.mozilla.fenix.GleanMetrics.SearchDefaultEngine import org.mozilla.fenix.GleanMetrics.SearchShortcuts import org.mozilla.fenix.GleanMetrics.SearchSuggestions import org.mozilla.fenix.GleanMetrics.SearchWidget +import org.mozilla.fenix.GleanMetrics.SearchWidgetCfr import org.mozilla.fenix.GleanMetrics.SyncAccount import org.mozilla.fenix.GleanMetrics.SyncAuth import org.mozilla.fenix.GleanMetrics.Tab @@ -529,6 +530,19 @@ private val Event.wrapper: EventWrapper<*>? is Event.VoiceSearchTapped -> EventWrapper( { VoiceSearch.tapped.record(it) } ) + is Event.SearchWidgetCFRDisplayed -> EventWrapper( + { SearchWidgetCfr.displayed.record(it) } + ) + is Event.SearchWidgetCFRCanceled -> EventWrapper( + { SearchWidgetCfr.canceled.record(it) } + ) + is Event.SearchWidgetCFRNotNowPressed -> EventWrapper( + { SearchWidgetCfr.notNowPressed.record(it) } + ) + is Event.SearchWidgetCFRAddWidgetPressed -> EventWrapper( + { SearchWidgetCfr.addWidgetPressed.record(it) } + ) + // Don't record other events in Glean: is Event.AddBookmark -> null is Event.OpenedBookmark -> null @@ -584,6 +598,9 @@ class GleanMetricsService(private val context: Context) : MetricsService { adjustAdGroup.set(context.settings().adjustAdGroup) adjustCreative.set(context.settings().adjustCreative) adjustNetwork.set(context.settings().adjustNetwork) + + searchWidgetInstalled.set(context.settings().searchWidgetInstalled) + val topSitesSize = context.settings().topSitesSize hasTopSites.set(topSitesSize > 0) if (topSitesSize > 0) { diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/Metrics.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/Metrics.kt index 4b7d49839f2c..3bcc9ead4014 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/Metrics.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/Metrics.kt @@ -168,6 +168,10 @@ sealed class Event { object AddonsOpenInSettings : Event() object AddonsOpenInToolbarMenu : Event() object VoiceSearchTapped : Event() + object SearchWidgetCFRDisplayed : Event() + object SearchWidgetCFRCanceled : Event() + object SearchWidgetCFRNotNowPressed : Event() + object SearchWidgetCFRAddWidgetPressed : Event() // Interaction events with extras diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchController.kt b/app/src/main/java/org/mozilla/fenix/search/SearchController.kt index cbe131f1c8d7..5a01ba3cea52 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchController.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchController.kt @@ -81,7 +81,7 @@ class DefaultSearchController( val event = if (url.isUrl()) { Event.EnteredUrl(false) } else { - context.settings().incrementActiveSearchCount() + activity.settings().incrementActiveSearchCount() val searchAccessPoint = when (store.state.searchAccessPoint) { NONE -> ACTION @@ -144,7 +144,7 @@ class DefaultSearchController( } override fun handleSearchTermsTapped(searchTerms: String) { - context.settings().incrementActiveSearchCount() + activity.settings().incrementActiveSearchCount() activity.openToBrowserAndLoad( searchTermOrURL = searchTerms, diff --git a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt index ed679dd603d5..b00674527ba3 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -55,6 +55,7 @@ class Settings private constructor( const val trackingProtectionOnboardingMaximumCount = 1 const val FENIX_PREFERENCES = "fenix_preferences" + private const val showSearchWidgetCFRMaxCount = 3 private const val BLOCKED_INT = 0 private const val ASK_TO_ALLOW_INT = 1 private const val ALLOWED_INT = 2 @@ -166,7 +167,7 @@ class Settings private constructor( fun shouldDisplaySearchWidgetCFR(): Boolean = isActiveSearcher && - searchWidgetCFRDismissCount < 3 && + searchWidgetCFRDismissCount < showSearchWidgetCFRMaxCount && !searchWidgetInstalled && !searchWidgetCFRManuallyDismissed diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a946856736b0..3d5cb1ba0ce1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -45,7 +45,7 @@ No thanks - + Get to Firefox faster. Add a widget to your Home screen. Add widget diff --git a/docs/metrics.md b/docs/metrics.md index 519dea92789d..1bbfc0fb3302 100644 --- a/docs/metrics.md +++ b/docs/metrics.md @@ -146,6 +146,10 @@ The following metrics are added to the ping: | search_suggestions.enable_in_private |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user enabled receiving search suggestions in private sessions |[1](https://github.com/mozilla-mobile/fenix/pull/6746)||2020-09-01 | | search_widget.new_tab_button |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed anywhere from the Firefox logo until the start of the microphone icon, opening a new tab search screen. |[1](https://github.com/mozilla-mobile/fenix/pull/4714)||2020-09-01 | | search_widget.voice_button |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the microphone icon, opening a new voice search screen. |[1](https://github.com/mozilla-mobile/fenix/pull/4714)||2020-09-01 | +| search_widget_cfr.add_widget_pressed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user pressed the "add widget" button. |[1](https://github.com/mozilla-mobile/fenix/pull/10958)||2020-09-01 | +| search_widget_cfr.canceled |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user dismissed the search widget cfr by tapping outside of the prompt |[1](https://github.com/mozilla-mobile/fenix/pull/10958)||2020-09-01 | +| search_widget_cfr.displayed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The search widget cfr was displayed. |[1](https://github.com/mozilla-mobile/fenix/pull/10958)||2020-09-01 | +| search_widget_cfr.not_now_pressed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user pressed the "not now" button. |[1](https://github.com/mozilla-mobile/fenix/pull/10958)||2020-09-01 | | sync_account.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed the sync account page |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-09-01 | | sync_account.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the sync account page |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-09-01 | | sync_account.send_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user sent the current tab to another FxA device |[1](https://github.com/mozilla-mobile/fenix/pull/5106)||2020-09-01 | @@ -233,6 +237,7 @@ The following metrics are added to the ping: | metrics.has_top_sites |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |A boolean that indicates if the user has top sites |[1](https://github.com/mozilla-mobile/fenix/pull/9556)||2020-09-01 | | 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)||2020-09-01 | | metrics.search_count |[labeled_counter](https://mozilla.github.io/glean/book/user/metrics/labeled_counters.html) |The labels for this counter are `.`. 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)||2020-09-01 | +| 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)||2020-09-01 | | metrics.toolbar_position |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string that indicates the new position of the toolbar TOP or BOTTOM |[1](https://github.com/mozilla-mobile/fenix/pull/6608)||2020-09-01 | | metrics.top_sites_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter that indicates how many top sites a user has. This value will only be set if the user has at least *one* top site. If they have 0, this ping will not get sent, resulting in a null value. To disambiguate between a failed `top_sites_count` ping and 0 top sites, please see `has_top_sites`. |[1](https://github.com/mozilla-mobile/fenix/pull/9556)||2020-09-01 | | perf.awesomebar.bookmark_suggestions |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |Duration of a bookmarks awesomebar suggestion query. |[1](https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979)||2020-09-15 |