diff --git a/app/scripts/lib/background-metametrics.js b/app/scripts/lib/background-metametrics.js deleted file mode 100644 index 7af1125c1..000000000 --- a/app/scripts/lib/background-metametrics.js +++ /dev/null @@ -1,14 +0,0 @@ -import { getBackgroundMetaMetricState } from '../../../ui/app/selectors' -import { sendMetaMetricsEvent } from '../../../ui/app/helpers/utils/metametrics.util' - -export default function backgroundMetaMetricsEvent (metaMaskState, version, eventData) { - const stateEventData = getBackgroundMetaMetricState({ metamask: metaMaskState }) - if (stateEventData.participateInMetaMetrics) { - sendMetaMetricsEvent({ - ...stateEventData, - ...eventData, - version, - currentPath: '/background', - }) - } -} diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index d87ea186b..1517e1bad 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -25,6 +25,7 @@ import { PhishingController, } from '@metamask/controllers' import { getTrackMetaMetricsEvent } from '../../shared/modules/metametrics' +import { getBackgroundMetaMetricState } from '../../ui/app/selectors' import ComposableObservableStore from './lib/ComposableObservableStore' import AccountTracker from './lib/account-tracker' import createLoggerMiddleware from './lib/createLoggerMiddleware' @@ -56,8 +57,6 @@ import getRestrictedMethods from './controllers/permissions/restrictedMethods' import nodeify from './lib/nodeify' import accountImporter from './account-import-strategies' import seedPhraseVerifier from './lib/seed-phrase-verifier' - -import backgroundMetaMetricsEvent from './lib/background-metametrics' import { ENVIRONMENT_TYPE_BACKGROUND } from './lib/enums' export default class MetamaskController extends EventEmitter { @@ -1893,19 +1892,18 @@ export default class MetamaskController extends EventEmitter { } const metamaskState = await this.getState() - const version = this.platform.getVersion() - backgroundMetaMetricsEvent( - metamaskState, - version, - { - customVariables, - eventOpts: { - action, - category: 'Background', - name, - }, + const additionalProperties = getBackgroundMetaMetricState(metamaskState) + + this.trackMetaMetricsEvent({ + event: name, + category: 'Background', + matomoEvent: true, + properties: { + action, + ...additionalProperties, + ...customVariables, }, - ) + }) } /** diff --git a/development/build/scripts.js b/development/build/scripts.js index 7dc8d2d95..c6b9734d5 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -18,6 +18,7 @@ const { makeStringTransform } = require('browserify-transform-tools') const conf = require('rc')('metamask', { INFURA_PROJECT_ID: process.env.INFURA_PROJECT_ID, SEGMENT_WRITE_KEY: process.env.SEGMENT_WRITE_KEY, + SEGMENT_LEGACY_WRITE_KEY: process.env.SEGMENT_LEGACY_WRITE_KEY, }) const packageJSON = require('../../package.json') @@ -324,6 +325,7 @@ function createScriptTasks ({ browserPlatforms, livereload }) { // inflating event volume. const SEGMENT_PROD_WRITE_KEY = opts.testing ? undefined : process.env.SEGMENT_PROD_WRITE_KEY const SEGMENT_DEV_WRITE_KEY = opts.testing ? undefined : conf.SEGMENT_WRITE_KEY + const SEGMENT_LEGACY_WRITE_KEY = opts.testing ? undefined : conf.SEGMENT_LEGACY_WRITE_KEY // Inject variables into bundle bundler.transform(envify({ @@ -343,6 +345,7 @@ function createScriptTasks ({ browserPlatforms, livereload }) { : conf.INFURA_PROJECT_ID ), SEGMENT_WRITE_KEY: environment === 'production' ? SEGMENT_PROD_WRITE_KEY : SEGMENT_DEV_WRITE_KEY, + SEGMENT_LEGACY_WRITE_KEY: environment === 'production' ? process.env.SEGMENT_LEGACY_WRITE_KEY : SEGMENT_LEGACY_WRITE_KEY, }), { global: true, }) diff --git a/docs/creating-metrics-events.md b/docs/creating-metrics-events.md deleted file mode 100644 index 26fd8a6bb..000000000 --- a/docs/creating-metrics-events.md +++ /dev/null @@ -1,72 +0,0 @@ -## Creating Metrics Events - -The `metricsEvent` method is made available to all components via context. This is done in `metamask-extension/ui/app/helpers/higher-order-components/metametrics/metametrics.provider.js`. As such, it can be called in all components by first adding it to the context proptypes: - -``` -static contextTypes = { - t: PropTypes.func, - metricsEvent: PropTypes.func, -} -``` - -and then accessing it on `this.context`. - -Below is an example of a metrics event call: - -``` -this.context.metricsEvent({ - eventOpts: { - category: 'Navigation', - action: 'Main Menu', - name: 'Switched Account', - }, -}) -``` - -### Base Schema - -Every `metricsEvent` call is passed an object that must have an `eventOpts` property. This property is an object that itself must have three properties: -- category: categorizes events according to the schema we have set up in our matomo.org instance -- action: usually describes the page on which the event takes place, or sometimes a significant subsections of a page -- name: a very specific descriptor of the event - -### Implicit properties - -All metrics events send the following data when called: -- network -- environmentType -- activeCurrency -- accountType -- numberOfTokens -- numberOfAccounts -- version - -These are added to the metrics event via the metametrics provider. - -### Custom Variables - -Metrics events can include custom variables. These are included within the `customVariables` property that is a first-level property within first param passed to `metricsEvent`. - -For example: -``` -this.context.metricsEvent({ - eventOpts: { - category: 'Settings', - action: 'Custom RPC', - name: 'Error', - }, - customVariables: { - networkId: newRpc, - chainId, - }, -}) -``` - -Custom variables can have custom property names and values can be strings or numbers. - -**To include a custom variable, there are a set of necessary steps you must take.** - -1. First you must declare a constant equal to the desired name of the custom variable property in `metamask-extension/ui/app/helpers/utils/metametrics.util.js` under `//Custom Variable Declarations` -1. Then you must add that name to the `customVariableNameIdMap` declaration - 1. The id must be between 1 and 5 - 1. There can be no more than 5 custom variables assigned ids on a given url diff --git a/package.json b/package.json index e89fa9fec..dfeb27ce6 100644 --- a/package.json +++ b/package.json @@ -198,6 +198,7 @@ "@storybook/storybook-deployer": "^2.8.6", "@testing-library/react": "^10.4.8", "@testing-library/react-hooks": "^3.2.1", + "@types/react": "^16.9.53", "addons-linter": "1.14.0", "babel-loader": "^8.0.6", "babelify": "^10.0.0", diff --git a/shared/modules/metametrics.js b/shared/modules/metametrics.js index 17b1fdd54..e0fc186f0 100644 --- a/shared/modules/metametrics.js +++ b/shared/modules/metametrics.js @@ -57,6 +57,10 @@ export const segment = process.env.SEGMENT_WRITE_KEY ? new Analytics(process.env.SEGMENT_WRITE_KEY, { flushAt }) : segmentNoop +export const segmentLegacy = process.env.SEGMENT_LEGACY_WRITE_KEY + ? new Analytics(process.env.SEGMENT_LEGACY_WRITE_KEY, { flushAt }) + : segmentNoop + /** * We attach context to every meta metrics event that help to qualify our analytics. * This type has all optional values because it represents a returned object from a @@ -111,6 +115,12 @@ export const segment = process.env.SEGMENT_WRITE_KEY * @property {string} [currency] - ISO 4127 format currency for events with revenue, defaults to US dollars * @property {number} [value] - Abstract "value" that this event has for MetaMask. * @property {boolean} [excludeMetaMetricsId] - whether to exclude the user's metametrics id for anonymity + * @property {string} [metaMetricsId] - an override for the metaMetricsId in the event one is created as part + * of an asynchronous workflow, such as awaiting the result of the metametrics opt-in function that generates the + * user's metametrics id. + * @property {boolean} [matomoEvent] - is this event a holdover from matomo that needs further migration? + * when true, sends the data to a special segment source that marks the event data as not conforming to our + * ideal schema * @property {MetaMetricsDynamicContext} [eventContext] - additional context to attach to event */ @@ -137,7 +147,9 @@ export function getTrackMetaMetricsEvent ( revenue, currency, value, + metaMetricsId: metaMetricsIdOverride, excludeMetaMetricsId: excludeId, + matomoEvent = false, eventContext = {}, }) { if (!event || !category) { @@ -199,8 +211,20 @@ export function getTrackMetaMetricsEvent ( context, } + // If we are tracking sensitive data we will always use the anonymousId property + // as well as our METAMETRICS_ANONYMOUS_ID. This prevents us from associating potentially + // identifiable information with a specific id. During the opt in flow we will track all + // events, but do so with the anonymous id. The one exception to that rule is after the + // user opts in to MetaMetrics. When that happens we receive back the user's new MetaMetrics + // id before it is fully persisted to state. To avoid a race condition we explicitly pass the + // new id to the track method. In that case we will track the opt in event to the user's id. + // In all other cases we use the metaMetricsId from state. if (excludeMetaMetricsId) { trackOptions.anonymousId = METAMETRICS_ANONYMOUS_ID + } else if (isOptIn && metaMetricsIdOverride) { + trackOptions.userId = metaMetricsIdOverride + } else if (isOptIn) { + trackOptions.anonymousId = METAMETRICS_ANONYMOUS_ID } else { trackOptions.userId = metaMetricsId } @@ -210,12 +234,18 @@ export function getTrackMetaMetricsEvent ( // If flushAt is greater than one the callback won't be triggered until after a number // of events have been queued equal to the flushAt value OR flushInterval passes. The // default flushInterval is ten seconds - segment.track(trackOptions, (err) => { + const callback = (err) => { if (err) { return reject(err) } return resolve() - }) + } + + if (matomoEvent === true) { + segmentLegacy.track(trackOptions, callback) + } else { + segment.track(trackOptions, callback) + } }) } } diff --git a/ui/app/contexts/metametrics.js b/ui/app/contexts/metametrics.js index 3212807c2..eb0c8e476 100644 --- a/ui/app/contexts/metametrics.js +++ b/ui/app/contexts/metametrics.js @@ -1,4 +1,4 @@ -import React, { Component, createContext, useEffect, useCallback, useState } from 'react' +import React, { Component, createContext, useEffect, useCallback, useState, useMemo } from 'react' import { useSelector } from 'react-redux' import PropTypes from 'prop-types' import { useHistory } from 'react-router-dom' @@ -9,16 +9,15 @@ import { getAccountType, getNumberOfAccounts, getNumberOfTokens, + getCurrentChainId, } from '../selectors/selectors' import { getSendToken } from '../selectors/send' import { txDataSelector, } from '../selectors/confirm-transaction' import { getEnvironmentType } from '../../../app/scripts/lib/util' -import { - sendMetaMetricsEvent, -} from '../helpers/utils/metametrics.util' -import { sendCountIsTrackable } from '../../../shared/modules/metametrics' +import { getTrackMetaMetricsEvent } from '../../../shared/modules/metametrics' +import { getCurrentLocale } from '../ducks/metamask/metamask' export const MetaMetricsContext = createContext(() => { captureException( @@ -30,6 +29,8 @@ export function MetaMetricsProvider ({ children }) { const txData = useSelector(txDataSelector) || {} const network = useSelector(getCurrentNetworkId) const environmentType = getEnvironmentType() + const chainId = useSelector(getCurrentChainId) + const locale = useSelector(getCurrentLocale) const activeCurrency = useSelector(getSendToken)?.symbol const accountType = useSelector(getAccountType) const confirmTransactionOrigin = txData.origin @@ -44,7 +45,7 @@ export function MetaMetricsProvider ({ children }) { previousPath: '', })) - const { previousPath, currentPath } = state + const { currentPath } = state useEffect(() => { const unlisten = history.listen(() => setState((prevState) => ({ @@ -55,45 +56,63 @@ export function MetaMetricsProvider ({ children }) { return unlisten }, [history]) + /** + * track a metametrics event + * + * @param {import('../../../shared/modules/metametrics').MetaMetricsEventPayload} - payload for event + * @returns undefined + */ + const trackEvent = useMemo(() => { + const referrer = confirmTransactionOrigin ? { url: confirmTransactionOrigin } : undefined + const page = { + path: currentPath, + } + return getTrackMetaMetricsEvent(global.platform.getVersion(), () => ({ + context: { + referrer, + page, + }, + environmentType, + locale: locale.replace('_', '-'), + network, + chainId, + participateInMetaMetrics, + metaMetricsId, + metaMetricsSendCount, + })) + }, [network, chainId, locale, environmentType, participateInMetaMetrics, currentPath, confirmTransactionOrigin, metaMetricsId, metaMetricsSendCount]) + const metricsEvent = useCallback((config = {}, overrides = {}) => { const { eventOpts = {} } = config - const { name = '' } = eventOpts - const { currentPath: overrideCurrentPath = '' } = overrides - const isSendFlow = Boolean(name.match(/^send|^confirm/u) || overrideCurrentPath.match(/send|confirm/u)) - if (participateInMetaMetrics || config.isOptIn) { - return sendMetaMetricsEvent({ - network, - environmentType, - activeCurrency, - accountType, - confirmTransactionOrigin, - metaMetricsId, - numberOfTokens, - numberOfAccounts, - version: global.platform.getVersion(), - ...config, - previousPath, - currentPath, - excludeMetaMetricsId: isSendFlow && !sendCountIsTrackable(metaMetricsSendCount + 1), - ...overrides, - }) - } - - return undefined + return trackEvent({ + event: eventOpts.name, + category: eventOpts.category, + isOptIn: config.isOptIn, + excludeMetaMetricsId: eventOpts.excludeMetaMetricsId ?? overrides.excludeMetaMetricsId ?? false, + metaMetricsId: config.metaMetricsId, + matomoEvent: true, + properties: { + action: eventOpts.action, + number_of_tokens: numberOfTokens, + number_of_accounts: numberOfAccounts, + active_currency: activeCurrency, + account_type: accountType, + is_new_visit: config.is_new_visit, + // the properties coming from this key will not match our standards for + // snake_case on properties, and they may be redundant and/or not in the + // proper location (origin not as a referrer, for example). This is a temporary + // solution to not lose data, and the entire event system will be reworked in + // forthcoming PRs to deprecate the old Matomo events in favor of the new schema. + ...config.customVariables, + }, + }) }, [ - network, - environmentType, - activeCurrency, accountType, - confirmTransactionOrigin, - participateInMetaMetrics, - previousPath, - metaMetricsId, + activeCurrency, numberOfTokens, numberOfAccounts, - currentPath, - metaMetricsSendCount, + trackEvent, ]) return ( diff --git a/ui/app/helpers/utils/metametrics.util.js b/ui/app/helpers/utils/metametrics.util.js deleted file mode 100644 index bab0a15d8..000000000 --- a/ui/app/helpers/utils/metametrics.util.js +++ /dev/null @@ -1,216 +0,0 @@ -/* eslint camelcase: 0 */ - -import ethUtil from 'ethereumjs-util' - -const inDevelopment = process.env.METAMASK_DEBUG || process.env.IN_TEST - -let projectId = process.env.METAMETRICS_PROJECT_ID -if (!projectId) { - projectId = inDevelopment ? 1 : 2 -} - -const METAMETRICS_BASE_URL = 'https://chromeextensionmm.innocraft.cloud/piwik.php' -const METAMETRICS_REQUIRED_PARAMS = `?idsite=${projectId}&rec=1&apiv=1` -const METAMETRICS_BASE_FULL = METAMETRICS_BASE_URL + METAMETRICS_REQUIRED_PARAMS - -const METAMETRICS_TRACKING_URL = inDevelopment - ? 'http://www.metamask.io/metametrics' - : 'http://www.metamask.io/metametrics-prod' - -/** ***************Custom variables*************** **/ -// Custom variable declarations -const METAMETRICS_CUSTOM_GAS_LIMIT_CHANGE = 'gasLimitChange' -const METAMETRICS_CUSTOM_GAS_PRICE_CHANGE = 'gasPriceChange' -const METAMETRICS_CUSTOM_FUNCTION_TYPE = 'functionType' -const METAMETRICS_CUSTOM_RECIPIENT_KNOWN = 'recipientKnown' -const METAMETRICS_REQUEST_ORIGIN = 'origin' -const METAMETRICS_CUSTOM_FROM_NETWORK = 'fromNetwork' -const METAMETRICS_CUSTOM_TO_NETWORK = 'toNetwork' -const METAMETRICS_CUSTOM_ERROR_FIELD = 'errorField' -const METAMETRICS_CUSTOM_ERROR_MESSAGE = 'errorMessage' -const METAMETRICS_CUSTOM_RPC_NETWORK_ID = 'networkId' -const METAMETRICS_CUSTOM_RPC_CHAIN_ID = 'chainId' -const METAMETRICS_CUSTOM_GAS_CHANGED = 'gasChanged' -const METAMETRICS_CUSTOM_ASSET_SELECTED = 'assetSelected' - -const customVariableNameIdMap = { - [METAMETRICS_CUSTOM_FUNCTION_TYPE]: 1, - [METAMETRICS_CUSTOM_RECIPIENT_KNOWN]: 2, - [METAMETRICS_REQUEST_ORIGIN]: 3, - [METAMETRICS_CUSTOM_GAS_LIMIT_CHANGE]: 4, - [METAMETRICS_CUSTOM_GAS_PRICE_CHANGE]: 5, - - [METAMETRICS_CUSTOM_FROM_NETWORK]: 1, - [METAMETRICS_CUSTOM_TO_NETWORK]: 2, - - [METAMETRICS_CUSTOM_RPC_NETWORK_ID]: 1, - [METAMETRICS_CUSTOM_RPC_CHAIN_ID]: 2, - - [METAMETRICS_CUSTOM_ERROR_FIELD]: 3, - [METAMETRICS_CUSTOM_ERROR_MESSAGE]: 4, - - [METAMETRICS_CUSTOM_GAS_CHANGED]: 1, - [METAMETRICS_CUSTOM_ASSET_SELECTED]: 2, -} - -/** ********************************************************** **/ - -const METAMETRICS_CUSTOM_NETWORK = 'network' -const METAMETRICS_CUSTOM_ENVIRONMENT_TYPE = 'environmentType' -const METAMETRICS_CUSTOM_ACTIVE_CURRENCY = 'activeCurrency' -const METAMETRICS_CUSTOM_ACCOUNT_TYPE = 'accountType' -const METAMETRICS_CUSTOM_NUMBER_OF_ACCOUNTS = 'numberOfAccounts' -const METAMETRICS_CUSTOM_NUMBER_OF_TOKENS = 'numberOfTokens' -const METAMETRICS_CUSTOM_VERSION = 'version' - -const customDimensionsNameIdMap = { - [METAMETRICS_CUSTOM_NETWORK]: 5, - [METAMETRICS_CUSTOM_ENVIRONMENT_TYPE]: 6, - [METAMETRICS_CUSTOM_ACTIVE_CURRENCY]: 7, - [METAMETRICS_CUSTOM_ACCOUNT_TYPE]: 8, - [METAMETRICS_CUSTOM_NUMBER_OF_ACCOUNTS]: 9, - [METAMETRICS_CUSTOM_NUMBER_OF_TOKENS]: 10, - [METAMETRICS_CUSTOM_VERSION]: 11, -} - -function composeUrlRefParamAddition (previousPath, confirmTransactionOrigin) { - const externalOrigin = confirmTransactionOrigin && confirmTransactionOrigin !== 'metamask' - return `&urlref=${externalOrigin ? 'EXTERNAL' : encodeURIComponent(`${METAMETRICS_TRACKING_URL}${previousPath}`)}` -} - -// composes query params of the form &dimension[0-999]=[value] -function composeCustomDimensionParamAddition (customDimensions) { - const customDimensionParamStrings = Object.keys(customDimensions).reduce((acc, name) => { - return [...acc, `dimension${customDimensionsNameIdMap[name]}=${customDimensions[name]}`] - }, []) - return `&${customDimensionParamStrings.join('&')}` -} - -// composes query params in form: &cvar={[id]:[[name],[value]]} -// Example: &cvar={"1":["OS","iphone 5.0"],"2":["Matomo Mobile Version","1.6.2"],"3":["Locale","en::en"],"4":["Num Accounts","2"]} -function composeCustomVarParamAddition (customVariables) { - const customVariableIdValuePairs = Object.keys(customVariables).reduce((acc, name) => { - return { - [customVariableNameIdMap[name]]: [name, customVariables[name]], - ...acc, - } - }, {}) - return `&cvar=${encodeURIComponent(JSON.stringify(customVariableIdValuePairs))}` -} - -function composeParamAddition (paramValue, paramName) { - return paramValue !== 0 && !paramValue - ? '' - : `&${paramName}=${paramValue}` -} - -/** - * @name composeUrl - * @param {Object} config - configuration object for composing the metametrics url - * @property {object} config.eventOpts Object containing event category, action and name descriptors - * @property {object} config.customVariables Object containing custom properties with values relevant to a specific event - * @property {object} config.pageOpts Objects containing information about a page/route the event is dispatched from - * @property {number} config.network The selected network of the user when the event occurs - * @property {string} config.environmentType The "environment" the user is using the app from: 'popup', 'notification' or 'fullscreen' - * @property {string} config.activeCurrency The current the user has select as their primary currency at the time of the event - * @property {string} config.accountType The account type being used at the time of the event: 'hardware', 'imported' or 'default' - * @property {number} config.numberOfTokens The number of tokens that the user has added at the time of the event - * @property {number} config.numberOfAccounts The number of accounts the user has added at the time of the event - * @property {string} config.version The current version of the MetaMask extension - * @property {string} config.previousPath The pathname of the URL the user was on prior to the URL they are on at the time of the event - * @property {string} config.currentPath The pathname of the URL the user is on at the time of the event - * @property {string} config.metaMetricsId A random id assigned to a user at the time of opting in to metametrics. A hexadecimal number - * @property {string} config.confirmTransactionOrigin The origin on a transaction - * @property {boolean} config.excludeMetaMetricsId Whether or not the tracked event data should be associated with a metametrics id - * @property {boolean} config.isNewVisit Whether or not the event should be tracked as a new visit/user sessions - * @returns {string} - Returns a url to be passed to fetch to make the appropriate request to matomo. - * Example: https://chromeextensionmm.innocraft.cloud/piwik.php?idsite=1&rec=1&apiv=1&e_c=Navigation&e_a=Home&e_n=Clicked%20Send:%20Eth&urlref=http%3A%2F%2Fwww.metamask.io%2Fmetametrics%2Fhome.html%23send&dimension5=3&dimension6=fullscreen&dimension7=ETH&dimension8=default&dimension9=0&dimension10=3&url=http%3A%2F%2Fwww.metamask.io%2Fmetametrics%2Fhome.html%23&_id=49c10aff19795e9a&rand=7906028754863992&pv_id=53acad&uid=49c1 - */ -function composeUrl (config) { - const { - eventOpts = {}, - customVariables = '', - pageOpts = '', - network, - environmentType, - activeCurrency, - accountType, - numberOfTokens, - numberOfAccounts, - version, - previousPath = '', - currentPath, - metaMetricsId, - confirmTransactionOrigin, - excludeMetaMetricsId, - isNewVisit, - } = config - const base = METAMETRICS_BASE_FULL - - const e_c = composeParamAddition(eventOpts.category, 'e_c') - const e_a = composeParamAddition(eventOpts.action, 'e_a') - const e_n = composeParamAddition(eventOpts.name, 'e_n') - const new_visit = isNewVisit ? `&new_visit=1` : '' - - const cvar = (customVariables && composeCustomVarParamAddition(customVariables)) || '' - - const action_name = '' - - const urlref = previousPath && composeUrlRefParamAddition(previousPath, confirmTransactionOrigin) - - const dimensions = pageOpts.hideDimensions - ? '' - : ( - composeCustomDimensionParamAddition({ - network, - environmentType, - activeCurrency, - accountType, - version, - numberOfTokens: (customVariables && customVariables.numberOfTokens) || numberOfTokens, - numberOfAccounts: (customVariables && customVariables.numberOfAccounts) || numberOfAccounts, - }) - ) - const url = currentPath ? `&url=${encodeURIComponent(`${METAMETRICS_TRACKING_URL}${currentPath}`)}` : '' - const _id = metaMetricsId && !excludeMetaMetricsId ? `&_id=${metaMetricsId.slice(2, 18)}` : '' - const rand = `&rand=${String(Math.random()).slice(2)}` - const pv_id = currentPath ? `&pv_id=${ethUtil.bufferToHex(ethUtil.sha3(currentPath)).slice(2, 8)}` : '' - - let uid = '' - if (excludeMetaMetricsId) { - uid = '&uid=0000000000000000' - } else if (metaMetricsId) { - uid = `&uid=${metaMetricsId.slice(2, 18)}` - } - - return [base, e_c, e_a, e_n, cvar, action_name, urlref, dimensions, url, _id, rand, pv_id, uid, new_visit].join('') -} - -export function sendMetaMetricsEvent (config) { - return window.fetch(composeUrl(config), { - 'headers': {}, - 'method': 'GET', - }) -} - -export function verifyUserPermission (config, props) { - const { - eventOpts = {}, - } = config - const { userPermissionPreferences } = props - const { - allowAll, - allowNone, - allowSendMetrics, - } = userPermissionPreferences - - if (allowNone) { - return false - } else if (allowAll) { - return true - } else if (allowSendMetrics && eventOpts.name === 'send') { - return true - } - return false -} - diff --git a/ui/app/pages/routes/routes.component.js b/ui/app/pages/routes/routes.component.js index 37bb13f40..e5c3e74de 100644 --- a/ui/app/pages/routes/routes.component.js +++ b/ui/app/pages/routes/routes.component.js @@ -101,12 +101,6 @@ export default class Routes extends Component { this.props.history.listen((locationObj, action) => { if (action === 'PUSH') { pageChanged(locationObj.pathname) - this.context.metricsEvent({}, { - currentPath: locationObj.pathname, - pageOpts: { - hideDimensions: true, - }, - }) } }) } diff --git a/yarn.lock b/yarn.lock index c89e3b105..9df055969 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3063,6 +3063,11 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.1.tgz#be148756d5480a84cde100324c03a86ae5739fb5" integrity sha512-2zs+O+UkDsJ1Vcp667pd3f8xearMdopz/z54i99wtRDI5KLmngk7vlrYZD0ZjKHaROR03EznlBbVY9PfAEyJIQ== +"@types/prop-types@*": + version "15.7.3" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" + integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== + "@types/q@^1.5.1": version "1.5.2" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" @@ -3118,6 +3123,14 @@ dependencies: csstype "^2.2.0" +"@types/react@^16.9.53": + version "16.9.53" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.53.tgz#40cd4f8b8d6b9528aedd1fff8fcffe7a112a3d23" + integrity sha512-4nW60Sd4L7+WMXH1D6jCdVftuW7j4Za6zdp6tJ33Rqv0nk1ZAmQKML9ZLD4H0dehA3FZxXR/GM8gXplf82oNGw== + dependencies: + "@types/prop-types" "*" + csstype "^3.0.2" + "@types/redux@^3.6.0": version "3.6.0" resolved "https://registry.yarnpkg.com/@types/redux/-/redux-3.6.0.tgz#f1ebe1e5411518072e4fdfca5c76e16e74c1399a" @@ -8145,6 +8158,11 @@ csstype@^2.5.7: resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.5.tgz#1cd1dff742ebf4d7c991470ae71e12bb6751e034" integrity sha512-JsTaiksRsel5n7XwqPAfB0l3TFKdpjW/kgAELf9vrb5adGA7UCPLajKK5s3nFrcFm3Rkyp/Qkgl73ENc1UY3cA== +csstype@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.3.tgz#2b410bbeba38ba9633353aff34b05d9755d065f8" + integrity sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag== + currency-formatter@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/currency-formatter/-/currency-formatter-1.4.2.tgz#9da20b3706f7a42daf73b356b09a2a2b76ff3870"