1
0
Fork 0

For #1158 - Add search counts

master
Jeff Boek 2019-04-16 16:31:35 -07:00
parent 62937cd7f0
commit cb7ad32b62
4 changed files with 98 additions and 16 deletions

View File

@ -54,14 +54,19 @@ events:
description: > description: >
A user performed a search A user performed a search
extra_keys: extra_keys:
search_suggestion: source:
description: "A boolean that tells us whether or not the search term was suggested by the Awesomebar" description: >
search_shortcut: A string that tells us how the user performed the search. Possible values are:
description: "A boolean that tells us whether or not the search was conducted through a search shortcut" * default.action
* default.suggestion
* shortcut.action
* shortcut.suggestion
bugs: bugs:
- 959 - 959
data_reviews: data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673 - https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673
- https://github.com/mozilla-mobile/fenix/pull/1677
notification_emails: notification_emails:
- fenix-core@mozilla.com - fenix-core@mozilla.com
expires: "2020-03-01" expires: "2020-03-01"
@ -307,6 +312,24 @@ metrics:
notification_emails: notification_emails:
- fenix-core@mozilla.com - fenix-core@mozilla.com
expires: "2020-03-01" expires: "2020-03-01"
search_count:
type: labeled_counter
description: >
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 either be `action` or `suggestion`
send_in_pings:
- metrics
bugs:
- 1158
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/1677
notification_emails:
- fenix-core@mozilla.com
expires: "2019-09-01"
search.default_engine: search.default_engine:
code: code:
@ -357,4 +380,4 @@ search.default_engine:
- https://github.com/mozilla-mobile/fenix/issues/1607 - https://github.com/mozilla-mobile/fenix/issues/1607
notification_emails: notification_emails:
- fenix-core@mozilla.com - fenix-core@mozilla.com
expires: "2019-09-01" expires: "2019-09-01"

View File

@ -52,7 +52,10 @@ private val Event.wrapper
{ Events.enteredUrlKeys.valueOf(it) } { Events.enteredUrlKeys.valueOf(it) }
) )
is Event.PerformedSearch -> EventWrapper( is Event.PerformedSearch -> EventWrapper(
{ Events.performedSearch.record(it) }, {
Metrics.searchCount[this.eventSource.countLabel].add(1)
Events.performedSearch.record(it)
},
{ Events.performedSearchKeys.valueOf(it) } { Events.performedSearchKeys.valueOf(it) }
) )
is Event.FindInPageOpened -> EventWrapper<NoExtraKeys>( is Event.FindInPageOpened -> EventWrapper<NoExtraKeys>(

View File

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.components.metrics package org.mozilla.fenix.components.metrics
import mozilla.components.browser.search.SearchEngine
import mozilla.components.support.base.Component import mozilla.components.support.base.Component
import mozilla.components.support.base.facts.Fact import mozilla.components.support.base.facts.Fact
import mozilla.components.support.base.facts.FactProcessor import mozilla.components.support.base.facts.FactProcessor
@ -69,10 +70,49 @@ sealed class Event {
get() = mapOf("autocomplete" to autoCompleted.toString()) get() = mapOf("autocomplete" to autoCompleted.toString())
} }
data class PerformedSearch(val fromSearchSuggestion: Boolean, val fromSearchShortcut: Boolean) : Event() { data class PerformedSearch(val eventSource: EventSource) : Event() {
sealed class EngineSource {
data class Default(val engine: SearchEngine) : EngineSource()
data class Shortcut(val engine: SearchEngine) : EngineSource()
val searchEngine: SearchEngine
get() = when (this) {
is Default -> engine
is Shortcut -> engine
}
val descriptor: String
get() = when (this) {
is Default -> "default"
is Shortcut -> "shortcut"
}
}
sealed class EventSource {
data class Suggestion(val engineSource: EngineSource) : EventSource()
data class Action(val engineSource: EngineSource) : EventSource()
private val source: EngineSource
get() = when (this) {
is Suggestion -> engineSource
is Action -> engineSource
}
private val label: String
get() = when (this) {
is Suggestion -> "suggestion"
is Action -> "action"
}
val countLabel: String
get() = "${source.searchEngine.identifier}.$label"
val sourceLabel: String
get() = "${source.descriptor}.$label"
}
override val extras: Map<String, String>? override val extras: Map<String, String>?
get() = mapOf("search_suggestion" to fromSearchSuggestion.toString(), get() = mapOf("source" to eventSource.sourceLabel)
"search_shortcut" to fromSearchShortcut.toString())
} }
// Track only built-in engine selection. Do not track user-added engines! // Track only built-in engine selection. Do not track user-added engines!
@ -122,6 +162,8 @@ sealed class Event {
get() = mapOf("item" to item.toString().toLowerCase()) get() = mapOf("item" to item.toString().toLowerCase())
} }
sealed class Search
open val extras: Map<String, String>? open val extras: Map<String, String>?
get() = null get() = null
} }

