Commit 4fed2d53 authored by Keren Zhu's avatar Keren Zhu Committed by Commit Bot

Add Finch and UMA to IPH Snooze

* Add Finch to control snooze duration experiment.
* Add UMA to track 4 events, all with the count of previous snoozes.
  1) Tab Group IPH trigger.
  2) Tab Group IPH dismiss by dismiss button.
  3) Tab Group IPH dismiss by right-click on tab.
  4) Tab Group IPH snooze.

Bug: 1121399
Change-Id: Ib5aa2ed0c92d5bf8cfe2f1744d596ac2d03e6a0d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2425230
Commit-Queue: Keren Zhu <kerenzhu@chromium.org>
Reviewed-by: default avatarBrian White <bcwhite@chromium.org>
Reviewed-by: default avatarCollin Baker <collinbaker@chromium.org>
Reviewed-by: default avatarWei Li <weili@chromium.org>
Cr-Commit-Position: refs/heads/master@{#811904}
parent 37cb12f1
...@@ -7,11 +7,14 @@ ...@@ -7,11 +7,14 @@
#include <ostream> #include <ostream>
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/util/values/values_util.h" #include "base/util/values/values_util.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_registry_simple.h"
#include "components/prefs/scoped_user_pref_update.h" #include "components/prefs/scoped_user_pref_update.h"
...@@ -33,8 +36,26 @@ constexpr char kIPHSnoozedFeatureDuration[] = "last_snooze_duration"; ...@@ -33,8 +36,26 @@ constexpr char kIPHSnoozedFeatureDuration[] = "last_snooze_duration";
// Path to the count of how many times this IPH has been snoozed. // Path to the count of how many times this IPH has been snoozed.
// in_product_help.snoozed_feature.[iph_name].snooze_count // in_product_help.snoozed_feature.[iph_name].snooze_count
constexpr char kIPHSnoozedFeatureCount[] = "snooze_count"; constexpr char kIPHSnoozedFeatureCount[] = "snooze_count";
// Finch parameter to control the snooze duration.
// If this parameter is not specified or is zero, the default duration at the
// client side will be used.
constexpr base::FeatureParam<base::TimeDelta> kOverriddenDuration{
&feature_engagement::kIPHDesktopSnoozeFeature,
"x_iph_snooze_overridden_duration ", base::TimeDelta::FromHours(0)};
// Used in UMA histogram to track if the user snoozes for once or more.
enum class SnoozeType {
// The user snoozes the IPH for the first time.
kFirstTimeSnooze = 0,
// The user snoozes the IPH for the second time or more.
kRepeatingSnooze = 1,
kMaxValue = kRepeatingSnooze
};
} // namespace } // namespace
const int FeaturePromoSnoozeService::kUmaMaxSnoozeCount = 10;
FeaturePromoSnoozeService::FeaturePromoSnoozeService(Profile* profile) FeaturePromoSnoozeService::FeaturePromoSnoozeService(Profile* profile)
: profile_(profile) {} : profile_(profile) {}
...@@ -46,6 +67,14 @@ void FeaturePromoSnoozeService::OnUserSnooze(const base::Feature& iph_feature, ...@@ -46,6 +67,14 @@ void FeaturePromoSnoozeService::OnUserSnooze(const base::Feature& iph_feature,
if (!snooze_data) if (!snooze_data)
snooze_data = SnoozeData(); snooze_data = SnoozeData();
if (!kOverriddenDuration.Get().is_zero())
snooze_duration = kOverriddenDuration.Get();
base::UmaHistogramEnumeration(
"InProductHelp.Promos.Snooze." + std::string(iph_feature.name),
snooze_data->snooze_count == 0 ? SnoozeType::kFirstTimeSnooze
: SnoozeType::kRepeatingSnooze);
snooze_data->last_snooze_time = base::Time::Now(); snooze_data->last_snooze_time = base::Time::Now();
snooze_data->last_snooze_duration = snooze_duration; snooze_data->last_snooze_duration = snooze_duration;
snooze_data->snooze_count++; snooze_data->snooze_count++;
...@@ -63,6 +92,13 @@ void FeaturePromoSnoozeService::OnUserDismiss( ...@@ -63,6 +92,13 @@ void FeaturePromoSnoozeService::OnUserDismiss(
snooze_data->is_dismissed = true; snooze_data->is_dismissed = true;
SaveSnoozeData(iph_feature, *snooze_data); SaveSnoozeData(iph_feature, *snooze_data);
// Record count of previous snoozes when the IPH gets dismissed by "Got It"
// button.
base::UmaHistogramExactLinear(
"InProductHelp.Promos.SnoozeCountAtAcknowledge." +
std::string(iph_feature.name),
snooze_data->snooze_count, kUmaMaxSnoozeCount);
} }
bool FeaturePromoSnoozeService::IsBlocked(const base::Feature& iph_feature) { bool FeaturePromoSnoozeService::IsBlocked(const base::Feature& iph_feature) {
...@@ -100,6 +136,12 @@ void FeaturePromoSnoozeService::Reset(const base::Feature& iph_feature) { ...@@ -100,6 +136,12 @@ void FeaturePromoSnoozeService::Reset(const base::Feature& iph_feature) {
pref_data->RemovePath(iph_feature.name); pref_data->RemovePath(iph_feature.name);
} }
int FeaturePromoSnoozeService::GetSnoozeCount(
const base::Feature& iph_feature) {
base::Optional<SnoozeData> snooze_data = ReadSnoozeData(iph_feature);
return snooze_data ? snooze_data->snooze_count : 0;
}
base::Optional<FeaturePromoSnoozeService::SnoozeData> base::Optional<FeaturePromoSnoozeService::SnoozeData>
FeaturePromoSnoozeService::ReadSnoozeData(const base::Feature& iph_feature) { FeaturePromoSnoozeService::ReadSnoozeData(const base::Feature& iph_feature) {
std::string path_prefix = std::string(iph_feature.name) + "."; std::string path_prefix = std::string(iph_feature.name) + ".";
......
...@@ -24,6 +24,10 @@ class PrefRegistrySimple; ...@@ -24,6 +24,10 @@ class PrefRegistrySimple;
// If an IPH is dismissed, this service will reject controller's request. // If an IPH is dismissed, this service will reject controller's request.
class FeaturePromoSnoozeService { class FeaturePromoSnoozeService {
public: public:
// Maximum count of snoozes to track in UMA histogram.
// Snooze counts that are equal or larger than this value will be conflated.
static const int kUmaMaxSnoozeCount;
explicit FeaturePromoSnoozeService(Profile* profile); explicit FeaturePromoSnoozeService(Profile* profile);
// Disallow copy and assign. // Disallow copy and assign.
...@@ -48,11 +52,14 @@ class FeaturePromoSnoozeService { ...@@ -48,11 +52,14 @@ class FeaturePromoSnoozeService {
// snoozing period has timed out. // snoozing period has timed out.
bool IsBlocked(const base::Feature& iph_feature); bool IsBlocked(const base::Feature& iph_feature);
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
// Reset the state of |iph_feature|. // Reset the state of |iph_feature|.
void Reset(const base::Feature& iph_feature); void Reset(const base::Feature& iph_feature);
// Read the count of previous snoozes for |iph_feature| from profile.
int GetSnoozeCount(const base::Feature& iph_feature);
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
private: private:
// Snooze information dictionary saved under path // Snooze information dictionary saved under path
// in_product_help.snoozed_feature.[iph_name] in PerfService. // in_product_help.snoozed_feature.[iph_name] in PerfService.
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/optional.h" #include "base/optional.h"
#include "chrome/browser/feature_engagement/tracker_factory.h" #include "chrome/browser/feature_engagement/tracker_factory.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
...@@ -75,6 +76,13 @@ bool FeaturePromoControllerViews::MaybeShowPromoWithParams( ...@@ -75,6 +76,13 @@ bool FeaturePromoControllerViews::MaybeShowPromoWithParams(
base::Unretained(this), iph_feature)); base::Unretained(this), iph_feature));
widget_observer_.Add(promo_bubble_->GetWidget()); widget_observer_.Add(promo_bubble_->GetWidget());
// Record count of previous snoozes when an IPH triggers.
int snooze_count = snooze_service_->GetSnoozeCount(iph_feature);
base::UmaHistogramExactLinear("InProductHelp.Promos.SnoozeCountAtTrigger." +
std::string(iph_feature.name),
snooze_count,
snooze_service_->kUmaMaxSnoozeCount);
return true; return true;
} }
...@@ -130,6 +138,14 @@ FeaturePromoControllerViews::CloseBubbleAndContinuePromo( ...@@ -130,6 +138,14 @@ FeaturePromoControllerViews::CloseBubbleAndContinuePromo(
if (anchor_view_tracker_.view()) if (anchor_view_tracker_.view())
anchor_view_tracker_.view()->SetProperty(kHasInProductHelpPromoKey, false); anchor_view_tracker_.view()->SetProperty(kHasInProductHelpPromoKey, false);
// Record count of previous snoozes when the IPH gets dismissed by user
// following the promo. e.g. clicking on relevant controls.
int snooze_count = snooze_service_->GetSnoozeCount(iph_feature);
base::UmaHistogramExactLinear("InProductHelp.Promos.SnoozeCountAtFollow." +
std::string(iph_feature.name),
snooze_count,
snooze_service_->kUmaMaxSnoozeCount);
return PromoHandle(weak_ptr_factory_.GetWeakPtr()); return PromoHandle(weak_ptr_factory_.GetWeakPtr());
} }
......
...@@ -7857,6 +7857,10 @@ reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -7857,6 +7857,10 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
<suffix name="IPH_WebUITabStrip" <suffix name="IPH_WebUITabStrip"
label="In product help for opening the WebUI tab strip."/> label="In product help for opening the WebUI tab strip."/>
<affected-histogram name="InProductHelp.NotifyEventReadyState"/> <affected-histogram name="InProductHelp.NotifyEventReadyState"/>
<affected-histogram name="InProductHelp.Promos.Snooze"/>
<affected-histogram name="InProductHelp.Promos.SnoozeCountAtAcknowledge"/>
<affected-histogram name="InProductHelp.Promos.SnoozeCountAtFollow"/>
<affected-histogram name="InProductHelp.Promos.SnoozeCountAtTrigger"/>
<affected-histogram name="InProductHelp.ShouldTriggerHelpUI"/> <affected-histogram name="InProductHelp.ShouldTriggerHelpUI"/>
</histogram_suffixes> </histogram_suffixes>
......
...@@ -6498,6 +6498,56 @@ reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -6498,6 +6498,56 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</summary> </summary>
</histogram> </histogram>
<histogram name="InProductHelp.Promos.Snooze" units="SnoozeType"
expires_after="M88">
<!-- Name completed by histogram_suffixes name="IPHFeatures" -->
<owner>kerenzhu@chromium.org</owner>
<owner>collinbaker@chromium.org</owner>
<summary>
Record the number of first-time snoozes and repeating snoozes of an
in-product help bubble when the user clicks the snooze button. An snooze of
an IPH that has been snoozed before is a repeating snooze.
</summary>
</histogram>
<histogram name="InProductHelp.Promos.SnoozeCountAtAcknowledge" units="times"
expires_after="M88">
<!-- Name completed by histogram_suffixes name="IPHFeatures" -->
<owner>kerenzhu@chromium.org</owner>
<owner>collinbaker@chromium.org</owner>
<summary>
Record the number of previous snoozes when an in-product help bubble is
dismissed because the acknowledge button is clicked.
</summary>
</histogram>
<histogram name="InProductHelp.Promos.SnoozeCountAtFollow" units="times"
expires_after="M88">
<!-- Name completed by histogram_suffixes name="IPHFeatures" -->
<owner>kerenzhu@chromium.org</owner>
<owner>collinbaker@chromium.org</owner>
<summary>
Record the number of previous snoozes when an in-product help bubble is
dismissed because the user follows the promo, e.g. a relevant control is
clicked.
</summary>
</histogram>
<histogram name="InProductHelp.Promos.SnoozeCountAtTrigger" units="times"
expires_after="M88">
<!-- Name completed by histogram_suffixes name="IPHFeatures" -->
<owner>kerenzhu@chromium.org</owner>
<owner>collinbaker@chromium.org</owner>
<summary>
Record the number of previous snoozes when an in-product help bubble is
triggered.
</summary>
</histogram>
<histogram name="InProductHelp.ShouldTriggerHelpUI" enum="TriggerHelpUIResult" <histogram name="InProductHelp.ShouldTriggerHelpUI" enum="TriggerHelpUIResult"
expires_after="M85"> expires_after="M85">
<owner>nyquist@chromium.org</owner> <owner>nyquist@chromium.org</owner>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment