mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
remove matomo and route to segment (#9646)
This commit is contained in:
parent
379950d53f
commit
7d50357684
@ -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',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -25,6 +25,7 @@ import {
|
|||||||
PhishingController,
|
PhishingController,
|
||||||
} from '@metamask/controllers'
|
} from '@metamask/controllers'
|
||||||
import { getTrackMetaMetricsEvent } from '../../shared/modules/metametrics'
|
import { getTrackMetaMetricsEvent } from '../../shared/modules/metametrics'
|
||||||
|
import { getBackgroundMetaMetricState } from '../../ui/app/selectors'
|
||||||
import ComposableObservableStore from './lib/ComposableObservableStore'
|
import ComposableObservableStore from './lib/ComposableObservableStore'
|
||||||
import AccountTracker from './lib/account-tracker'
|
import AccountTracker from './lib/account-tracker'
|
||||||
import createLoggerMiddleware from './lib/createLoggerMiddleware'
|
import createLoggerMiddleware from './lib/createLoggerMiddleware'
|
||||||
@ -56,8 +57,6 @@ import getRestrictedMethods from './controllers/permissions/restrictedMethods'
|
|||||||
import nodeify from './lib/nodeify'
|
import nodeify from './lib/nodeify'
|
||||||
import accountImporter from './account-import-strategies'
|
import accountImporter from './account-import-strategies'
|
||||||
import seedPhraseVerifier from './lib/seed-phrase-verifier'
|
import seedPhraseVerifier from './lib/seed-phrase-verifier'
|
||||||
|
|
||||||
import backgroundMetaMetricsEvent from './lib/background-metametrics'
|
|
||||||
import { ENVIRONMENT_TYPE_BACKGROUND } from './lib/enums'
|
import { ENVIRONMENT_TYPE_BACKGROUND } from './lib/enums'
|
||||||
|
|
||||||
export default class MetamaskController extends EventEmitter {
|
export default class MetamaskController extends EventEmitter {
|
||||||
@ -1893,19 +1892,18 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const metamaskState = await this.getState()
|
const metamaskState = await this.getState()
|
||||||
const version = this.platform.getVersion()
|
const additionalProperties = getBackgroundMetaMetricState(metamaskState)
|
||||||
backgroundMetaMetricsEvent(
|
|
||||||
metamaskState,
|
this.trackMetaMetricsEvent({
|
||||||
version,
|
event: name,
|
||||||
{
|
category: 'Background',
|
||||||
customVariables,
|
matomoEvent: true,
|
||||||
eventOpts: {
|
properties: {
|
||||||
action,
|
action,
|
||||||
category: 'Background',
|
...additionalProperties,
|
||||||
name,
|
...customVariables,
|
||||||
},
|
|
||||||
},
|
},
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,6 +18,7 @@ const { makeStringTransform } = require('browserify-transform-tools')
|
|||||||
const conf = require('rc')('metamask', {
|
const conf = require('rc')('metamask', {
|
||||||
INFURA_PROJECT_ID: process.env.INFURA_PROJECT_ID,
|
INFURA_PROJECT_ID: process.env.INFURA_PROJECT_ID,
|
||||||
SEGMENT_WRITE_KEY: process.env.SEGMENT_WRITE_KEY,
|
SEGMENT_WRITE_KEY: process.env.SEGMENT_WRITE_KEY,
|
||||||
|
SEGMENT_LEGACY_WRITE_KEY: process.env.SEGMENT_LEGACY_WRITE_KEY,
|
||||||
})
|
})
|
||||||
|
|
||||||
const packageJSON = require('../../package.json')
|
const packageJSON = require('../../package.json')
|
||||||
@ -324,6 +325,7 @@ function createScriptTasks ({ browserPlatforms, livereload }) {
|
|||||||
// inflating event volume.
|
// inflating event volume.
|
||||||
const SEGMENT_PROD_WRITE_KEY = opts.testing ? undefined : process.env.SEGMENT_PROD_WRITE_KEY
|
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_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
|
// Inject variables into bundle
|
||||||
bundler.transform(envify({
|
bundler.transform(envify({
|
||||||
@ -343,6 +345,7 @@ function createScriptTasks ({ browserPlatforms, livereload }) {
|
|||||||
: conf.INFURA_PROJECT_ID
|
: conf.INFURA_PROJECT_ID
|
||||||
),
|
),
|
||||||
SEGMENT_WRITE_KEY: environment === 'production' ? SEGMENT_PROD_WRITE_KEY : SEGMENT_DEV_WRITE_KEY,
|
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,
|
global: true,
|
||||||
})
|
})
|
||||||
|
@ -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
|
|
@ -198,6 +198,7 @@
|
|||||||
"@storybook/storybook-deployer": "^2.8.6",
|
"@storybook/storybook-deployer": "^2.8.6",
|
||||||
"@testing-library/react": "^10.4.8",
|
"@testing-library/react": "^10.4.8",
|
||||||
"@testing-library/react-hooks": "^3.2.1",
|
"@testing-library/react-hooks": "^3.2.1",
|
||||||
|
"@types/react": "^16.9.53",
|
||||||
"addons-linter": "1.14.0",
|
"addons-linter": "1.14.0",
|
||||||
"babel-loader": "^8.0.6",
|
"babel-loader": "^8.0.6",
|
||||||
"babelify": "^10.0.0",
|
"babelify": "^10.0.0",
|
||||||
|
@ -57,6 +57,10 @@ export const segment = process.env.SEGMENT_WRITE_KEY
|
|||||||
? new Analytics(process.env.SEGMENT_WRITE_KEY, { flushAt })
|
? new Analytics(process.env.SEGMENT_WRITE_KEY, { flushAt })
|
||||||
: segmentNoop
|
: 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.
|
* 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
|
* 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 {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 {number} [value] - Abstract "value" that this event has for MetaMask.
|
||||||
* @property {boolean} [excludeMetaMetricsId] - whether to exclude the user's metametrics id for anonymity
|
* @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
|
* @property {MetaMetricsDynamicContext} [eventContext] - additional context to attach to event
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -137,7 +147,9 @@ export function getTrackMetaMetricsEvent (
|
|||||||
revenue,
|
revenue,
|
||||||
currency,
|
currency,
|
||||||
value,
|
value,
|
||||||
|
metaMetricsId: metaMetricsIdOverride,
|
||||||
excludeMetaMetricsId: excludeId,
|
excludeMetaMetricsId: excludeId,
|
||||||
|
matomoEvent = false,
|
||||||
eventContext = {},
|
eventContext = {},
|
||||||
}) {
|
}) {
|
||||||
if (!event || !category) {
|
if (!event || !category) {
|
||||||
@ -199,8 +211,20 @@ export function getTrackMetaMetricsEvent (
|
|||||||
context,
|
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) {
|
if (excludeMetaMetricsId) {
|
||||||
trackOptions.anonymousId = METAMETRICS_ANONYMOUS_ID
|
trackOptions.anonymousId = METAMETRICS_ANONYMOUS_ID
|
||||||
|
} else if (isOptIn && metaMetricsIdOverride) {
|
||||||
|
trackOptions.userId = metaMetricsIdOverride
|
||||||
|
} else if (isOptIn) {
|
||||||
|
trackOptions.anonymousId = METAMETRICS_ANONYMOUS_ID
|
||||||
} else {
|
} else {
|
||||||
trackOptions.userId = metaMetricsId
|
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
|
// 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
|
// of events have been queued equal to the flushAt value OR flushInterval passes. The
|
||||||
// default flushInterval is ten seconds
|
// default flushInterval is ten seconds
|
||||||
segment.track(trackOptions, (err) => {
|
const callback = (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err)
|
return reject(err)
|
||||||
}
|
}
|
||||||
return resolve()
|
return resolve()
|
||||||
})
|
}
|
||||||
|
|
||||||
|
if (matomoEvent === true) {
|
||||||
|
segmentLegacy.track(trackOptions, callback)
|
||||||
|
} else {
|
||||||
|
segment.track(trackOptions, callback)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 { useSelector } from 'react-redux'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { useHistory } from 'react-router-dom'
|
import { useHistory } from 'react-router-dom'
|
||||||
@ -9,16 +9,15 @@ import {
|
|||||||
getAccountType,
|
getAccountType,
|
||||||
getNumberOfAccounts,
|
getNumberOfAccounts,
|
||||||
getNumberOfTokens,
|
getNumberOfTokens,
|
||||||
|
getCurrentChainId,
|
||||||
} from '../selectors/selectors'
|
} from '../selectors/selectors'
|
||||||
import { getSendToken } from '../selectors/send'
|
import { getSendToken } from '../selectors/send'
|
||||||
import {
|
import {
|
||||||
txDataSelector,
|
txDataSelector,
|
||||||
} from '../selectors/confirm-transaction'
|
} from '../selectors/confirm-transaction'
|
||||||
import { getEnvironmentType } from '../../../app/scripts/lib/util'
|
import { getEnvironmentType } from '../../../app/scripts/lib/util'
|
||||||
import {
|
import { getTrackMetaMetricsEvent } from '../../../shared/modules/metametrics'
|
||||||
sendMetaMetricsEvent,
|
import { getCurrentLocale } from '../ducks/metamask/metamask'
|
||||||
} from '../helpers/utils/metametrics.util'
|
|
||||||
import { sendCountIsTrackable } from '../../../shared/modules/metametrics'
|
|
||||||
|
|
||||||
export const MetaMetricsContext = createContext(() => {
|
export const MetaMetricsContext = createContext(() => {
|
||||||
captureException(
|
captureException(
|
||||||
@ -30,6 +29,8 @@ export function MetaMetricsProvider ({ children }) {
|
|||||||
const txData = useSelector(txDataSelector) || {}
|
const txData = useSelector(txDataSelector) || {}
|
||||||
const network = useSelector(getCurrentNetworkId)
|
const network = useSelector(getCurrentNetworkId)
|
||||||
const environmentType = getEnvironmentType()
|
const environmentType = getEnvironmentType()
|
||||||
|
const chainId = useSelector(getCurrentChainId)
|
||||||
|
const locale = useSelector(getCurrentLocale)
|
||||||
const activeCurrency = useSelector(getSendToken)?.symbol
|
const activeCurrency = useSelector(getSendToken)?.symbol
|
||||||
const accountType = useSelector(getAccountType)
|
const accountType = useSelector(getAccountType)
|
||||||
const confirmTransactionOrigin = txData.origin
|
const confirmTransactionOrigin = txData.origin
|
||||||
@ -44,7 +45,7 @@ export function MetaMetricsProvider ({ children }) {
|
|||||||
previousPath: '',
|
previousPath: '',
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const { previousPath, currentPath } = state
|
const { currentPath } = state
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unlisten = history.listen(() => setState((prevState) => ({
|
const unlisten = history.listen(() => setState((prevState) => ({
|
||||||
@ -55,45 +56,63 @@ export function MetaMetricsProvider ({ children }) {
|
|||||||
return unlisten
|
return unlisten
|
||||||
}, [history])
|
}, [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 metricsEvent = useCallback((config = {}, overrides = {}) => {
|
||||||
const { eventOpts = {} } = config
|
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 trackEvent({
|
||||||
return sendMetaMetricsEvent({
|
event: eventOpts.name,
|
||||||
network,
|
category: eventOpts.category,
|
||||||
environmentType,
|
isOptIn: config.isOptIn,
|
||||||
activeCurrency,
|
excludeMetaMetricsId: eventOpts.excludeMetaMetricsId ?? overrides.excludeMetaMetricsId ?? false,
|
||||||
accountType,
|
metaMetricsId: config.metaMetricsId,
|
||||||
confirmTransactionOrigin,
|
matomoEvent: true,
|
||||||
metaMetricsId,
|
properties: {
|
||||||
numberOfTokens,
|
action: eventOpts.action,
|
||||||
numberOfAccounts,
|
number_of_tokens: numberOfTokens,
|
||||||
version: global.platform.getVersion(),
|
number_of_accounts: numberOfAccounts,
|
||||||
...config,
|
active_currency: activeCurrency,
|
||||||
previousPath,
|
account_type: accountType,
|
||||||
currentPath,
|
is_new_visit: config.is_new_visit,
|
||||||
excludeMetaMetricsId: isSendFlow && !sendCountIsTrackable(metaMetricsSendCount + 1),
|
// the properties coming from this key will not match our standards for
|
||||||
...overrides,
|
// 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.
|
||||||
return undefined
|
...config.customVariables,
|
||||||
|
},
|
||||||
|
})
|
||||||
}, [
|
}, [
|
||||||
network,
|
|
||||||
environmentType,
|
|
||||||
activeCurrency,
|
|
||||||
accountType,
|
accountType,
|
||||||
confirmTransactionOrigin,
|
activeCurrency,
|
||||||
participateInMetaMetrics,
|
|
||||||
previousPath,
|
|
||||||
metaMetricsId,
|
|
||||||
numberOfTokens,
|
numberOfTokens,
|
||||||
numberOfAccounts,
|
numberOfAccounts,
|
||||||
currentPath,
|
trackEvent,
|
||||||
metaMetricsSendCount,
|
|
||||||
])
|
])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
@ -101,12 +101,6 @@ export default class Routes extends Component {
|
|||||||
this.props.history.listen((locationObj, action) => {
|
this.props.history.listen((locationObj, action) => {
|
||||||
if (action === 'PUSH') {
|
if (action === 'PUSH') {
|
||||||
pageChanged(locationObj.pathname)
|
pageChanged(locationObj.pathname)
|
||||||
this.context.metricsEvent({}, {
|
|
||||||
currentPath: locationObj.pathname,
|
|
||||||
pageOpts: {
|
|
||||||
hideDimensions: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
18
yarn.lock
18
yarn.lock
@ -3063,6 +3063,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.1.tgz#be148756d5480a84cde100324c03a86ae5739fb5"
|
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.1.tgz#be148756d5480a84cde100324c03a86ae5739fb5"
|
||||||
integrity sha512-2zs+O+UkDsJ1Vcp667pd3f8xearMdopz/z54i99wtRDI5KLmngk7vlrYZD0ZjKHaROR03EznlBbVY9PfAEyJIQ==
|
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":
|
"@types/q@^1.5.1":
|
||||||
version "1.5.2"
|
version "1.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
|
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
|
||||||
@ -3118,6 +3123,14 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
csstype "^2.2.0"
|
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":
|
"@types/redux@^3.6.0":
|
||||||
version "3.6.0"
|
version "3.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/redux/-/redux-3.6.0.tgz#f1ebe1e5411518072e4fdfca5c76e16e74c1399a"
|
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"
|
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.5.tgz#1cd1dff742ebf4d7c991470ae71e12bb6751e034"
|
||||||
integrity sha512-JsTaiksRsel5n7XwqPAfB0l3TFKdpjW/kgAELf9vrb5adGA7UCPLajKK5s3nFrcFm3Rkyp/Qkgl73ENc1UY3cA==
|
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:
|
currency-formatter@^1.4.2:
|
||||||
version "1.4.2"
|
version "1.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/currency-formatter/-/currency-formatter-1.4.2.tgz#9da20b3706f7a42daf73b356b09a2a2b76ff3870"
|
resolved "https://registry.yarnpkg.com/currency-formatter/-/currency-formatter-1.4.2.tgz#9da20b3706f7a42daf73b356b09a2a2b76ff3870"
|
||||||
|
Loading…
Reference in New Issue
Block a user