View File

@ -120,7 +120,9 @@ class SearchFragment : Fragment() {
val event = if (it.url.isUrl()) { val event = if (it.url.isUrl()) {
Event.EnteredUrl(false) Event.EnteredUrl(false)
} else { } else {
Event.PerformedSearch(false, isSearchShortcut(it.engine)) if (it.engine == null) { return@subscribe }
createSearchEvent(it.engine, false)
} }
requireComponents.analytics.metrics.track(event) requireComponents.analytics.metrics.track(event)
@ -150,8 +152,10 @@ class SearchFragment : Fragment() {
.invoke(it.searchTerms, it.engine) .invoke(it.searchTerms, it.engine)
(activity as HomeActivity).openToBrowser(sessionId, BrowserDirection.FromSearch) (activity as HomeActivity).openToBrowser(sessionId, BrowserDirection.FromSearch)
requireComponents.analytics.metrics if (it.engine == null) { return@subscribe }
.track(Event.PerformedSearch(true, isSearchShortcut(it.engine))) val event = createSearchEvent(it.engine, true)
requireComponents.analytics.metrics.track(event)
} }
is AwesomeBarAction.SearchShortcutEngineSelected -> { is AwesomeBarAction.SearchShortcutEngineSelected -> {
getManagedEmitter<AwesomeBarChange>() getManagedEmitter<AwesomeBarChange>()
@ -165,6 +169,20 @@ class SearchFragment : Fragment() {
} }
} }
private fun createSearchEvent(engine: SearchEngine, isSuggestion: Boolean): Event.PerformedSearch {
val isShortcut = engine != requireComponents.search.searchEngineManager.defaultSearchEngine
val engineSource =
if (isShortcut) Event.PerformedSearch.EngineSource.Shortcut(engine)
else Event.PerformedSearch.EngineSource.Default(engine)
val source =
if (isSuggestion) Event.PerformedSearch.EventSource.Suggestion(engineSource)
else Event.PerformedSearch.EventSource.Action(engineSource)
return Event.PerformedSearch(source)
}
private fun getSearchUseCase(context: Context, useNewTab: Boolean): SearchUseCases.SearchUseCase { private fun getSearchUseCase(context: Context, useNewTab: Boolean): SearchUseCases.SearchUseCase {
if (!useNewTab) { if (!useNewTab) {
return context.components.useCases.searchUseCases.defaultSearch return context.components.useCases.searchUseCases.defaultSearch
@ -186,8 +204,4 @@ class SearchFragment : Fragment() {
false -> context.components.useCases.tabsUseCases.addTab false -> context.components.useCases.tabsUseCases.addTab
} }
} }
private fun isSearchShortcut(engine: SearchEngine?): Boolean {
return engine != null && engine != requireComponents.search.searchEngineManager.defaultSearchEngine
}
} }