1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 09:57:02 +01:00

track sensitiveProperties in a duplicate event. (#9807)

This commit is contained in:
Brad Decker 2020-11-10 09:49:01 -06:00 committed by GitHub
parent aa85533368
commit 980b140891
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 42 additions and 63 deletions

View File

@ -1,5 +1,5 @@
import Analytics from 'analytics-node' import Analytics from 'analytics-node'
import { omit, pick } from 'lodash' import { merge, omit, pick } from 'lodash'
// flushAt controls how many events are sent to segment at once. Segment // flushAt controls how many events are sent to segment at once. Segment
// will hold onto a queue of events until it hits this number, then it sends // will hold onto a queue of events until it hits this number, then it sends
@ -137,6 +137,8 @@ export const segmentLegacy =
* @property {string} category - category to associate event to * @property {string} category - category to associate event to
* @property {boolean} [isOptIn] - happened during opt in/out workflow * @property {boolean} [isOptIn] - happened during opt in/out workflow
* @property {object} [properties] - object of custom values to track, snake_case * @property {object} [properties] - object of custom values to track, snake_case
* @property {object} [sensitiveProperties] - Object of sensitive values to track, snake_case.
* These properties will be sent in an additional event that excludes the user's metaMetricsId.
* @property {number} [revenue] - amount of currency that event creates in revenue for MetaMask * @property {number} [revenue] - amount of currency that event creates in revenue for MetaMask
* @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.
@ -168,6 +170,7 @@ export function getTrackMetaMetricsEvent(metamaskVersion, getDynamicState) {
category, category,
isOptIn, isOptIn,
properties = {}, properties = {},
sensitiveProperties,
revenue, revenue,
currency, currency,
value, value,
@ -179,6 +182,27 @@ export function getTrackMetaMetricsEvent(metamaskVersion, getDynamicState) {
if (!event || !category) { if (!event || !category) {
throw new Error('Must specify event and category.') throw new Error('Must specify event and category.')
} }
// Uses recursion to track a duplicate event with sensitive properties included,
// but metaMetricsId excluded
if (sensitiveProperties) {
if (excludeId === true) {
throw new Error(
'sensitiveProperties was specified in an event payload that also set the excludeMetaMetricsId flag',
)
}
trackMetaMetricsEvent({
event,
category,
isOptIn,
properties: merge(sensitiveProperties, properties),
revenue,
currency,
value,
excludeMetaMetricsId: true,
matomoEvent,
eventContext,
})
}
const { const {
participateInMetaMetrics, participateInMetaMetrics,
context: providedContext, context: providedContext,

View File

@ -94,8 +94,7 @@ export default function AwaitingSwap({
const quotesExpiredEvent = useNewMetricEvent({ const quotesExpiredEvent = useNewMetricEvent({
event: 'Quotes Timed Out', event: 'Quotes Timed Out',
excludeMetaMetricsId: true, sensitiveProperties: {
properties: {
token_from: sourceTokenInfo?.symbol, token_from: sourceTokenInfo?.symbol,
token_from_amount: fetchParams?.value, token_from_amount: fetchParams?.value,
token_to: destinationTokenInfo?.symbol, token_to: destinationTokenInfo?.symbol,
@ -106,10 +105,6 @@ export default function AwaitingSwap({
}, },
category: 'swaps', category: 'swaps',
}) })
const anonymousQuotesExpiredEvent = useNewMetricEvent({
event: 'Quotes Timed Out',
category: 'swaps',
})
const blockExplorerUrl = const blockExplorerUrl =
txHash && getBlockExplorerUrlForTx(networkId, txHash, rpcPrefs) txHash && getBlockExplorerUrlForTx(networkId, txHash, rpcPrefs)
@ -196,7 +191,6 @@ export default function AwaitingSwap({
if (!trackedQuotesExpiredEvent) { if (!trackedQuotesExpiredEvent) {
setTrackedQuotesExpiredEvent(true) setTrackedQuotesExpiredEvent(true)
quotesExpiredEvent() quotesExpiredEvent()
anonymousQuotesExpiredEvent()
} }
} else if (errorKey === ERROR_FETCHING_QUOTES) { } else if (errorKey === ERROR_FETCHING_QUOTES) {
headerText = t('swapFetchingQuotesErrorTitle') headerText = t('swapFetchingQuotesErrorTitle')

View File

@ -202,12 +202,7 @@ export default function Swap() {
const exitedSwapsEvent = useNewMetricEvent({ const exitedSwapsEvent = useNewMetricEvent({
event: 'Exited Swaps', event: 'Exited Swaps',
category: 'swaps', category: 'swaps',
}) sensitiveProperties: {
const anonymousExitedSwapsEvent = useNewMetricEvent({
event: 'Exited Swaps',
category: 'swaps',
excludeMetaMetricsId: true,
properties: {
token_from: fetchParams?.sourceTokenInfo?.symbol, token_from: fetchParams?.sourceTokenInfo?.symbol,
token_from_amount: fetchParams?.value, token_from_amount: fetchParams?.value,
request_type: fetchParams?.balanceError, request_type: fetchParams?.balanceError,
@ -221,7 +216,6 @@ export default function Swap() {
useEffect(() => { useEffect(() => {
exitEventRef.current = () => { exitEventRef.current = () => {
exitedSwapsEvent() exitedSwapsEvent()
anonymousExitedSwapsEvent()
} }
}) })

View File

@ -69,12 +69,7 @@ export default function LoadingSwapsQuotes({
const quotesRequestCancelledEventConfig = { const quotesRequestCancelledEventConfig = {
event: 'Quotes Request Cancelled', event: 'Quotes Request Cancelled',
category: 'swaps', category: 'swaps',
} sensitiveProperties: {
const anonymousQuotesRequestCancelledEventConfig = {
event: 'Quotes Request Cancelled',
category: 'swaps',
excludeMetaMetricsId: true,
properties: {
token_from: fetchParams?.sourceTokenInfo?.symbol, token_from: fetchParams?.sourceTokenInfo?.symbol,
token_from_amount: fetchParams?.value, token_from_amount: fetchParams?.value,
request_type: fetchParams?.balanceError, request_type: fetchParams?.balanceError,
@ -232,7 +227,6 @@ export default function LoadingSwapsQuotes({
submitText={t('back')} submitText={t('back')}
onSubmit={async () => { onSubmit={async () => {
metaMetricsEvent(quotesRequestCancelledEventConfig) metaMetricsEvent(quotesRequestCancelledEventConfig)
metaMetricsEvent(anonymousQuotesRequestCancelledEventConfig)
await dispatch(navigateBackToBuildQuote(history)) await dispatch(navigateBackToBuildQuote(history))
}} }}
hideCancel hideCancel

View File

@ -300,26 +300,10 @@ export default function ViewQuote() {
available_quotes: numberOfQuotes, available_quotes: numberOfQuotes,
} }
const anonymousAllAvailableQuotesOpened = useNewMetricEvent({
event: 'All Available Quotes Opened',
properties: {
...eventObjectBase,
other_quote_selected: usedQuote?.aggregator !== topQuote?.aggregator,
other_quote_selected_source:
usedQuote?.aggregator === topQuote?.aggregator
? null
: usedQuote?.aggregator,
},
excludeMetaMetricsId: true,
category: 'swaps',
})
const allAvailableQuotesOpened = useNewMetricEvent({ const allAvailableQuotesOpened = useNewMetricEvent({
event: 'All Available Quotes Opened', event: 'All Available Quotes Opened',
category: 'swaps', category: 'swaps',
}) sensitiveProperties: {
const anonymousQuoteDetailsOpened = useNewMetricEvent({
event: 'Quote Details Opened',
properties: {
...eventObjectBase, ...eventObjectBase,
other_quote_selected: usedQuote?.aggregator !== topQuote?.aggregator, other_quote_selected: usedQuote?.aggregator !== topQuote?.aggregator,
other_quote_selected_source: other_quote_selected_source:
@ -327,38 +311,34 @@ export default function ViewQuote() {
? null ? null
: usedQuote?.aggregator, : usedQuote?.aggregator,
}, },
excludeMetaMetricsId: true,
category: 'swaps',
}) })
const quoteDetailsOpened = useNewMetricEvent({ const quoteDetailsOpened = useNewMetricEvent({
event: 'Quote Details Opened', event: 'Quote Details Opened',
category: 'swaps', category: 'swaps',
sensitiveProperties: {
...eventObjectBase,
other_quote_selected: usedQuote?.aggregator !== topQuote?.aggregator,
other_quote_selected_source:
usedQuote?.aggregator === topQuote?.aggregator
? null
: usedQuote?.aggregator,
},
}) })
const anonymousEditSpendLimitOpened = useNewMetricEvent({ const editSpendLimitOpened = useNewMetricEvent({
event: 'Edit Spend Limit Opened', event: 'Edit Spend Limit Opened',
properties: { category: 'swaps',
sensitiveProperties: {
...eventObjectBase, ...eventObjectBase,
custom_spend_limit_set: originalApproveAmount === approveAmount, custom_spend_limit_set: originalApproveAmount === approveAmount,
custom_spend_limit_amount: custom_spend_limit_amount:
originalApproveAmount === approveAmount ? null : approveAmount, originalApproveAmount === approveAmount ? null : approveAmount,
}, },
excludeMetaMetricsId: true,
category: 'swaps',
})
const editSpendLimitOpened = useNewMetricEvent({
event: 'Edit Spend Limit Opened',
category: 'swaps',
}) })
const anonymousBestQuoteReviewedEvent = useNewMetricEvent({
event: 'Best Quote Reviewed',
properties: { ...eventObjectBase, network_fees: feeInFiat },
excludeMetaMetricsId: true,
category: 'swaps',
})
const bestQuoteReviewedEvent = useNewMetricEvent({ const bestQuoteReviewedEvent = useNewMetricEvent({
event: 'Best Quote Reviewed', event: 'Best Quote Reviewed',
category: 'swaps', category: 'swaps',
sensitiveProperties: { ...eventObjectBase, network_fees: feeInFiat },
}) })
useEffect(() => { useEffect(() => {
if ( if (
@ -376,7 +356,6 @@ export default function ViewQuote() {
) { ) {
bestQuoteReviewedEventSent.current = true bestQuoteReviewedEventSent.current = true
bestQuoteReviewedEvent() bestQuoteReviewedEvent()
anonymousBestQuoteReviewedEvent()
} }
}, [ }, [
sourceTokenSymbol, sourceTokenSymbol,
@ -388,13 +367,11 @@ export default function ViewQuote() {
numberOfQuotes, numberOfQuotes,
feeInFiat, feeInFiat,
bestQuoteReviewedEvent, bestQuoteReviewedEvent,
anonymousBestQuoteReviewedEvent,
]) ])
const metaMaskFee = usedQuote.fee const metaMaskFee = usedQuote.fee
const onFeeCardTokenApprovalClick = () => { const onFeeCardTokenApprovalClick = () => {
anonymousEditSpendLimitOpened()
editSpendLimitOpened() editSpendLimitOpened()
dispatch( dispatch(
showModal({ showModal({
@ -500,10 +477,7 @@ export default function ViewQuote() {
}} }}
swapToSymbol={destinationTokenSymbol} swapToSymbol={destinationTokenSymbol}
initialAggId={usedQuote.aggregator} initialAggId={usedQuote.aggregator}
onQuoteDetailsIsOpened={() => { onQuoteDetailsIsOpened={quoteDetailsOpened}
anonymousQuoteDetailsOpened()
quoteDetailsOpened()
}}
/> />
)} )}
<div className="view-quote__insufficient-eth-warning-wrapper"> <div className="view-quote__insufficient-eth-warning-wrapper">
@ -547,7 +521,6 @@ export default function ViewQuote() {
<div <div
className="view-quote__view-other-button-fade" className="view-quote__view-other-button-fade"
onClick={() => { onClick={() => {
anonymousAllAvailableQuotesOpened()
allAvailableQuotesOpened() allAvailableQuotesOpened()
setSelectQuotePopoverShown(true) setSelectQuotePopoverShown(true)
}} }}