Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(424)

Side by Side Diff: chrome/browser/ui/webui/ntp/ntp_user_data_logger.cc

Issue 2124903003: Record impressions/navigations only once per tile. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/webui/ntp/ntp_user_data_logger.h" 5 #include "chrome/browser/ui/webui/ntp/ntp_user_data_logger.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/strings/stringprintf.h" 11 #include "base/strings/stringprintf.h"
12 #include "chrome/browser/after_startup_task_utils.h" 12 #include "chrome/browser/after_startup_task_utils.h"
13 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/search/search.h" 14 #include "chrome/browser/search/search.h"
15 #include "chrome/browser/sync/profile_sync_service_factory.h" 15 #include "chrome/browser/sync/profile_sync_service_factory.h"
16 #include "chrome/common/search/search_urls.h" 16 #include "chrome/common/search/search_urls.h"
17 #include "chrome/common/url_constants.h" 17 #include "chrome/common/url_constants.h"
18 #include "components/browser_sync/browser/profile_sync_service.h" 18 #include "components/browser_sync/browser/profile_sync_service.h"
19 #include "components/sync_sessions/sessions_sync_manager.h" 19 #include "components/sync_sessions/sessions_sync_manager.h"
20 #include "components/sync_sessions/sync_sessions_metrics.h" 20 #include "components/sync_sessions/sync_sessions_metrics.h"
21 #include "content/public/browser/navigation_details.h" 21 #include "content/public/browser/navigation_details.h"
22 #include "content/public/browser/navigation_entry.h" 22 #include "content/public/browser/navigation_entry.h"
23 #include "content/public/browser/user_metrics.h" 23 #include "content/public/browser/user_metrics.h"
24 #include "content/public/browser/web_contents.h" 24 #include "content/public/browser/web_contents.h"
25 25
26 namespace { 26 namespace {
27 27
28 // Number of Most Visited elements on the NTP for logging purposes.
29 const int kNumMostVisited = 8;
30
31 // Name of the histogram keeping track of suggestion impressions. 28 // Name of the histogram keeping track of suggestion impressions.
32 const char kMostVisitedImpressionHistogramName[] = 29 const char kMostVisitedImpressionHistogramName[] =
33 "NewTabPage.SuggestionsImpression"; 30 "NewTabPage.SuggestionsImpression";
34 31
35 // Format string to generate the name for the histogram keeping track of 32 // Format string to generate the name for the histogram keeping track of
36 // suggestion impressions. 33 // suggestion impressions.
37 const char kMostVisitedImpressionHistogramWithProvider[] = 34 const char kMostVisitedImpressionHistogramWithProvider[] =
38 "NewTabPage.SuggestionsImpression.%s"; 35 "NewTabPage.SuggestionsImpression.%s";
39 36
40 // Name of the histogram keeping track of suggestion navigations. 37 // Name of the histogram keeping track of suggestion navigations.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 if (counter) 71 if (counter)
75 counter->AddTime(value); 72 counter->AddTime(value);
76 } 73 }
77 74
78 75
79 NTPUserDataLogger::~NTPUserDataLogger() {} 76 NTPUserDataLogger::~NTPUserDataLogger() {}
80 77
81 // static 78 // static
82 NTPUserDataLogger* NTPUserDataLogger::GetOrCreateFromWebContents( 79 NTPUserDataLogger* NTPUserDataLogger::GetOrCreateFromWebContents(
83 content::WebContents* content) { 80 content::WebContents* content) {
81 DCHECK(search::IsInstantNTP(content));
82
84 // Calling CreateForWebContents when an instance is already attached has no 83 // Calling CreateForWebContents when an instance is already attached has no
85 // effect, so we can do this. 84 // effect, so we can do this.
86 NTPUserDataLogger::CreateForWebContents(content); 85 NTPUserDataLogger::CreateForWebContents(content);
87 NTPUserDataLogger* logger = NTPUserDataLogger::FromWebContents(content); 86 NTPUserDataLogger* logger = NTPUserDataLogger::FromWebContents(content);
88 87
89 // We record the URL of this NTP in order to identify navigations that 88 // We record the URL of this NTP in order to identify navigations that
90 // originate from it. We use the NavigationController's URL since it might 89 // originate from it. We use the NavigationController's URL since it might
91 // differ from the WebContents URL which is usually chrome://newtab/. 90 // differ from the WebContents URL which is usually chrome://newtab/.
91 //
92 // We update the NTP URL every time this function is called, because the NTP
93 // URL sometimes changes while it is open, and we care about the final one for
94 // detecting when the user leaves or returns to the NTP. In particular, if the
95 // Google URL changes (e.g. google.com -> google.de), then we fall back to the
96 // local NTP.
92 const content::NavigationEntry* entry = 97 const content::NavigationEntry* entry =
93 content->GetController().GetVisibleEntry(); 98 content->GetController().GetVisibleEntry();
94 if (entry) 99 if (entry && (logger->ntp_url_ != entry->GetURL())) {
100 DVLOG(1) << "NTP URL changed from \"" << logger->ntp_url_ << "\" to \""
101 << entry->GetURL() << "\"";
95 logger->ntp_url_ = entry->GetURL(); 102 logger->ntp_url_ = entry->GetURL();
103 }
96 104
97 return logger; 105 return logger;
98 } 106 }
99 107
100 void NTPUserDataLogger::LogEvent(NTPLoggingEventType event, 108 void NTPUserDataLogger::LogEvent(NTPLoggingEventType event,
101 base::TimeDelta time) { 109 base::TimeDelta time) {
102 switch (event) { 110 switch (event) {
103 case NTP_SERVER_SIDE_SUGGESTION: 111 case NTP_SERVER_SIDE_SUGGESTION:
104 has_server_side_suggestions_ = true; 112 has_server_side_suggestions_ = true;
105 break; 113 break;
(...skipping 10 matching lines...) Expand all
116 case NTP_ALL_TILES_LOADED: 124 case NTP_ALL_TILES_LOADED:
117 EmitNtpStatistics(time); 125 EmitNtpStatistics(time);
118 break; 126 break;
119 default: 127 default:
120 NOTREACHED(); 128 NOTREACHED();
121 } 129 }
122 } 130 }
123 131
124 void NTPUserDataLogger::LogMostVisitedImpression( 132 void NTPUserDataLogger::LogMostVisitedImpression(
125 int position, NTPLoggingTileSource tile_source) { 133 int position, NTPLoggingTileSource tile_source) {
134 if ((position >= kNumMostVisited) || (impression_was_logged_[position])) {
Marc Treib 2016/07/15 11:47:37 optional nit: no parens required around impression
135 return;
136 }
137 impression_was_logged_[position] = true;
138
126 UMA_HISTOGRAM_ENUMERATION(kMostVisitedImpressionHistogramName, position, 139 UMA_HISTOGRAM_ENUMERATION(kMostVisitedImpressionHistogramName, position,
127 kNumMostVisited); 140 kNumMostVisited);
128 141
129 // Cannot rely on UMA histograms macro because the name of the histogram is 142 // Cannot rely on UMA histograms macro because the name of the histogram is
130 // generated dynamically. 143 // generated dynamically.
131 base::HistogramBase* counter = base::LinearHistogram::FactoryGet( 144 base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
132 base::StringPrintf(kMostVisitedImpressionHistogramWithProvider, 145 base::StringPrintf(kMostVisitedImpressionHistogramWithProvider,
133 GetSourceName(tile_source).c_str()), 146 GetSourceName(tile_source).c_str()),
134 1, 147 1,
135 kNumMostVisited, 148 kNumMostVisited,
(...skipping 17 matching lines...) Expand all
153 kNumMostVisited + 1, 166 kNumMostVisited + 1,
154 base::Histogram::kUmaTargetedHistogramFlag); 167 base::Histogram::kUmaTargetedHistogramFlag);
155 counter->Add(position); 168 counter->Add(position);
156 169
157 // Records the action. This will be available as a time-stamped stream 170 // Records the action. This will be available as a time-stamped stream
158 // server-side and can be used to compute time-to-long-dwell. 171 // server-side and can be used to compute time-to-long-dwell.
159 content::RecordAction(base::UserMetricsAction("MostVisited_Clicked")); 172 content::RecordAction(base::UserMetricsAction("MostVisited_Clicked"));
160 } 173 }
161 174
162 NTPUserDataLogger::NTPUserDataLogger(content::WebContents* contents) 175 NTPUserDataLogger::NTPUserDataLogger(content::WebContents* contents)
163 : has_server_side_suggestions_(false), 176 : content::WebContentsObserver(contents),
177 has_server_side_suggestions_(false),
164 has_client_side_suggestions_(false), 178 has_client_side_suggestions_(false),
165 number_of_tiles_(0), 179 number_of_tiles_(0),
166 has_emitted_(false), 180 has_emitted_(false),
167 during_startup_(false) { 181 during_startup_(false) {
168 during_startup_ = !AfterStartupTaskUtils::IsBrowserStartupComplete(); 182 during_startup_ = !AfterStartupTaskUtils::IsBrowserStartupComplete();
169 183
170 // We record metrics about session data here because when this class typically 184 // We record metrics about session data here because when this class typically
171 // emits metrics it is too late. This session data would theoretically have 185 // emits metrics it is too late. This session data would theoretically have
172 // been used to populate the page, and we want to learn about its state when 186 // been used to populate the page, and we want to learn about its state when
173 // the NTP is being generated. 187 // the NTP is being generated.
174 if (contents) { 188 if (contents) {
175 ProfileSyncService* sync = ProfileSyncServiceFactory::GetForProfile( 189 ProfileSyncService* sync = ProfileSyncServiceFactory::GetForProfile(
176 Profile::FromBrowserContext(contents->GetBrowserContext())); 190 Profile::FromBrowserContext(contents->GetBrowserContext()));
177 if (sync) { 191 if (sync) {
178 browser_sync::SessionsSyncManager* sessions = 192 browser_sync::SessionsSyncManager* sessions =
179 static_cast<browser_sync::SessionsSyncManager*>( 193 static_cast<browser_sync::SessionsSyncManager*>(
180 sync->GetSessionsSyncableService()); 194 sync->GetSessionsSyncableService());
181 if (sessions) { 195 if (sessions) {
182 sync_sessions::SyncSessionsMetrics::RecordYoungestForeignTabAgeOnNTP( 196 sync_sessions::SyncSessionsMetrics::RecordYoungestForeignTabAgeOnNTP(
183 sessions); 197 sessions);
184 } 198 }
185 } 199 }
186 } 200 }
187 } 201 }
188 202
203 // content::WebContentsObserver override
204 void NTPUserDataLogger::NavigationEntryCommitted(
205 const content::LoadCommittedDetails& load_details) {
206 NavigatedFromURLToURL(load_details.previous_url,
207 load_details.entry->GetURL());
208 }
209
210 void NTPUserDataLogger::NavigatedFromURLToURL(const GURL& from,
211 const GURL& to) {
212 // User is returning to NTP, probably via the back button; reset stats.
213 if (from.is_valid() && to.is_valid() && (to == ntp_url_)) {
214 DVLOG(1) << "Returning to New Tab Page";
215 impression_was_logged_.reset();
216 has_emitted_ = false;
217 number_of_tiles_ = 0;
218 has_server_side_suggestions_ = false;
219 has_client_side_suggestions_ = false;
220 }
221 }
222
189 void NTPUserDataLogger::EmitNtpStatistics(base::TimeDelta load_time) { 223 void NTPUserDataLogger::EmitNtpStatistics(base::TimeDelta load_time) {
190 // We only send statistics once per page. 224 // We only send statistics once per page.
191 if (has_emitted_) 225 if (has_emitted_)
192 return; 226 return;
227 DVLOG(1) << "Emitting NTP load time: " << load_time << ", "
228 << "number of tiles: " << number_of_tiles_;
193 229
194 logLoadTimeHistogram("NewTabPage.LoadTime", load_time); 230 logLoadTimeHistogram("NewTabPage.LoadTime", load_time);
195 231
196 // Split between ML and MV. 232 // Split between ML and MV.
197 std::string type = has_server_side_suggestions_ ? 233 std::string type = has_server_side_suggestions_ ?
198 "MostLikely" : "MostVisited"; 234 "MostLikely" : "MostVisited";
199 logLoadTimeHistogram("NewTabPage.LoadTime." + type, load_time); 235 logLoadTimeHistogram("NewTabPage.LoadTime." + type, load_time);
200 // Split between Web and Local. 236 // Split between Web and Local.
201 std::string source = ntp_url_.SchemeIsHTTPOrHTTPS() ? "Web" : "LocalNTP"; 237 std::string source = ntp_url_.SchemeIsHTTPOrHTTPS() ? "Web" : "LocalNTP";
202 logLoadTimeHistogram("NewTabPage.LoadTime." + source, load_time); 238 logLoadTimeHistogram("NewTabPage.LoadTime." + source, load_time);
203 239
204 // Split between Startup and non-startup. 240 // Split between Startup and non-startup.
205 std::string status = during_startup_ ? "Startup" : "NewTab"; 241 std::string status = during_startup_ ? "Startup" : "NewTab";
206 logLoadTimeHistogram("NewTabPage.LoadTime." + status, load_time); 242 logLoadTimeHistogram("NewTabPage.LoadTime." + status, load_time);
207 243
208 has_server_side_suggestions_ = false; 244 has_server_side_suggestions_ = false;
209 has_client_side_suggestions_ = false; 245 has_client_side_suggestions_ = false;
210 UMA_HISTOGRAM_CUSTOM_COUNTS( 246 UMA_HISTOGRAM_CUSTOM_COUNTS(
211 "NewTabPage.NumberOfTiles", number_of_tiles_, 0, kNumMostVisited, 247 "NewTabPage.NumberOfTiles", number_of_tiles_, 0, kNumMostVisited,
212 kNumMostVisited + 1); 248 kNumMostVisited + 1);
213 number_of_tiles_ = 0; 249 number_of_tiles_ = 0;
214 has_emitted_ = true; 250 has_emitted_ = true;
215 during_startup_ = false; 251 during_startup_ = false;
216 } 252 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/webui/ntp/ntp_user_data_logger.h ('k') | chrome/browser/ui/webui/ntp/ntp_user_data_logger_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698