From c50e1fa8d0bf50daec70efbfa1557c171d11ef80 Mon Sep 17 00:00:00 2001 From: Ian Bicking Date: Fri, 9 Nov 2018 15:55:14 -0600 Subject: [PATCH] Fixes #5067 - add custom dimension for login type to GA (#5152) * WIP update of #5067, add custom dimension for login type to GA * Update with accountId in metrics doc --- docs/METRICS.md | 17 ++++++++++++++--- server/src/ga-activation.js | 5 ++++- server/src/server.js | 22 +++++++++++++++++++--- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/docs/METRICS.md b/docs/METRICS.md index 1f7a92cb95..01cc79dcb9 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -10,13 +10,15 @@ This document is a summary of the metrics Firefox Screenshots will record, how w Additionally, it's important to recognize that Firefox Screenshots is an add-on in a browser as well as a server-side service. -## deviceId / user ID +## accountId / deviceId / user ID -Each device that uses Screenshots (browser, profile, computer) generates a random UUID ID. We call this the deviceId. In addition a random secret is generated. The two together are used to register and authenticate with the server. +Each device that takes Screenshots (browser, profile, computer) generates a random UUID ID. We call this the deviceId. In addition a random secret is generated. The two together are used to register and authenticate with the server. The deviceId is only registered with the screenshots.firefox.com server when the user first saves a shot. Starting Screenshots or downloading does not cause registration. -Each event is sent to the server with its deviceId. The server hashes this ID (combining it with a random server string that is rotated occasionally) before sending it to Google Analytics. This hashed ID is generally called `cid` (customer ID, a Google Analytics term). +An alternate way to authenticate with server is by successful signin to firefox account. An accountId which is a uid returned by fxa-auth-server is assigned once a user login with firefox account and its value is reset on signout from settings. + +Each event is sent to the server with its accountId or deviceId. The server hashes this ID (combining it with a random server string that is rotated occasionally) before sending it to Google Analytics. This hashed ID is generally called `cid` (customer ID, a Google Analytics term). For web page views (viewing and interacting with individual shots or My Shots) we serve up `/ga-activation.js` or `/ga-activation-hashed.js` (the latter for pages with private URLs). This file is generated *per user* and includes the `cid`, if the user is authenticated with the service. @@ -83,6 +85,15 @@ Event label: exactly what control invoked the action, such as toolbar-button. T * `selection`: anything that happens during the selection phase, that doesn't happen in the topbar * `keyboard`: any keyboard shortcut used +#### Login status custom dimension + +The `cd9` dimension holds the "login type". The values can be: + +* `non-login`: visitor is not logged in +* `extension`: logged in via the extension, with no FxA login +* `extension-fxa`: logged in via the extension, With a FxA login +* `browser-fxa`: using a non-Firefox browser, with a FxA login + #### A/B tests ##### Test alternate share panel diff --git a/server/src/ga-activation.js b/server/src/ga-activation.js index 0c13825958..bd0740cdca 100644 --- a/server/src/ga-activation.js +++ b/server/src/ga-activation.js @@ -133,6 +133,7 @@ const gaJs = ` window.sendEvent = function (action, label, options) { var event = "web"; + var loginType = "__LOGIN_TYPE__" || null; if (typeof label == "object") { if (options) { console.error("Error: got label and options"); @@ -146,6 +147,7 @@ window.sendEvent = function (action, label, options) { options[window.abTests[testName].gaField] = window.abTests[testName].value; } } + options.cd9 = loginType; console.debug("sendEvent", event + "/" + action + (label ? "/" + label : "") || "none", options || "no-options"); ga("send", "event", event, action, label, options); }; @@ -153,7 +155,7 @@ window.sendEvent = function (action, label, options) { const idRegex = /^[a-zA-Z0-9_.,-]{1,1000}$/; -exports.makeGaActivationString = function(gaId, userId, abTests, hashLocation) { +exports.makeGaActivationString = function({gaId, userId, abTests, hashLocation, loginType}) { if (gaId === "") { // Don't enable ga if no id was provided return stubGaJs.replace(/__ABTESTS__/g, JSON.stringify(abTests)); @@ -171,5 +173,6 @@ exports.makeGaActivationString = function(gaId, userId, abTests, hashLocation) { let script = gaJs.replace(/__GA_ID__/g, gaId).replace(/__USER_ID__/g, userId); script = script.replace(/__HASH_LOCATION__/g, hashLocation ? "true" : "false"); script = script.replace(/__ABTESTS__/g, JSON.stringify(abTests)); + script = script.replace(/__LOGIN_TYPE__/g, loginType || ""); return script; }; diff --git a/server/src/server.js b/server/src/server.js index 01ee1dfda1..608bb59040 100644 --- a/server/src/server.js +++ b/server/src/server.js @@ -328,16 +328,32 @@ app.get("/ga-activation-hashed.js", function(req, res) { function sendGaActivation(req, res, hashPage) { let promise; + let loginType = "non-login"; + if (req.accountId) { + if (req.deviceId) { + loginType = "extension-fxa"; + } else { + loginType = "browser-fxa"; + } + } else if (req.deviceId) { + loginType = "extension"; + } setMonthlyCache(res, {private: true}); - if (req.deviceId) { - promise = hashUserId(req.deviceId).then((uuid) => { + if (req.accountId || req.deviceId) { + promise = hashUserId(req.accountId || req.deviceId).then((uuid) => { return uuid.toString(); }); } else { promise = Promise.resolve(""); } promise.then((userUuid) => { - const script = gaActivation.makeGaActivationString(config.gaId, userUuid, req.abTests, hashPage); + const script = gaActivation.makeGaActivationString({ + gaId: config.gaId, + userId: userUuid, + abTests: req.abTests, + hashLocation: hashPage, + loginType, + }); jsResponse(res, script); }).catch((e) => { errorResponse(res, "Error creating user UUID:", e);