From 1bd97d30773b89a6be3c07eb7f85ae284e82462d Mon Sep 17 00:00:00 2001 From: dominickn Date: Thu, 6 Aug 2015 19:29:09 -0700 Subject: [PATCH] Add UMA to track app install banner outcomes. It is difficult to get a picture for what is happening when banners are shown, as three separate metrics track a number of fine-grained outcomes. This CL adds a new UMA solely tracking the user response to a banner, that is, once a banner is shown, whether users accept, dismiss, or ignore it. Native and web apps are tracked by separate metrics. BUG=516956 Review URL: https://codereview.chromium.org/1269303002 Cr-Commit-Position: refs/heads/master@{#342270} --- .../banners/app_banner_infobar_delegate_android.cc | 22 ++++++- .../banners/app_banner_infobar_delegate_android.h | 1 + .../banners/app_banner_infobar_delegate_desktop.cc | 11 +++- .../banners/app_banner_infobar_delegate_desktop.h | 1 + chrome/browser/banners/app_banner_metrics.cc | 73 +++++++++++----------- chrome/browser/banners/app_banner_metrics.h | 12 ++++ tools/metrics/histograms/histograms.xml | 18 ++++++ 7 files changed, 97 insertions(+), 41 deletions(-) rewrite chrome/browser/banners/app_banner_metrics.cc (68%) diff --git a/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc b/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc index a61220907f48..e1a247133029 100644 --- a/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc +++ b/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc @@ -43,7 +43,8 @@ AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid( : app_title_(app_title), app_icon_(app_icon), event_request_id_(event_request_id), - web_app_data_(web_app_data) { + web_app_data_(web_app_data), + has_user_interaction_(false) { DCHECK(!web_app_data.IsEmpty()); CreateJavaDelegate(); } @@ -58,12 +59,20 @@ AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid( app_icon_(app_icon), event_request_id_(event_request_id), native_app_data_(native_app_data), - native_app_package_(native_app_package) { + native_app_package_(native_app_package), + has_user_interaction_(false) { DCHECK(!native_app_data_.is_null()); CreateJavaDelegate(); } AppBannerInfoBarDelegateAndroid::~AppBannerInfoBarDelegateAndroid() { + if (!has_user_interaction_) { + if (!native_app_data_.is_null()) + TrackUserResponse(USER_RESPONSE_NATIVE_APP_IGNORED); + else if (!web_app_data_.IsEmpty()) + TrackUserResponse(USER_RESPONSE_WEB_APP_IGNORED); + } + TrackDismissEvent(DISMISS_EVENT_DISMISSED); JNIEnv* env = base::android::AttachCurrentThread(); Java_AppBannerInfoBarDelegateAndroid_destroy(env, @@ -150,6 +159,8 @@ gfx::Image AppBannerInfoBarDelegateAndroid::GetIcon() const { } void AppBannerInfoBarDelegateAndroid::InfoBarDismissed() { + has_user_interaction_ = true; + content::WebContents* web_contents = InfoBarService::WebContentsFromInfoBar(infobar()); if (!web_contents) @@ -161,9 +172,11 @@ void AppBannerInfoBarDelegateAndroid::InfoBarDismissed() { event_request_id_)); if (!native_app_data_.is_null()) { + TrackUserResponse(USER_RESPONSE_NATIVE_APP_DISMISSED); AppBannerSettingsHelper::RecordBannerDismissEvent( web_contents, native_app_package_, AppBannerSettingsHelper::NATIVE); } else if (!web_app_data_.IsEmpty()) { + TrackUserResponse(USER_RESPONSE_WEB_APP_DISMISSED); AppBannerSettingsHelper::RecordBannerDismissEvent( web_contents, web_app_data_.start_url.spec(), AppBannerSettingsHelper::WEB); @@ -179,6 +192,8 @@ int AppBannerInfoBarDelegateAndroid::GetButtons() const { } bool AppBannerInfoBarDelegateAndroid::Accept() { + has_user_interaction_ = true; + content::WebContents* web_contents = InfoBarService::WebContentsFromInfoBar(infobar()); if (!web_contents) { @@ -187,6 +202,7 @@ bool AppBannerInfoBarDelegateAndroid::Accept() { } if (!native_app_data_.is_null()) { + TrackUserResponse(USER_RESPONSE_NATIVE_APP_ACCEPTED); JNIEnv* env = base::android::AttachCurrentThread(); TabAndroid* tab = TabAndroid::FromWebContents(web_contents); @@ -209,6 +225,8 @@ bool AppBannerInfoBarDelegateAndroid::Accept() { SendBannerAccepted(web_contents, "play"); return was_opened; } else if (!web_app_data_.IsEmpty()) { + TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED); + AppBannerSettingsHelper::RecordBannerInstallEvent( web_contents, web_app_data_.start_url.spec(), AppBannerSettingsHelper::WEB); diff --git a/chrome/browser/android/banners/app_banner_infobar_delegate_android.h b/chrome/browser/android/banners/app_banner_infobar_delegate_android.h index f912dfcab69f..8bca480179ac 100644 --- a/chrome/browser/android/banners/app_banner_infobar_delegate_android.h +++ b/chrome/browser/android/banners/app_banner_infobar_delegate_android.h @@ -81,6 +81,7 @@ class AppBannerInfoBarDelegateAndroid : public ConfirmInfoBarDelegate { base::android::ScopedJavaGlobalRef native_app_data_; std::string native_app_package_; + bool has_user_interaction_; DISALLOW_COPY_AND_ASSIGN(AppBannerInfoBarDelegateAndroid); }; // AppBannerInfoBarDelegateAndroid diff --git a/chrome/browser/banners/app_banner_infobar_delegate_desktop.cc b/chrome/browser/banners/app_banner_infobar_delegate_desktop.cc index e959a879835b..693180a83994 100644 --- a/chrome/browser/banners/app_banner_infobar_delegate_desktop.cc +++ b/chrome/browser/banners/app_banner_infobar_delegate_desktop.cc @@ -28,10 +28,13 @@ AppBannerInfoBarDelegateDesktop::AppBannerInfoBarDelegateDesktop( fetcher_(fetcher), web_manifest_(web_manifest), bookmark_app_helper_(bookmark_app_helper), - event_request_id_(event_request_id) { + event_request_id_(event_request_id), + has_user_interaction_(false) { } AppBannerInfoBarDelegateDesktop::~AppBannerInfoBarDelegateDesktop() { + if (!has_user_interaction_) + TrackUserResponse(USER_RESPONSE_WEB_APP_IGNORED); } // static @@ -71,6 +74,9 @@ base::string16 AppBannerInfoBarDelegateDesktop::GetButtonLabel( } bool AppBannerInfoBarDelegateDesktop::Accept() { + TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED); + has_user_interaction_ = true; + bookmark_app_helper_->CreateFromAppBanner( base::Bind(&AppBannerDataFetcherDesktop::FinishCreateBookmarkApp, fetcher_), @@ -79,6 +85,9 @@ bool AppBannerInfoBarDelegateDesktop::Accept() { } void AppBannerInfoBarDelegateDesktop::InfoBarDismissed() { + TrackUserResponse(USER_RESPONSE_WEB_APP_DISMISSED); + has_user_interaction_ = true; + content::WebContents* web_contents = InfoBarService::WebContentsFromInfoBar(infobar()); if (web_contents) { diff --git a/chrome/browser/banners/app_banner_infobar_delegate_desktop.h b/chrome/browser/banners/app_banner_infobar_delegate_desktop.h index 6baa40e92bf9..a2f9df9690b8 100644 --- a/chrome/browser/banners/app_banner_infobar_delegate_desktop.h +++ b/chrome/browser/banners/app_banner_infobar_delegate_desktop.h @@ -61,6 +61,7 @@ class AppBannerInfoBarDelegateDesktop : public ConfirmInfoBarDelegate { content::Manifest web_manifest_; extensions::BookmarkAppHelper* bookmark_app_helper_; int event_request_id_; + bool has_user_interaction_; Type GetInfoBarType() const override; int GetIconID() const override; diff --git a/chrome/browser/banners/app_banner_metrics.cc b/chrome/browser/banners/app_banner_metrics.cc dissimilarity index 68% index 57a7d0fb1591..5ab6f59abb42 100644 --- a/chrome/browser/banners/app_banner_metrics.cc +++ b/chrome/browser/banners/app_banner_metrics.cc @@ -1,38 +1,35 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/banners/app_banner_metrics.h" - -#include "base/metrics/histogram.h" - -namespace banners { - -void TrackDismissEvent(int event) { - std::vector codes; - for (int i = DISMISS_EVENT_MIN + 1; i < DISMISS_EVENT_MAX; ++i) { - codes.push_back(i); - } - DCHECK(std::find(codes.begin(), codes.end(), event) != codes.end()); - UMA_HISTOGRAM_CUSTOM_ENUMERATION("AppBanners.DismissEvent", event, codes); -} - -void TrackDisplayEvent(int event) { - std::vector codes; - for (int i = DISPLAY_EVENT_MIN + 1; i < DISPLAY_EVENT_MAX; ++i) { - codes.push_back(i); - } - DCHECK(std::find(codes.begin(), codes.end(), event) != codes.end()); - UMA_HISTOGRAM_CUSTOM_ENUMERATION("AppBanners.DisplayEvent", event, codes); -} - -void TrackInstallEvent(int event) { - std::vector codes; - for (int i = INSTALL_EVENT_MIN + 1; i < INSTALL_EVENT_MAX; ++i) { - codes.push_back(i); - } - DCHECK(std::find(codes.begin(), codes.end(), event) != codes.end()); - UMA_HISTOGRAM_CUSTOM_ENUMERATION("AppBanners.InstallEvent", event, codes); -} - -} // namespace banners +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/banners/app_banner_metrics.h" + +#include "base/metrics/sparse_histogram.h" + +namespace banners { + +void TrackDismissEvent(int event) { + DCHECK_LT(DISMISS_EVENT_MIN, event); + DCHECK_LT(event, DISMISS_EVENT_MAX); + UMA_HISTOGRAM_SPARSE_SLOWLY("AppBanners.DismissEvent", event); +} + +void TrackDisplayEvent(int event) { + DCHECK_LT(DISPLAY_EVENT_MIN, event); + DCHECK_LT(event, DISPLAY_EVENT_MAX); + UMA_HISTOGRAM_SPARSE_SLOWLY("AppBanners.DisplayEvent", event); +} + +void TrackInstallEvent(int event) { + DCHECK_LT(INSTALL_EVENT_MIN, event); + DCHECK_LT(event, INSTALL_EVENT_MAX); + UMA_HISTOGRAM_SPARSE_SLOWLY("AppBanners.InstallEvent", event); +} + +void TrackUserResponse(int event) { + DCHECK_LT(USER_RESPONSE_MIN, event); + DCHECK_LT(event, USER_RESPONSE_MAX); + UMA_HISTOGRAM_SPARSE_SLOWLY("AppBanners.UserResponse", event); +} + +} // namespace banners diff --git a/chrome/browser/banners/app_banner_metrics.h b/chrome/browser/banners/app_banner_metrics.h index aced73b3238a..7c7817929243 100644 --- a/chrome/browser/banners/app_banner_metrics.h +++ b/chrome/browser/banners/app_banner_metrics.h @@ -46,9 +46,21 @@ enum DismissEvent { DISMISS_EVENT_MAX = 48, }; +enum UserResponse { + USER_RESPONSE_MIN = 0, + USER_RESPONSE_NATIVE_APP_ACCEPTED = 1, + USER_RESPONSE_WEB_APP_ACCEPTED = 2, + USER_RESPONSE_NATIVE_APP_DISMISSED = 3, + USER_RESPONSE_WEB_APP_DISMISSED = 4, + USER_RESPONSE_NATIVE_APP_IGNORED = 5, + USER_RESPONSE_WEB_APP_IGNORED = 6, + USER_RESPONSE_MAX = 7, +}; + void TrackDismissEvent(int event); void TrackDisplayEvent(int event); void TrackInstallEvent(int event); +void TrackUserResponse(int event); }; // namespace banners diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 8f4649f569eb..e8209c9091fc 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -338,6 +338,15 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries. + + dominickn@chromium.org + + App banners promote an application related to the current website, and are + requested specifically through the current page's HTML. This stat + specifically tracks a user's response to a displayed banner. + + + michaeln@chromium.org @@ -50933,6 +50942,15 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries. + + + + + + + + + -- 2.11.4.GIT