Skip to content

Commit

Permalink
Bug 1672763 - Telemetry for Pocket button. r=gvn
Browse files Browse the repository at this point in the history
  • Loading branch information
ScottDowne committed Nov 13, 2020
1 parent b9e19e2 commit 4819c09
Show file tree
Hide file tree
Showing 12 changed files with 318 additions and 113 deletions.
7 changes: 4 additions & 3 deletions browser/components/newtab/docs/v2-system-addon/data_events.md
Original file line number Diff line number Diff line change
Expand Up @@ -723,11 +723,11 @@ This reports the user's interaction with those Pocket tiles.
}
```

## On Save Recs pings
## Save to Pocket button pings

Right now the save to Pocket button, while technically outside of newtab, has some similarities with the newtab telemetry.

These pings record user interaction with the recs we display in the doorhanger after you save a page using the Pocket button next to the address bar. This is not telemetry for the address bar save to Pocket button itself, just for the similar recs displayed in the doorhanger.
These pings record user interaction with the save to Pocket button.

### Click/impression ping

Expand All @@ -737,7 +737,8 @@ These pings record user interaction with the recs we display in the doorhanger a
"version": "83.0a1",
"release_channel": "default",
"model": "",
"events": [{"action":"click|impression","position":0}],
"events": [{"action":"click|impression|unpin","position":0,"source":"save_button|on_save_recs|learn_more|sign_up_1|sign_up_2|log_in"}],
"pocket_logged_in_state": true|false,
"impression_id": "{005deed0-e3e4-4c02-a041-17405fd703f6}",
"profile_creation_date": 18550
}
Expand Down
19 changes: 19 additions & 0 deletions browser/components/pocket/content/SaveToPocket.jsm
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ ChromeUtils.defineModuleGetter(
"AboutReaderParent",
"resource:///actors/AboutReaderParent.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"pktTelemetry",
"chrome://pocket/content/pktTelemetry.jsm"
);

var EXPORTED_SYMBOLS = ["SaveToPocket"];

Expand Down Expand Up @@ -110,6 +115,20 @@ var PocketPageAction = {
onLocationChange(browserWindow) {
PocketPageAction.updateUrlbarNodeState(browserWindow);
},
onPinToUrlbarToggled() {
if (!this.pinnedToUrlbar) {
const payload = pktTelemetry.createPingPayload({
events: [
{
action: "unpin",
source: "save_button",
},
],
});
// Send unpin event ping.
pktTelemetry.sendStructuredIngestionEvent(payload);
}
},
})
);
}
Expand Down
145 changes: 51 additions & 94 deletions browser/components/pocket/content/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,6 @@ ChromeUtils.defineModuleGetter(
"PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"PingCentre",
"resource:///modules/PingCentre.jsm"
);
XPCOMUtils.defineLazyGetter(this, "pingCentre", () => {
return new PingCentre({ topic: POCKET_TELEMETRY_TOPIC });
});
ChromeUtils.defineModuleGetter(
this,
"ReaderMode",
Expand All @@ -67,23 +59,14 @@ ChromeUtils.defineModuleGetter(
"pktApi",
"chrome://pocket/content/pktApi.jsm"
);
XPCOMUtils.defineLazyServiceGetters(this, {
gUUIDGenerator: ["@mozilla.org/uuid-generator;1", "nsIUUIDGenerator"],
});
XPCOMUtils.defineLazyModuleGetters(this, {
TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.jsm",
});

// List of namespaces for the structured ingestion system.
// They are defined in https://github.com/mozilla-services/mozilla-pipeline-schemas
const STRUCTURED_INGESTION_NAMESPACE_AS = "activity-stream";
const STRUCTURED_INGESTION_ENDPOINT_PREF =
"browser.newtabpage.activity-stream.telemetry.structuredIngestion.endpoint";
// This is the topic for telemetry pings, used inside PingCentre.
const POCKET_TELEMETRY_TOPIC = "pocket";
ChromeUtils.defineModuleGetter(
this,
"pktTelemetry",
"chrome://pocket/content/pktTelemetry.jsm"
);

const POCKET_ONSAVERECS_PREF = "extensions.pocket.onSaveRecs";
const POCKET_ONSAVERECS_LOCLES_PREF = "extensions.pocket.onSaveRecs.locales";
const PREF_IMPRESSION_ID = "browser.newtabpage.activity-stream.impressionId";

var pktUI = (function() {
// -- Initialization (on startup and new windows) -- //
Expand Down Expand Up @@ -112,73 +95,6 @@ var pktUI = (function() {
}
initPrefs();

// -- Telemetry API -- //

const structuredIngestionEndpointBase = Services.prefs.getStringPref(
STRUCTURED_INGESTION_ENDPOINT_PREF,
""
);

// Sets or gets the impression id that's use for Pocket impressions.
// The impression id cannot be tied to a client id.
// This is the same impression id used in newtab pocket impressions.
function getOrCreateImpressionId() {
let impressionId = Services.prefs.getStringPref(PREF_IMPRESSION_ID, "");

if (!impressionId) {
impressionId = String(gUUIDGenerator.generateUUID());
Services.prefs.setStringPref(PREF_IMPRESSION_ID, impressionId);
}
return impressionId;
}

const impressionId = getOrCreateImpressionId();

/**
* Generates an endpoint for Structured Ingestion telemetry pipeline. Note that
* Structured Ingestion requires a different endpoint for each ping. See more
* details about endpoint schema at:
* https://github.com/mozilla/gcp-ingestion/blob/master/docs/edge.md#postput-request
*/
function _generateStructuredIngestionEndpoint() {
const uuid = gUUIDGenerator.generateUUID().toString();
// Structured Ingestion does not support the UUID generated by gUUIDGenerator,
// because it contains leading and trailing braces. Need to trim them first.
const docID = uuid.slice(1, -1);
const extension = `${STRUCTURED_INGESTION_NAMESPACE_AS}/on-save-recs/1/${docID}`;
return `${structuredIngestionEndpointBase}/${extension}`;
}

/**
* createPingPayload - Create a ping for an impression stats
*
* @param {ob} data The data object to be included in the ping.
* @return {obj} A telemetry ping
*/
function createPingPayload(data) {
// experiments, locale, version, and release_channel are provided by pingCentre.
// model and events is provided in the data param.
return {
...data,
impression_id: impressionId,
profile_creation_date:
TelemetryEnvironment.currentEnvironment.profile.resetDate ||
TelemetryEnvironment.currentEnvironment.profile.creationDate,
};
}

/**
* sendStructuredIngestionEvent - Sent a ping for an impression stats
*
* @param {ob} eventObject The data object to be included in the ping.
*/
function sendStructuredIngestionEvent(eventObject) {
pingCentre.sendStructuredIngestionPing(
eventObject,
_generateStructuredIngestionEndpoint()
);
}

// -- Communication to API -- //

/**
Expand Down Expand Up @@ -266,6 +182,19 @@ var pktUI = (function() {
{
width: inOverflowMenu ? overflowMenuWidth : 300,
height: startheight,
onShow() {
// A successful button click, for logged out users.
pktTelemetry.sendStructuredIngestionEvent(
pktTelemetry.createPingPayload({
events: [
{
action: "click",
source: "save_button",
},
],
})
);
},
}
);
});
Expand Down Expand Up @@ -357,6 +286,18 @@ var pktUI = (function() {
return;
}

// A successful button click, for logged in users.
pktTelemetry.sendStructuredIngestionEvent(
pktTelemetry.createPingPayload({
events: [
{
action: "click",
source: "save_button",
},
],
})
);

// Add url
var options = {
success(data, request) {
Expand Down Expand Up @@ -386,7 +327,7 @@ var pktUI = (function() {
data
);
if (data?.recommendations?.[0]?.experiment) {
const payload = createPingPayload({
const payload = pktTelemetry.createPingPayload({
// This is the ML model used to recommend the story.
// Right now this value is the same for all three items returned together,
// so we can just use the first item's value for all.
Expand All @@ -395,10 +336,11 @@ var pktUI = (function() {
events: data.recommendations.map((item, index) => ({
action: "impression",
position: index,
source: "on_save_recs",
})),
});
// Send view impression ping.
sendStructuredIngestionEvent(payload);
pktTelemetry.sendStructuredIngestionEvent(payload);
}
},
});
Expand Down Expand Up @@ -546,6 +488,20 @@ var pktUI = (function() {
return;
}

// We don't track every click, only clicks with a known source.
if (data.source) {
const payload = pktTelemetry.createPingPayload({
events: [
{
action: "click",
source: data.source,
},
],
});
// Send click event ping.
pktTelemetry.sendStructuredIngestionEvent(payload);
}

var url = data.url;
openTabWithUrl(url, contentPrincipal, csp);
pktUIMessaging.sendResponseMessageToPanel(
Expand Down Expand Up @@ -575,17 +531,18 @@ var pktUI = (function() {
const { url, position, model } = data;
// Check to see if we need to and can fire valid telemetry.
if (model && (position || position === 0)) {
const payload = createPingPayload({
const payload = pktTelemetry.createPingPayload({
model,
events: [
{
action: "click",
position,
source: "on_save_recs",
},
],
});
// Send click event ping.
sendStructuredIngestionEvent(payload);
pktTelemetry.sendStructuredIngestionEvent(payload);
}

openTabWithUrl(url, contentPrincipal, csp);
Expand Down
37 changes: 35 additions & 2 deletions browser/components/pocket/content/panels/js/signup.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
PKT_SIGNUP_OVERLAY is the view itself and contains all of the methods to manipute the overlay and messaging.
It does not contain any logic for saving or communication with the extension or server.
*/

var PKT_SIGNUP_OVERLAY = function(options) {
var myself = this;
this.inited = false;
Expand All @@ -26,13 +27,45 @@ var PKT_SIGNUP_OVERLAY = function(options) {
this.loggedOutVariant = "control";
this.dictJSON = {};
this.initCloseTabEvents = function() {
$(".btn,.pkt_ext_learnmore,.alreadyhave > a").click(function(e) {
function clickHelper(e, linkData) {
e.preventDefault();
thePKT_SIGNUP.sendMessage("openTabWithUrl", {
url: $(this).attr("href"),
url: linkData.url,
activate: true,
source: linkData.source || "",
});
myself.closePopup();
}
$(".pkt_ext_learnmore").click(function(e) {
clickHelper(e, {
source: "learn_more",
url: $(this).attr("href"),
});
});
$(".signup-btn-firefox").click(function(e) {
clickHelper(e, {
source: "sign_up_1",
url: $(this).attr("href"),
});
});
$(".signup-btn-email").click(function(e) {
clickHelper(e, {
source: "sign_up_2",
url: $(this).attr("href"),
});
});
$(".pkt_ext_login").click(function(e) {
clickHelper(e, {
source: "log_in",
url: $(this).attr("href"),
});
});
// A generic click we don't do anything special for.
// Was used for an experiment, possibly not needed anymore.
$(".signup-btn-tryitnow").click(function(e) {
clickHelper(e, {
url: $(this).attr("href"),
});
});
};
this.closePopup = function() {
Expand Down
Loading

0 comments on commit 4819c09

Please sign in to comment.