Bug 1413830 - PART 4: send bubble_state;r=fischer,francois draft
authorFred Lin <gasolin@gmail.com>
Wed, 22 Nov 2017 09:56:44 +0800
changeset 703623 678f8dcea68a436b8f0376ab9684819075db63b2
parent 703622 a861f884c78b223d28fd8028ee7a7c5908749835
child 741839 41778908168b003910e43844102342465db612e9
push id90891
push userbmo:gasolin@mozilla.com
push dateMon, 27 Nov 2017 07:51:07 +0000
reviewersfischer, francois
bugs1413830
milestone59.0a1
Bug 1413830 - PART 4: send bubble_state;r=fischer,francois MozReview-Commit-ID: LZkT7p1SHQy
browser/extensions/onboarding/OnboardingTelemetry.jsm
browser/extensions/onboarding/content/onboarding.js
browser/extensions/onboarding/data_events.md
--- a/browser/extensions/onboarding/OnboardingTelemetry.jsm
+++ b/browser/extensions/onboarding/OnboardingTelemetry.jsm
@@ -129,53 +129,58 @@ const BASIC_EVENT_SCHEMA = {
  * To save server space and make query easier, we track session begin and end but only send pings
  * when session end. Therefore the server will get single "onboarding/overlay/notification-session"
  * event which includes both `session_begin` and `session_end` timestamp.
  *
  * We send `session_begin` and `session_end` timestamps instead of `session_duration` diff because
  * of analytics engineer's request.
  */
 const EVENT_WHITELIST = {
+  // track when bubble class is added
+  "bubble-class-added": {topic: "internal"},
   // track when a notification appears.
   "notification-appear": {
     topic: "firefox-onboarding-event2",
     category: "notification-interactions",
     parent: "notification",
+    sendBubbleState: true,
     sendLogoState: true,
     sendNotificationImpression: true,
     validators: Object.assign({}, BASIC_EVENT_SCHEMA, {
       bubble_state: isValidBubbleState,
       current_tour_id: hasString,
       logo_state: isValidLogoState,
       notification_impression: isPositiveInteger,
       notification_state: isValidNotificationState,
       target_tour_id: isEmptyString,
     }),
   },
   // track when a user clicks close notification button
   "notification-close-button-click": {
     topic: "firefox-onboarding-event2",
     category: "notification-interactions",
     parent: "notification",
+    sendBubbleState: true,
     sendLogoState: true,
     sendNotificationImpression: true,
     validators: Object.assign({}, BASIC_EVENT_SCHEMA, {
       bubble_state: isValidBubbleState,
       current_tour_id: hasString,
       logo_state: isValidLogoState,
       notification_impression: isPositiveInteger,
       notification_state: isValidNotificationState,
       target_tour_id: hasString,
     }),
   },
   // track when a user clicks notification's Call-To-Action button
   "notification-cta-click": {
     topic: "firefox-onboarding-event2",
     category: "notification-interactions",
     parent: "notification",
+    sendBubbleState: true,
     sendLogoState: true,
     sendNotificationImpression: true,
     validators: Object.assign({}, BASIC_EVENT_SCHEMA, {
       bubble_state: isValidBubbleState,
       current_tour_id: hasString,
       logo_state: isValidLogoState,
       notification_impression: isPositiveInteger,
       notification_state: isValidNotificationState,
@@ -197,16 +202,17 @@ const EVENT_WHITELIST = {
   "notification-session-begin": {topic: "internal"},
   // track the end of a notification
   "notification-session-end": {topic: "internal"},
   // track when a user clicks the Firefox logo
   "onboarding-logo-click": {
     topic: "firefox-onboarding-event2",
     category: "logo-interactions",
     parent: "onboarding",
+    sendBubbleState: true,
     sendLogoState: true,
     sendNotificationState: true,
     validators: Object.assign({}, BASIC_EVENT_SCHEMA, {
       bubble_state: isValidBubbleState,
       current_tour_id: isEmptyString,
       logo_state: isValidLogoState,
       notification_impression: isMinusOne,
       notification_state: isValidNotificationState,
@@ -340,16 +346,18 @@ const EVENT_WHITELIST = {
       bubble_state: isEmptyString,
       current_tour_id: hasString,
       logo_state: isEmptyString,
       notification_impression: isMinusOne,
       notification_state: isEmptyString,
       target_tour_id: isEmptyString,
     }),
   },
+  // track when watermark class is added
+  "watermark-class-added": {topic: "internal"},
 };
 
 /**
  * We send 2 kinds (firefox-onboarding-event, firefox-onboarding-session) of pings to ping centre
  * server (they call it `topic`). The `internal` state in `topic` field means this event is used internaly to
  * track states and will not send out any message.
  *
  * To save server space and make query easier, we track session begin and end but only send pings
@@ -430,16 +438,17 @@ let OnboardingTelemetry = {
       return;
     }
     // session_key and page url are must have
     if (!session_key || !page || !tour_type) {
       throw new Error("session_key, page url, and tour_type are required for onboarding-register-session");
     }
     let onboarding_session_id = gUUIDGenerator.generateUUID().toString();
     this.state.sessions[session_key] = {
+      bubble_state: "bubble",
       onboarding_session_id,
       overlay_session_id: "",
       notification_session_id: "",
       notification_state: "hide",
       page,
       tour_type,
     };
   },
@@ -464,16 +473,19 @@ let OnboardingTelemetry = {
     }
 
     if (!this.state.sessions[session_key]) {
       throw new Error(`should pass valid session_key`);
     }
 
     if (topic === "internal") {
       switch (event) {
+        case "bubble-class-added":
+          this.state.sessions[session_key].bubble_state = "bubble";
+          break;
         case "onboarding-session-begin":
           this.state.sessions[session_key].onboarding_session_begin = Date.now();
           break;
         case "onboarding-session-end":
           data.event = "onboarding-session";
           this._sendPing("firefox-onboarding-session2", data);
           break;
         case "overlay-session-begin":
@@ -485,25 +497,29 @@ let OnboardingTelemetry = {
           this._sendPing("firefox-onboarding-session2", data);
           break;
         case "notification-finished":
           this.state.sessions[session_key].notification_state = "finished";
           break;
         case "notification-hide":
           this.state.sessions[session_key].notification_state = "hide";
           break;
-        case "notification-session-begin":
+          case "notification-session-begin":
           this.state.sessions[session_key].notification_session_id = gUUIDGenerator.generateUUID().toString();
           this.state.sessions[session_key].notification_session_begin = Date.now();
           this.state.sessions[session_key].notification_state = "show";
+          this.state.sessions[session_key].bubble_state = "dot";
           break;
         case "notification-session-end":
           data.event = "notification-session";
           this._sendPing("firefox-onboarding-session2", data);
           break;
+        case "watermark-class-added":
+          this.state.sessions[session_key].bubble_state = "hide";
+          break;
       }
     } else {
       this._sendPing(topic, data);
     }
   },
 
   // send out pings by topic
   _sendPing(topic, data) {
@@ -513,29 +529,31 @@ let OnboardingTelemetry = {
     let {
       current_tour_id = "",
       event,
       session_key,
       target_tour_id = "",
       width,
     } = data;
     let {
+      bubble_state,
       notification_session_begin,
       notification_session_id,
       notification_state,
       onboarding_session_begin,
       onboarding_session_id,
       overlay_session_begin,
       overlay_session_id,
       page,
       tour_type,
     } = this.state.sessions[session_key];
     let {
       category,
       parent,
+      sendBubbleState,
       sendLogoState,
       sendNotificationImpression,
       sendNotificationState,
     } = EVENT_WHITELIST[event];
     let session_begin;
     let payload;
     let session_id;
     let root_session_id = onboarding_session_id;
@@ -618,16 +636,17 @@ let OnboardingTelemetry = {
           // the field is used to identify how user open the overlay (through default logo or watermark),
           // the number of open from notification can be retrieved via `notification-cta-click` event
           let logo_state = Services.prefs.getStringPref("browser.onboarding.state", "default");
           payload.logo_state = logo_state === "default" ? "logo" : logo_state;
         } else {
           payload.logo_state = "";
         }
         payload.notification_state = sendNotificationState ? notification_state : "";
+        payload.bubble_state = sendBubbleState ? bubble_state : "";
         this._validatePayload(payload);
         this.eventProbe && this.eventProbe.sendPing(payload,
           {filter: ONBOARDING_ID});
         break;
     }
   },
 
   processOldPings(data) {
--- a/browser/extensions/onboarding/content/onboarding.js
+++ b/browser/extensions/onboarding/content/onboarding.js
@@ -418,16 +418,20 @@ class Onboarding {
       // Don't show the overlay UI before we get to a better, responsive design.
       this.destroy();
       return;
     }
 
     this._initUI();
     if (this._isFirstSession && this.width >= SPEECH_BUBBLE_MIN_WIDTH_PX) {
       this._overlayIcon.classList.add("onboarding-speech-bubble");
+      telemetry({
+        event: "bubble-class-added",
+        session_key: this._session_key,
+      });
     } else {
       this._overlayIcon.classList.remove("onboarding-speech-bubble");
     }
   }
 
   _initUI() {
     if (this.uiInitialized) {
       return;
@@ -781,16 +785,20 @@ class Onboarding {
 
   _onIconStateChange(state) {
     switch (state) {
       case ICON_STATE_DEFAULT:
         this._overlayIcon.classList.remove("onboarding-watermark");
         break;
       case ICON_STATE_WATERMARK:
         this._overlayIcon.classList.add("onboarding-watermark");
+        telemetry({
+          event: "watermark-class-added",
+          session_key: this._session_key,
+        });
         break;
     }
     return true;
   }
 
   showOverlay() {
     if (this._tourItems.length == 0) {
       // Lazy loading until first toggle.
--- a/browser/extensions/onboarding/data_events.md
+++ b/browser/extensions/onboarding/data_events.md
@@ -54,16 +54,17 @@ For reference, Onyx is a Mozilla owned s
 | `ua` | [Auto populated by Onyx] The user agent string. | :two:
 | `ver` | [Auto populated by Onyx] The version of the Onyx API the ping was sent to. | :one:
 
 # Example Onboarding `event` Log
 
 ```js
 {
   "addon_version": "1.0.0",
+  "bubble_state": ["bubble" | "dot" | "hide"],
   "category": ["logo-interactions"|"overlay-interactions"|"notification-interactions"],
   "client_id": "374dc4d8-0cb2-4ac5-a3cf-c5a9bc3c602e",
   "locale": "en-US",
   "logo_state": ["logo" | "watermark"],
   "notification_impression": [1-8],
   "notification_state": ["show" | "hide" | "finished"],
   "page": ["about:newtab" | "about:home"],
   "parent_session_id": "{45cddbeb-2bec-4f3a-bada-fb87d4b79a6c}",
@@ -83,16 +84,17 @@ For reference, Onyx is a Mozilla owned s
   "date": "2016-03-07",
 }
 ```
 
 
 | KEY | DESCRIPTION | &nbsp; |
 |-----|-------------|:-----:|
 | `addon_version` | [Required] The version of the Onboarding addon. | :one:
+| `bubble_state` | [Optional] | One of ["bubble", "dot", "hide"] indicates the current visual state of the speach bubble (content dialog besides the onboarding logo). | :one:
 | `category` | [Required] Either ("overlay-interactions", "notification-interactions") to identify which kind of the interaction | :one:
 | `client_id` | [Required] An identifier generated by [ClientID](https://github.com/mozilla/gecko-dev/blob/master/toolkit/modules/ClientID.jsm) module to provide an identifier for this device. This data is automatically appended by `ping-centre` module | :one:
 | `current_tour_id` | [Optional] id of the current tour. The number of open from notification can be retrieved via 'notification-cta-click event'. We put "" when this field is not relevant to this event | :one:
 | `ip` | [Auto populated by Onyx] The IP address of the client. Onyx does use (with the permission) the IP address to infer user's geo-information so that it could prepare the corresponding tiles for the country she lives in. However, Ping-centre will NOT store IP address in the database, where only authorized Mozilla employees can access the telemetry data, and all the raw logs are being strictly managed by the Ops team and will expire according to the Mozilla's data retention policy.| :two:
 | `locale` | The browser chrome's language (e.g. en-US). | :two:
 | `logo_state` | [Optional] One of ["logo", "watermark"] indicates the overlay is opened while in the default or the watermark state. Open from the notification bar is counted via 'notification-cta-click event'. | :one:
 | `notification_impression` | [Optional] An integer to record how many times the current notification tour is shown to the user. Each Notification tour can show not more than 8 times. We put `-1` when this field is not relevant to this event | :one:
 | `notification_state` | [Optional] One of ["show", "hide", "finished"] indicates the current notification bar state. | :one:
@@ -123,18 +125,20 @@ Here are all allowed event `type` string
 | `onboarding-session` | event is sent when the tab unload to track the start and end time of the onboarding session. |
 | `onboarding-session-begin` | internal event triggered when the onboarding starts, will not send out any data. |
 | `onboarding-session-end` | internal event triggered when the onboarding ends, `onboarding-session` event is the actual event that send to the server. |
 
 ### Onboarding events
 
 | EVENT | DESCRIPTION |
 |-----------|---------------------|
+| `bubble-class-added` | internal event triggered when add `onboarding-speech-bubble` class to the overlay icon. |
 | `onboarding-logo-click` | event is triggered when a user clicks the logo to open the overlay. |
 | `onboarding-register-session` | internal event triggered when loading the onboarding module, will not send out any data. |
+| `watermark-class-added` | internal event triggered when add `onboarding-watermark` class to the overlay icon. |
 
 ### Overlay events
 
 | EVENT | DESCRIPTION |
 |-----------|---------------------|
 | `overlay-close-button-click` | event is triggered when a user clicks close overlay button. |
 | `overlay-close-outside-click` | event is triggered when a user clicks outside the overlay area to end the tour. |
 | `overlay-cta-click` | event is triggered when a user clicks overlay's Call-To-Action button. |