2020-10-26 20:05:57 +01:00
|
|
|
import React, { Component, createContext, useEffect, useCallback, useState, useMemo } from 'react'
|
2020-05-08 18:41:43 +02:00
|
|
|
import { useSelector } from 'react-redux'
|
|
|
|
import PropTypes from 'prop-types'
|
|
|
|
import { useHistory } from 'react-router-dom'
|
|
|
|
import { captureException } from '@sentry/browser'
|
|
|
|
|
|
|
|
import {
|
|
|
|
getCurrentNetworkId,
|
|
|
|
getAccountType,
|
|
|
|
getNumberOfAccounts,
|
|
|
|
getNumberOfTokens,
|
2020-10-26 20:05:57 +01:00
|
|
|
getCurrentChainId,
|
2020-05-08 18:41:43 +02:00
|
|
|
} from '../selectors/selectors'
|
2020-06-01 19:54:32 +02:00
|
|
|
import { getSendToken } from '../selectors/send'
|
2020-05-08 18:41:43 +02:00
|
|
|
import {
|
|
|
|
txDataSelector,
|
|
|
|
} from '../selectors/confirm-transaction'
|
|
|
|
import { getEnvironmentType } from '../../../app/scripts/lib/util'
|
2020-10-26 20:05:57 +01:00
|
|
|
import { getTrackMetaMetricsEvent } from '../../../shared/modules/metametrics'
|
|
|
|
import { getCurrentLocale } from '../ducks/metamask/metamask'
|
2020-05-08 18:41:43 +02:00
|
|
|
|
|
|
|
export const MetaMetricsContext = createContext(() => {
|
|
|
|
captureException(
|
2020-07-14 17:20:41 +02:00
|
|
|
Error(`MetaMetrics context function was called from a react node that is not a descendant of a MetaMetrics context provider`),
|
2020-05-08 18:41:43 +02:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
export function MetaMetricsProvider ({ children }) {
|
|
|
|
const txData = useSelector(txDataSelector) || {}
|
|
|
|
const network = useSelector(getCurrentNetworkId)
|
|
|
|
const environmentType = getEnvironmentType()
|
2020-10-26 20:05:57 +01:00
|
|
|
const chainId = useSelector(getCurrentChainId)
|
|
|
|
const locale = useSelector(getCurrentLocale)
|
2020-06-01 19:54:32 +02:00
|
|
|
const activeCurrency = useSelector(getSendToken)?.symbol
|
2020-05-08 18:41:43 +02:00
|
|
|
const accountType = useSelector(getAccountType)
|
|
|
|
const confirmTransactionOrigin = txData.origin
|
|
|
|
const metaMetricsId = useSelector((state) => state.metamask.metaMetricsId)
|
|
|
|
const participateInMetaMetrics = useSelector((state) => state.metamask.participateInMetaMetrics)
|
|
|
|
const metaMetricsSendCount = useSelector((state) => state.metamask.metaMetricsSendCount)
|
|
|
|
const numberOfTokens = useSelector(getNumberOfTokens)
|
|
|
|
const numberOfAccounts = useSelector(getNumberOfAccounts)
|
|
|
|
const history = useHistory()
|
|
|
|
const [state, setState] = useState(() => ({
|
Use `pathname` instead of URL for `currentPath` metrics parameter (#9158)
The `currentPath` parameter passed to our metrics utility had been
passed the full URL rather than just the path, contrary to what the
name would imply. We only used the path portion, so passing the full
URL did lead to complications.
Now just the `pathname` is passed in, rather than the full URL. This
simplifies the metrics logic, and it incidentally fixes two bugs.
The main bug fixed is regarding Firefox metrics. Previously we had
assumed the `currentPath` would start with `chrome-extension://`, which
of course was not true on Firefox. This lead to us incorrectly parsing
the `currentPath`, so path tracking was broken for Firefox events.
This broken parsing is now bypassed entirely, so metrics should now
work the same on Firefox as on Chrome.
The second bug was that we were incorrectly setting the tracking URL
for background events during tests. As a result, we were incorrectly
detecting ourselves as an internal site that had referred the user to
us. But this was not of major concern, since it only affected test
metrics (which get sent to the development Matomo project).
Lastly, this change let us discard the `pathname` parameter used in
the `overrides` parameter of the `metricsEvent` function. Now that
`currentPath` is equivalent to `pathname`, the `pathname` parameter is
redundant.
2020-08-07 20:32:46 +02:00
|
|
|
currentPath: (new URL(window.location.href)).pathname,
|
2020-05-08 18:41:43 +02:00
|
|
|
previousPath: '',
|
|
|
|
}))
|
|
|
|
|
2020-10-26 20:05:57 +01:00
|
|
|
const { currentPath } = state
|
2020-05-08 18:41:43 +02:00
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
const unlisten = history.listen(() => setState((prevState) => ({
|
Use `pathname` instead of URL for `currentPath` metrics parameter (#9158)
The `currentPath` parameter passed to our metrics utility had been
passed the full URL rather than just the path, contrary to what the
name would imply. We only used the path portion, so passing the full
URL did lead to complications.
Now just the `pathname` is passed in, rather than the full URL. This
simplifies the metrics logic, and it incidentally fixes two bugs.
The main bug fixed is regarding Firefox metrics. Previously we had
assumed the `currentPath` would start with `chrome-extension://`, which
of course was not true on Firefox. This lead to us incorrectly parsing
the `currentPath`, so path tracking was broken for Firefox events.
This broken parsing is now bypassed entirely, so metrics should now
work the same on Firefox as on Chrome.
The second bug was that we were incorrectly setting the tracking URL
for background events during tests. As a result, we were incorrectly
detecting ourselves as an internal site that had referred the user to
us. But this was not of major concern, since it only affected test
metrics (which get sent to the development Matomo project).
Lastly, this change let us discard the `pathname` parameter used in
the `overrides` parameter of the `metricsEvent` function. Now that
`currentPath` is equivalent to `pathname`, the `pathname` parameter is
redundant.
2020-08-07 20:32:46 +02:00
|
|
|
currentPath: (new URL(window.location.href)).pathname,
|
2020-05-08 18:41:43 +02:00
|
|
|
previousPath: prevState.currentPath,
|
|
|
|
})))
|
|
|
|
// remove this listener if the component is no longer mounted
|
|
|
|
return unlisten
|
|
|
|
}, [history])
|
|
|
|
|
2020-10-26 20:05:57 +01:00
|
|
|
/**
|
|
|
|
* 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])
|
|
|
|
|
2020-05-08 18:41:43 +02:00
|
|
|
const metricsEvent = useCallback((config = {}, overrides = {}) => {
|
|
|
|
const { eventOpts = {} } = config
|
2020-08-12 21:06:57 +02:00
|
|
|
|
2020-10-26 20:05:57 +01:00
|
|
|
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,
|
|
|
|
},
|
|
|
|
})
|
2020-05-08 18:41:43 +02:00
|
|
|
}, [
|
|
|
|
accountType,
|
2020-10-26 20:05:57 +01:00
|
|
|
activeCurrency,
|
2020-05-08 18:41:43 +02:00
|
|
|
numberOfTokens,
|
|
|
|
numberOfAccounts,
|
2020-10-26 20:05:57 +01:00
|
|
|
trackEvent,
|
2020-05-08 18:41:43 +02:00
|
|
|
])
|
|
|
|
|
|
|
|
return (
|
|
|
|
<MetaMetricsContext.Provider value={metricsEvent}>
|
|
|
|
{children}
|
|
|
|
</MetaMetricsContext.Provider>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
MetaMetricsProvider.propTypes = { children: PropTypes.node }
|
|
|
|
|
|
|
|
export class LegacyMetaMetricsProvider extends Component {
|
|
|
|
static propTypes = {
|
|
|
|
children: PropTypes.node,
|
|
|
|
}
|
|
|
|
|
|
|
|
static defaultProps = {
|
|
|
|
children: undefined,
|
|
|
|
}
|
|
|
|
|
|
|
|
static contextType = MetaMetricsContext
|
|
|
|
|
|
|
|
static childContextTypes = {
|
|
|
|
metricsEvent: PropTypes.func,
|
|
|
|
}
|
|
|
|
|
|
|
|
getChildContext () {
|
|
|
|
return {
|
|
|
|
metricsEvent: this.context,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
render () {
|
|
|
|
return this.props.children
|
|
|
|
}
|
|
|
|
}
|