forked from bwinton/SnoozeTabs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Initial implementation of metrics pings
* Create `lib/metrics.js` to organize metrics pings & tab state tracking * Add metrics pings to `background.js` * Include time option type ID in snoozed tab data for `snooze` event * Include tab ID in snoozed tab data when snoozed for `resnooze` event * Add first draft of docs/metrics.md * Tests for `lib/metrics.js` Fixes bwinton#45. Fixes bwinton#46.
- Loading branch information
Showing
6 changed files
with
365 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
# METRICS | ||
|
||
## Data Analysis | ||
|
||
The collected data will primarily be used to answer the following questions. | ||
Images are used for visualization and are not composed of actual data. | ||
|
||
### Do people use this? | ||
|
||
What is the overall engagement of Snooze Tabs? **This is the standard Daily | ||
Active User (DAU) and Monthly Active User (MAU) analysis.** This captures data | ||
from the people who have the add-on installed, regardless of whether they are | ||
actively interacting with it. | ||
|
||
### Immediate Questions | ||
|
||
TBD | ||
|
||
### Follow-up Questions | ||
|
||
TBD | ||
|
||
## Data Collection | ||
|
||
### Server Side | ||
There is currently no server side component to Snooze Tabs. | ||
|
||
### Client Side | ||
Snooze Tabs will use Test Pilot's Telemetry wrapper with no batching of data. | ||
Details of when pings are sent are below, along with examples of the `payload` | ||
portion of a `testpilottest` telemetry ping for each scenario. | ||
|
||
* The user opens the snooze panel | ||
```js | ||
{ "event": "panel-opened" } | ||
``` | ||
|
||
* The user snoozes a tab, choosing either a pre-defined time or a custom time | ||
```js | ||
{ | ||
"event": "snoozed", | ||
"snooze_time": 1484345836165, | ||
"snooze_time_type": "tomorrow" | ||
} | ||
``` | ||
|
||
* A snoozed tab wakes up as a live tab | ||
```js | ||
{ | ||
"event": "woken", | ||
"snooze_time": 1484345836165, | ||
"snooze_time_type": "tomorrow" | ||
} | ||
``` | ||
|
||
* A previously snoozed tab is focused | ||
```js | ||
{ | ||
"event": "focused", | ||
"snooze_time": 1484345836165, | ||
"snooze_time_type": "tomorrow" | ||
} | ||
``` | ||
|
||
* A previously snoozed tab is closed without having been focused | ||
```js | ||
{ | ||
"event": "closed-unfocused", | ||
"snooze_time": 1484345836165, | ||
"snooze_time_type": "tomorrow" | ||
} | ||
``` | ||
|
||
* A previously snoozed tab is snoozed again after waking | ||
```js | ||
{ | ||
"event": "resnoozed", | ||
"snooze_time": 1484345836165, | ||
"snooze_time_type": "tomorrow" | ||
} | ||
``` | ||
|
||
* A snoozed tab is cancelled from the management panel | ||
```js | ||
{ | ||
"event": "cancelled", | ||
"snooze_time": 1484345836165, | ||
"snooze_time_type": "tomorrow" | ||
} | ||
``` | ||
|
||
* A snoozed tab is clicked from the management panel | ||
```js | ||
{ | ||
"event": "clicked", | ||
"snooze_time": 1484345836165, | ||
"snooze_time_type": "tomorrow" | ||
} | ||
``` | ||
|
||
A Redshift schema for the payload: | ||
|
||
```lua | ||
local schema = { | ||
-- column name field type length attributes field name | ||
{"event", "VARCHAR", 255, nil, "Fields[payload.event]"}, | ||
{"snooze_time", "INTEGER", nil, nil, "Fields[payload.snooze_time]"}, | ||
{"snooze_time_type", "VARCHAR", 255, nil, "Fields[payload.snooze_time_type]"}, | ||
} | ||
``` | ||
|
||
All Mozilla data is kept by default for 180 days and in accordance with our | ||
privacy policies. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,99 @@ | ||
// Track recent tabs woken to see whether they're later closed or focused | ||
let unseenWakeHistory = {}; | ||
let seenWakeHistory = {}; | ||
|
||
// BroadcastChannel for sending metrics pings to Test Pilot add-on | ||
let pingChannel = null; | ||
|
||
// Name of the metrics BroadcastChannel expected by the Test Pilot add-on | ||
const TESTPILOT_TELEMETRY_CHANNEL = 'testpilot-telemetry' | ||
|
||
const DEBUG = (process.env.NODE_ENV === 'development'); | ||
|
||
function log(...args) { | ||
if (DEBUG) { console.log('SnoozeTabs (Metrics):', ...args); } // eslint-disable-line no-console | ||
} | ||
|
||
export default { | ||
init(BroadcastChannel, tabs) { | ||
unseenWakeHistory = {}; | ||
seenWakeHistory = {}; | ||
pingChannel = new BroadcastChannel(TESTPILOT_TELEMETRY_CHANNEL); | ||
tabs.onActivated.addListener(this.handleTabActivated.bind(this)); | ||
tabs.onRemoved.addListener(this.handleTabRemoved.bind(this)); | ||
log('init()'); | ||
}, | ||
|
||
postMessage(message) { | ||
log('postMessage', message); | ||
return (!pingChannel) ? null : pingChannel.postMessage(message); | ||
}, | ||
|
||
handleTabActivated(activeInfo) { | ||
const tabId = activeInfo.tabId; | ||
if (!(tabId in unseenWakeHistory)) { return; } | ||
|
||
const item = unseenWakeHistory[tabId]; | ||
delete unseenWakeHistory[tabId]; | ||
seenWakeHistory[tabId] = item; | ||
|
||
this.wokenTabFocused(item); | ||
}, | ||
|
||
handleTabRemoved(tabId/*, removeInfo */) { | ||
if (tabId in seenWakeHistory) { | ||
delete seenWakeHistory[tabId]; | ||
} | ||
|
||
if (!(tabId in unseenWakeHistory)) { return; } | ||
|
||
const item = unseenWakeHistory[tabId]; | ||
delete unseenWakeHistory[tabId]; | ||
|
||
this.wokenTabClosed(item); | ||
}, | ||
|
||
panelOpened() { | ||
this.postMessage({ event: 'panel-opened' }); | ||
}, | ||
|
||
_commonTabPostMessage(event, item) { | ||
this.postMessage({ | ||
event, | ||
snooze_time: item.time, | ||
snooze_time_type: item.timeType | ||
}); | ||
}, | ||
|
||
clickSnoozedTab(item) { | ||
this._commonTabPostMessage('clicked', item); | ||
}, | ||
|
||
cancelSnoozedTab(item) { | ||
this._commonTabPostMessage('cancelled', item); | ||
}, | ||
|
||
scheduleSnoozedTab(item) { | ||
const tabId = item.tabId; | ||
if (tabId in seenWakeHistory || tabId in unseenWakeHistory) { | ||
delete seenWakeHistory[tabId]; | ||
delete unseenWakeHistory[tabId]; | ||
this._commonTabPostMessage('resnoozed', item); | ||
} else { | ||
this._commonTabPostMessage('snoozed', item); | ||
} | ||
}, | ||
|
||
tabWoken(item, tab) { | ||
unseenWakeHistory[tab.id] = item; | ||
this._commonTabPostMessage('woken', item); | ||
}, | ||
|
||
wokenTabFocused(item) { | ||
this._commonTabPostMessage('focused', item); | ||
}, | ||
|
||
wokenTabClosed(item) { | ||
this._commonTabPostMessage('closed-unfocused', item); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.