#158: Add badge_toolbar_button and send_notification probes

Add badge_toolbar_button and send_notification probes:
* Add an additional extra key, 'price_last_high' to 'send_notification' and 'open_external_page' (with 'element' value of 'system_notification') and update METRICS.md.
* Add a 'sendTelemetry' flag for the 'sendProductToBackground' function to also be removed when the 'resend' code is removed in './src/extraction/index.js'.
  * Due to the fix for Issue #192, I was seeing some extra 'badge_toolbar_button' events (with 'badge_type' of 'add') as we are resending extracted product information 5 and 10 seconds after the product page loads.
* Update METRICS.md to clarify when 'badge_toolbar_button' with a 'badge_type' of 'price_alert' fires, since it will continue to fire for the same price alert until that alert is dismissed which is not obvious.
This commit is contained in:
Bianca Danforth 2018-10-31 10:34:26 -07:00
Родитель 3743b4cfca
Коммит 16a8fa3791
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 2C96DD7DB2A2D72D
6 изменённых файлов: 34 добавлений и 6 удалений

Просмотреть файл

@ -143,6 +143,8 @@ Below is a sample ping for the `badge_toolbar_button` and `visit_supported_site`
- `method`: The extraction method that was successful, if any. One of: 'fathom', 'fallback' or 'neither'. A value of 'neither' means that extraction failed.
- `'price'`: The price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only).
- `'price_alert'`: 'true' if the product has an active Price Alert; otherwise 'false'.
- `'price_last_high'`: The last high price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only).
- A high price is, semantically, the price that there's been an interesting drop from to warrant alerting the user. Practically, it is the highest price since the previous price alert.
- `'price_orig'`: The original price of the product in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only).
- `'price_prev'`: The previous price of the product when different from the latest price (`price`) in subunits (e.g. a $10.00 product would have a value of `'1000'`). For the MVP, the units here are always cents (USD currency only).
- `'product_index'`: The index of the product in the product listing. The top most list item is index '0'. The list is sorted by date added, descending (#113).
@ -216,6 +218,8 @@ Fired when the user clicks on a UI element in the extension that opens a page in
- `'price_alert'`
- `'price_orig'`
- `'product_key'`
- `'system_notification'` only:
- `'price_last_high'`
- `'product_card'` only:
- `'product_index'`
@ -313,6 +317,7 @@ Fired whenever a price change (of any magnitude and in any direction) is detecte
Fired whenever the toolbar is badged in response to:
1. A successful product extraction or
2. A Price Alert
- Note: For Price Alerts, this event will continue to trigger after the initial Price Alert is shown to the user until the Price Alert is dismissed (per the [UX spec](https://mozilla.invisionapp.com/share/UFNSHAIMT4V#/screens/317130676_Artboard_1) and when a system notification is clicked).
#### Payload properties
@ -336,6 +341,7 @@ Fired whenever a system notification is sent to the user notifying them of a Pri
- `'system_notification'`
- `extra_keys`: Object
- `'price'`
- `'price_last_high'`
- `'price_orig'`
- `'product_key'`
- `'tracked_prods'`

Просмотреть файл

@ -10,6 +10,7 @@
import config from 'commerce/config';
import {updateProductWithExtracted} from 'commerce/background/price_updates';
import {isValidExtractedProduct} from 'commerce/state/products';
import {recordEvent} from 'commerce/telemetry/extension';
/**
* Triggers background tasks when a product is extracted from a webpage. Along
@ -20,7 +21,7 @@ import {isValidExtractedProduct} from 'commerce/state/products';
* @param {MessageSender} sender
* The sender for the content script that extracted this product
*/
export async function handleExtractedProductData({extractedProduct}, sender) {
export async function handleExtractedProductData({extractedProduct, sendTelemetry = true}, sender) {
// Do nothing if the extracted product isn't valid.
if (!isValidExtractedProduct(extractedProduct)) {
return;
@ -51,6 +52,11 @@ export async function handleExtractedProductData({extractedProduct}, sender) {
tabId,
});
browser.browserAction.setBadgeText({text: '✚', tabId});
if (sendTelemetry) {
await recordEvent('badge_toolbar_button', 'toolbar_button', null, {
badge_type: 'add',
});
}
}
// Update saved product data if it exists

Просмотреть файл

@ -28,13 +28,16 @@ import {recordEvent} from 'commerce/telemetry/extension';
* Update the extension UI based on the current state of active price alerts.
* Should be called whenever price alerts may have changed.
*/
export function handlePriceAlerts() {
export async function handlePriceAlerts() {
const state = store.getState();
const activeAlerts = getActivePriceAlerts(state);
// Show the browser action badge if there are any active alerts.
if (activeAlerts.length > 0) {
browser.browserAction.setBadgeText({text: `${activeAlerts.length}`});
await recordEvent('badge_toolbar_button', 'toolbar_button', null, {
badge_type: 'price_alert',
});
} else {
browser.browserAction.setBadgeText({text: null});
}
@ -61,6 +64,12 @@ export function handlePriceAlerts() {
title: `Price Alert: ${product.title}`,
message: `${vendorName} · Originally ${original}, high of ${high}, now ${now}`,
});
await recordEvent('send_notification', 'system_notification', null, { // eslint-disable-line no-await-in-loop
price: alertPrice.amount.getAmount(),
price_last_high: highPriceAmount.getAmount(),
price_orig: originalPrice.amount.getAmount(),
product_key: product.anonId,
});
// Update state now that we've shown it
store.dispatch(showPriceAlert(alert));
@ -86,10 +95,12 @@ export async function handleNotificationClicked(notificationId) {
// Record open_external_page event
const latestPrice = getLatestPriceForProduct(state, product.id);
const originalPrice = getOldestPriceForProduct(state, product.id);
const highPriceAmount = Dinero({amount: alert.highPriceAmount});
await recordEvent('open_external_page', 'ui_element', null, {
element: 'system_notification',
price: latestPrice.amount.getAmount(),
price_alert: alert.active,
price_last_high: highPriceAmount.getAmount(),
price_orig: originalPrice.amount.getAmount(),
product_key: product.anonId,
});

Просмотреть файл

@ -99,7 +99,7 @@ export async function updateProductWithExtracted(data) {
const updatedState = store.getState();
const latestPrice = getLatestPriceForProduct(updatedState, id);
const originalPrice = getOldestPriceForProduct(updatedState, id);
recordEvent('detect_price_change', 'product_page', null, {
await recordEvent('detect_price_change', 'product_page', null, {
price: latestPrice.amount.getAmount(),
price_prev: previousPrice.amount.getAmount(),
price_orig: originalPrice.amount.getAmount(),

Просмотреть файл

@ -42,9 +42,10 @@ function extractProduct() {
return null;
}
async function sendProductToBackground(extractedProduct) {
async function sendProductToBackground(extractedProduct, sendTelemetry) {
return browser.runtime.sendMessage({
type: 'extracted-product',
sendTelemetry,
extractedProduct: {
...extractedProduct,
url: document.location.href,
@ -111,8 +112,9 @@ async function attemptExtraction() {
// Messy workaround for bug 1493470: Resend product info to the background
// script twice in case subframe loads clear the toolbar icon.
// TODO(osmose): Remove once Firefox 64 hits the release channel.
const resend = () => sendProductToBackground(extractedProduct);
// TODO(osmose): Remove once Firefox 64 hits the release channel, including second argument
// to sendProductToBackground.
const resend = () => sendProductToBackground(extractedProduct, false);
setTimeout(resend, 5000);
setTimeout(resend, 10000);

Просмотреть файл

@ -52,6 +52,8 @@ const EVENTS = {
'price_alert',
'price_orig',
'product_key',
// For 'element' value of 'system_notification' only
'price_last_high',
// For 'element' value 'product_card' only
'product_index',
],
@ -137,6 +139,7 @@ const EVENTS = {
objects: ['system_notification'],
extra_keys: [
'price',
'price_last_high',
'price_orig',
'product_key',
...DEFAULT_EXTRAS,