Commit b17a38d9 authored by Lynn's avatar Lynn Committed by GitHub

feat: abstract analytics logging (#3892)

* fix: init commit

* fix: replace ReactGA.event with GoogleAnalyticsProvider.sentEvent

* fix: use GoogleAnalyticsProvider for all other ReactGA usages

* fix: add missing GoogleAnalyticsProvider import

* fix: incorporate zzmp's suggestions

* fix: add import I forgot

* fix: add another import I forgot

* fix: respond to zzmp comments
Co-authored-by: default avatarLynn Yu <lynn.yu@uniswap.org>
parent 22136b27
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { sendEvent } from 'components/analytics'
import React, { ErrorInfo } from 'react' import React, { ErrorInfo } from 'react'
import ReactGA from 'react-ga4'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import store, { AppState } from '../../state' import store, { AppState } from '../../state'
...@@ -85,7 +85,10 @@ export default class ErrorBoundary extends React.Component<unknown, ErrorBoundar ...@@ -85,7 +85,10 @@ export default class ErrorBoundary extends React.Component<unknown, ErrorBoundar
} }
componentDidCatch(error: Error, errorInfo: ErrorInfo) { componentDidCatch(error: Error, errorInfo: ErrorInfo) {
ReactGA.event('exception', { description: error.toString() + errorInfo.toString(), fatal: true }) sendEvent('exception', {
description: error.toString() + errorInfo.toString(),
fatal: true,
})
} }
render() { render() {
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency } from '@uniswap/sdk-core' import { Currency } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk' import { FeeAmount } from '@uniswap/v3-sdk'
import { sendEvent } from 'components/analytics'
import { ButtonGray } from 'components/Button' import { ButtonGray } from 'components/Button'
import Card from 'components/Card' import Card from 'components/Card'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
...@@ -10,8 +11,7 @@ import { useFeeTierDistribution } from 'hooks/useFeeTierDistribution' ...@@ -10,8 +11,7 @@ import { useFeeTierDistribution } from 'hooks/useFeeTierDistribution'
import { PoolState, usePools } from 'hooks/usePools' import { PoolState, usePools } from 'hooks/usePools'
import usePrevious from 'hooks/usePrevious' import usePrevious from 'hooks/usePrevious'
import { DynamicSection } from 'pages/AddLiquidity/styled' import { DynamicSection } from 'pages/AddLiquidity/styled'
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import ReactGA from 'react-ga4'
import { Box } from 'rebass' import { Box } from 'rebass'
import styled, { keyframes } from 'styled-components/macro' import styled, { keyframes } from 'styled-components/macro'
import { ThemedText } from 'theme' import { ThemedText } from 'theme'
...@@ -101,7 +101,7 @@ export default function FeeSelector({ ...@@ -101,7 +101,7 @@ export default function FeeSelector({
const handleFeePoolSelectWithEvent = useCallback( const handleFeePoolSelectWithEvent = useCallback(
(fee: FeeAmount) => { (fee: FeeAmount) => {
ReactGA.event({ sendEvent({
category: 'FeePoolSelect', category: 'FeePoolSelect',
action: 'Manual', action: 'Manual',
}) })
...@@ -122,7 +122,7 @@ export default function FeeSelector({ ...@@ -122,7 +122,7 @@ export default function FeeSelector({
setShowOptions(false) setShowOptions(false)
recommended.current = true recommended.current = true
ReactGA.event({ sendEvent({
category: 'FeePoolSelect', category: 'FeePoolSelect',
action: ' Recommended', action: ' Recommended',
}) })
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency, Price, Token } from '@uniswap/sdk-core' import { Currency, Price, Token } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk' import { FeeAmount } from '@uniswap/v3-sdk'
import { sendEvent } from 'components/analytics'
import { AutoColumn, ColumnCenter } from 'components/Column' import { AutoColumn, ColumnCenter } from 'components/Column'
import Loader from 'components/Loader' import Loader from 'components/Loader'
import { format } from 'd3' import { format } from 'd3'
...@@ -9,7 +10,6 @@ import useTheme from 'hooks/useTheme' ...@@ -9,7 +10,6 @@ import useTheme from 'hooks/useTheme'
import { saturate } from 'polished' import { saturate } from 'polished'
import React, { ReactNode, useCallback, useMemo } from 'react' import React, { ReactNode, useCallback, useMemo } from 'react'
import { BarChart2, CloudOff, Inbox } from 'react-feather' import { BarChart2, CloudOff, Inbox } from 'react-feather'
import ReactGA from 'react-ga4'
import { batch } from 'react-redux' import { batch } from 'react-redux'
import { Bound } from 'state/mint/v3/actions' import { Bound } from 'state/mint/v3/actions'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
...@@ -158,7 +158,7 @@ export default function LiquidityChartRangeInput({ ...@@ -158,7 +158,7 @@ export default function LiquidityChartRangeInput({
) )
if (isError) { if (isError) {
ReactGA.event('exception', { description: error.toString(), fatal: false }) sendEvent('exception', { description: error.toString(), fatal: false })
} }
return ( return (
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { CurrencyAmount, Token } from '@uniswap/sdk-core' import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { sendEvent } from 'components/analytics'
import useActiveWeb3React from 'hooks/useActiveWeb3React' import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useCallback, useEffect } from 'react' import { useCallback, useEffect } from 'react'
import { Heart, X } from 'react-feather' import { Heart, X } from 'react-feather'
import ReactGA from 'react-ga4'
import styled, { keyframes } from 'styled-components/macro' import styled, { keyframes } from 'styled-components/macro'
import tokenLogo from '../../assets/images/token-logo.png' import tokenLogo from '../../assets/images/token-logo.png'
...@@ -65,7 +65,7 @@ export default function ClaimPopup() { ...@@ -65,7 +65,7 @@ export default function ClaimPopup() {
const showClaimModal = useModalOpen(ApplicationModal.SELF_CLAIM) const showClaimModal = useModalOpen(ApplicationModal.SELF_CLAIM)
const toggleSelfClaimModal = useToggleSelfClaimModal() const toggleSelfClaimModal = useToggleSelfClaimModal()
const handleToggleSelfClaimModal = useCallback(() => { const handleToggleSelfClaimModal = useCallback(() => {
ReactGA.event({ sendEvent({
category: 'MerkleDrop', category: 'MerkleDrop',
action: 'Toggle self claim modal', action: 'Toggle self claim modal',
}) })
...@@ -79,7 +79,7 @@ export default function ClaimPopup() { ...@@ -79,7 +79,7 @@ export default function ClaimPopup() {
// listen for available claim and show popup if needed // listen for available claim and show popup if needed
useEffect(() => { useEffect(() => {
if (userHasAvailableclaim) { if (userHasAvailableclaim) {
ReactGA.event({ sendEvent({
category: 'MerkleDrop', category: 'MerkleDrop',
action: 'Show claim popup', action: 'Show claim popup',
}) })
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { sendEvent } from 'components/analytics'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import { RowFixed } from 'components/Row' import { RowFixed } from 'components/Row'
import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp' import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp'
import { useEffect } from 'react' import { useEffect } from 'react'
import { MessageCircle, X } from 'react-feather' import { MessageCircle, X } from 'react-feather'
import ReactGA from 'react-ga4'
import { useShowSurveyPopup } from 'state/user/hooks' import { useShowSurveyPopup } from 'state/user/hooks'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { ExternalLink, ThemedText, Z_INDEX } from 'theme' import { ExternalLink, ThemedText, Z_INDEX } from 'theme'
...@@ -62,7 +62,7 @@ export default function SurveyPopup() { ...@@ -62,7 +62,7 @@ export default function SurveyPopup() {
if (Math.random() < 0.01) { if (Math.random() < 0.01) {
setShowSurveyPopup(true) setShowSurveyPopup(true)
// log a case of succesful view // log a case of succesful view
ReactGA.event({ sendEvent({
category: 'Survey', category: 'Survey',
action: 'Saw Survey', action: 'Saw Survey',
}) })
...@@ -80,7 +80,7 @@ export default function SurveyPopup() { ...@@ -80,7 +80,7 @@ export default function SurveyPopup() {
<Wrapper gap="10px"> <Wrapper gap="10px">
<WrappedCloseIcon <WrappedCloseIcon
onClick={() => { onClick={() => {
ReactGA.event({ sendEvent({
category: 'Survey', category: 'Survey',
action: 'Clicked Survey Link', action: 'Clicked Survey Link',
}) })
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { sendEvent } from 'components/analytics'
import Card, { DarkGreyCard } from 'components/Card' import Card, { DarkGreyCard } from 'components/Card'
import Row, { AutoRow, RowBetween } from 'components/Row' import Row, { AutoRow, RowBetween } from 'components/Row'
import { useEffect, useRef } from 'react' import { useEffect, useRef } from 'react'
import { ArrowDown, Info, X } from 'react-feather' import { ArrowDown, Info, X } from 'react-feather'
import ReactGA from 'react-ga4'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { ExternalLink, ThemedText } from 'theme' import { ExternalLink, ThemedText } from 'theme'
import { isMobile } from 'utils/userAgent' import { isMobile } from 'utils/userAgent'
...@@ -87,7 +87,7 @@ export function PrivacyPolicyModal() { ...@@ -87,7 +87,7 @@ export function PrivacyPolicyModal() {
useEffect(() => { useEffect(() => {
if (!open) return if (!open) return
ReactGA.event({ sendEvent({
category: 'Modal', category: 'Modal',
action: 'Show Legal', action: 'Show Legal',
}) })
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { sendEvent } from 'components/analytics'
import { ButtonOutlined } from 'components/Button' import { ButtonOutlined } from 'components/Button'
import { AutoRow } from 'components/Row' import { AutoRow } from 'components/Row'
import React from 'react' import React from 'react'
import ReactGA from 'react-ga4'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { ThemedText } from 'theme' import { ThemedText } from 'theme'
...@@ -20,7 +20,7 @@ export default function PresetsButtons({ setFullRange }: { setFullRange: () => v ...@@ -20,7 +20,7 @@ export default function PresetsButtons({ setFullRange }: { setFullRange: () => v
<Button <Button
onClick={() => { onClick={() => {
setFullRange() setFullRange()
ReactGA.event({ sendEvent({
category: 'Liquidity', category: 'Liquidity',
action: 'Full Range Clicked', action: 'Full Range Clicked',
}) })
......
// eslint-disable-next-line no-restricted-imports // eslint-disable-next-line no-restricted-imports
import { t, Trans } from '@lingui/macro' import { t, Trans } from '@lingui/macro'
import { Currency, Token } from '@uniswap/sdk-core' import { Currency, Token } from '@uniswap/sdk-core'
import { sendEvent } from 'components/analytics'
import useActiveWeb3React from 'hooks/useActiveWeb3React' import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useDebounce from 'hooks/useDebounce' import useDebounce from 'hooks/useDebounce'
import { useOnClickOutside } from 'hooks/useOnClickOutside' import { useOnClickOutside } from 'hooks/useOnClickOutside'
...@@ -11,7 +12,6 @@ import { getTokenFilter } from 'lib/hooks/useTokenList/filtering' ...@@ -11,7 +12,6 @@ import { getTokenFilter } from 'lib/hooks/useTokenList/filtering'
import { tokenComparator, useSortTokensByQuery } from 'lib/hooks/useTokenList/sorting' import { tokenComparator, useSortTokensByQuery } from 'lib/hooks/useTokenList/sorting'
import { KeyboardEvent, RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react' import { KeyboardEvent, RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Edit } from 'react-feather' import { Edit } from 'react-feather'
import ReactGA from 'react-ga4'
import AutoSizer from 'react-virtualized-auto-sizer' import AutoSizer from 'react-virtualized-auto-sizer'
import { FixedSizeList } from 'react-window' import { FixedSizeList } from 'react-window'
import { Text } from 'rebass' import { Text } from 'rebass'
...@@ -93,7 +93,7 @@ export function CurrencySearch({ ...@@ -93,7 +93,7 @@ export function CurrencySearch({
useEffect(() => { useEffect(() => {
if (isAddressSearch) { if (isAddressSearch) {
ReactGA.event({ sendEvent({
category: 'Currency Select', category: 'Currency Select',
action: 'Search by address', action: 'Search by address',
label: isAddressSearch, label: isAddressSearch,
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { TokenList } from '@uniswap/token-lists' import { TokenList } from '@uniswap/token-lists'
import { sendEvent } from 'components/analytics'
import { ButtonPrimary } from 'components/Button' import { ButtonPrimary } from 'components/Button'
import Card from 'components/Card' import Card from 'components/Card'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
...@@ -11,7 +12,6 @@ import useTheme from 'hooks/useTheme' ...@@ -11,7 +12,6 @@ import useTheme from 'hooks/useTheme'
import { transparentize } from 'polished' import { transparentize } from 'polished'
import { useCallback, useState } from 'react' import { useCallback, useState } from 'react'
import { AlertTriangle, ArrowLeft } from 'react-feather' import { AlertTriangle, ArrowLeft } from 'react-feather'
import ReactGA from 'react-ga4'
import { useAppDispatch } from 'state/hooks' import { useAppDispatch } from 'state/hooks'
import { enableList, removeList } from 'state/lists/actions' import { enableList, removeList } from 'state/lists/actions'
import { useAllLists } from 'state/lists/hooks' import { useAllLists } from 'state/lists/hooks'
...@@ -54,7 +54,7 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro ...@@ -54,7 +54,7 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
setAddError(null) setAddError(null)
fetchList(listURL) fetchList(listURL)
.then(() => { .then(() => {
ReactGA.event({ sendEvent({
category: 'Lists', category: 'Lists',
action: 'Add List', action: 'Add List',
label: listURL, label: listURL,
...@@ -66,7 +66,7 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro ...@@ -66,7 +66,7 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
setModalView(CurrencyModalView.manage) setModalView(CurrencyModalView.manage)
}) })
.catch((error) => { .catch((error) => {
ReactGA.event({ sendEvent({
category: 'Lists', category: 'Lists',
action: 'Add List Failed', action: 'Add List Failed',
label: listURL, label: listURL,
......
// eslint-disable-next-line no-restricted-imports // eslint-disable-next-line no-restricted-imports
import { t, Trans } from '@lingui/macro' import { t, Trans } from '@lingui/macro'
import { TokenList } from '@uniswap/token-lists' import { TokenList } from '@uniswap/token-lists'
import { sendEvent } from 'components/analytics'
import Card from 'components/Card' import Card from 'components/Card'
import { UNSUPPORTED_LIST_URLS } from 'constants/lists' import { UNSUPPORTED_LIST_URLS } from 'constants/lists'
import useActiveWeb3React from 'hooks/useActiveWeb3React' import useActiveWeb3React from 'hooks/useActiveWeb3React'
...@@ -9,7 +10,6 @@ import parseENSAddress from 'lib/utils/parseENSAddress' ...@@ -9,7 +10,6 @@ import parseENSAddress from 'lib/utils/parseENSAddress'
import uriToHttp from 'lib/utils/uriToHttp' import uriToHttp from 'lib/utils/uriToHttp'
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react' import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { CheckCircle, Settings } from 'react-feather' import { CheckCircle, Settings } from 'react-feather'
import ReactGA from 'react-ga4'
import { usePopper } from 'react-popper' import { usePopper } from 'react-popper'
import { useAppDispatch, useAppSelector } from 'state/hooks' import { useAppDispatch, useAppSelector } from 'state/hooks'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
...@@ -126,7 +126,7 @@ const ListRow = memo(function ListRow({ listUrl }: { listUrl: string }) { ...@@ -126,7 +126,7 @@ const ListRow = memo(function ListRow({ listUrl }: { listUrl: string }) {
const handleAcceptListUpdate = useCallback(() => { const handleAcceptListUpdate = useCallback(() => {
if (!pending) return if (!pending) return
ReactGA.event({ sendEvent({
category: 'Lists', category: 'Lists',
action: 'Update List from List Select', action: 'Update List from List Select',
label: listUrl, label: listUrl,
...@@ -135,13 +135,13 @@ const ListRow = memo(function ListRow({ listUrl }: { listUrl: string }) { ...@@ -135,13 +135,13 @@ const ListRow = memo(function ListRow({ listUrl }: { listUrl: string }) {
}, [dispatch, listUrl, pending]) }, [dispatch, listUrl, pending])
const handleRemoveList = useCallback(() => { const handleRemoveList = useCallback(() => {
ReactGA.event({ sendEvent({
category: 'Lists', category: 'Lists',
action: 'Start Remove List', action: 'Start Remove List',
label: listUrl, label: listUrl,
}) })
if (window.prompt(t`Please confirm you would like to remove this list by typing REMOVE`) === `REMOVE`) { if (window.prompt(t`Please confirm you would like to remove this list by typing REMOVE`) === `REMOVE`) {
ReactGA.event({ sendEvent({
category: 'Lists', category: 'Lists',
action: 'Confirm Remove List', action: 'Confirm Remove List',
label: listUrl, label: listUrl,
...@@ -151,7 +151,7 @@ const ListRow = memo(function ListRow({ listUrl }: { listUrl: string }) { ...@@ -151,7 +151,7 @@ const ListRow = memo(function ListRow({ listUrl }: { listUrl: string }) {
}, [dispatch, listUrl]) }, [dispatch, listUrl])
const handleEnableList = useCallback(() => { const handleEnableList = useCallback(() => {
ReactGA.event({ sendEvent({
category: 'Lists', category: 'Lists',
action: 'Enable List', action: 'Enable List',
label: listUrl, label: listUrl,
...@@ -160,7 +160,7 @@ const ListRow = memo(function ListRow({ listUrl }: { listUrl: string }) { ...@@ -160,7 +160,7 @@ const ListRow = memo(function ListRow({ listUrl }: { listUrl: string }) {
}, [dispatch, listUrl]) }, [dispatch, listUrl])
const handleDisableList = useCallback(() => { const handleDisableList = useCallback(() => {
ReactGA.event({ sendEvent({
category: 'Lists', category: 'Lists',
action: 'Disable List', action: 'Disable List',
label: listUrl, label: listUrl,
......
// eslint-disable-next-line no-restricted-imports // eslint-disable-next-line no-restricted-imports
import { t, Trans } from '@lingui/macro' import { t, Trans } from '@lingui/macro'
import { Percent } from '@uniswap/sdk-core' import { Percent } from '@uniswap/sdk-core'
import { sendEvent } from 'components/analytics'
import useActiveWeb3React from 'hooks/useActiveWeb3React' import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { AUTO_ROUTER_SUPPORTED_CHAINS } from 'lib/hooks/routing/clientSideSmartOrderRouter' import { AUTO_ROUTER_SUPPORTED_CHAINS } from 'lib/hooks/routing/clientSideSmartOrderRouter'
import { useContext, useRef, useState } from 'react' import { useContext, useRef, useState } from 'react'
import { Settings, X } from 'react-feather' import { Settings, X } from 'react-feather'
import ReactGA from 'react-ga4'
import { Text } from 'rebass' import { Text } from 'rebass'
import styled, { ThemeContext } from 'styled-components/macro' import styled, { ThemeContext } from 'styled-components/macro'
...@@ -211,7 +211,7 @@ export default function SettingsTab({ placeholderSlippage }: { placeholderSlippa ...@@ -211,7 +211,7 @@ export default function SettingsTab({ placeholderSlippage }: { placeholderSlippa
id="toggle-optimized-router-button" id="toggle-optimized-router-button"
isActive={!clientSideRouter} isActive={!clientSideRouter}
toggle={() => { toggle={() => {
ReactGA.event({ sendEvent({
category: 'Routing', category: 'Routing',
action: clientSideRouter ? 'enable routing API' : 'disable routing API', action: clientSideRouter ? 'enable routing API' : 'disable routing API',
}) })
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { sendEvent } from 'components/analytics'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import { PrivacyPolicy } from 'components/PrivacyPolicy' import { PrivacyPolicy } from 'components/PrivacyPolicy'
import Row, { AutoRow } from 'components/Row' import Row, { AutoRow } from 'components/Row'
import { useCallback, useEffect, useState } from 'react' import { useCallback, useEffect, useState } from 'react'
import { ArrowLeft } from 'react-feather' import { ArrowLeft } from 'react-feather'
import ReactGA from 'react-ga4'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { AbstractConnector } from 'web3-react-abstract-connector' import { AbstractConnector } from 'web3-react-abstract-connector'
import { UnsupportedChainIdError, useWeb3React } from 'web3-react-core' import { UnsupportedChainIdError, useWeb3React } from 'web3-react-core'
...@@ -169,7 +169,7 @@ export default function WalletModal({ ...@@ -169,7 +169,7 @@ export default function WalletModal({
return true return true
}) })
// log selected wallet // log selected wallet
ReactGA.event({ sendEvent({
category: 'Wallet', category: 'Wallet',
action: 'Change Wallet', action: 'Change Wallet',
label: name, label: name,
......
import ReactGA from 'react-ga4'
import { GaOptions, InitOptions, UaEventOptions } from 'react-ga4/types/ga4'
/**
* Google Analytics Provider containing all methods used throughout app to log events to Google Analytics.
*/
export default class GoogleAnalyticsProvider {
public sendEvent(event: string | UaEventOptions, params?: any) {
ReactGA.event(event, params)
}
public initialize(
GA_MEASUREMENT_ID: InitOptions[] | string,
options?: {
legacyDimensionMetric?: boolean
nonce?: string
testMode?: boolean
gaOptions?: GaOptions | any
gtagOptions?: any
}
) {
ReactGA.initialize(GA_MEASUREMENT_ID, options)
}
public set(fieldsObject: any) {
ReactGA.set(fieldsObject)
}
public outboundLink(
{
label,
}: {
label: string
},
hitCallback: () => unknown
) {
ReactGA.outboundLink({ label }, hitCallback)
}
public pageview(path?: string, _?: string[], title?: string) {
ReactGA.pageview(path, _, title)
}
public ga(...args: any[]) {
ReactGA.ga(...args)
}
public gaCommandSendTiming(timingCategory: any, timingVar: any, timingValue: any, timingLabel: any) {
ReactGA._gaCommandSendTiming(timingCategory, timingVar, timingValue, timingLabel)
}
}
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useEffect } from 'react'
import ReactGA from 'react-ga4'
import { RouteComponentProps } from 'react-router-dom'
import { getCLS, getFCP, getFID, getLCP, Metric } from 'web-vitals'
import { GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY } from './index'
function reportWebVitals({ name, delta, id }: Metric) {
ReactGA._gaCommandSendTiming('Web Vitals', name, Math.round(name === 'CLS' ? delta * 1000 : delta), id)
}
// tracks web vitals and pageviews
export default function GoogleAnalyticsReporter({ location: { pathname, search } }: RouteComponentProps): null {
useEffect(() => {
getFCP(reportWebVitals)
getFID(reportWebVitals)
getLCP(reportWebVitals)
getCLS(reportWebVitals)
}, [])
const { chainId } = useActiveWeb3React()
useEffect(() => {
// cd1 - custom dimension 1 - chainId
ReactGA.set({ cd1: chainId ?? 0 })
}, [chainId])
useEffect(() => {
ReactGA.pageview(`${pathname}${search}`)
}, [pathname, search])
useEffect(() => {
// typed as 'any' in react-ga4 -.-
ReactGA.ga((tracker: any) => {
if (!tracker) return
const clientId = tracker.get('clientId')
window.localStorage.setItem(GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY, clientId)
})
}, [])
return null
}
import ReactGA from 'react-ga4' import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useEffect } from 'react'
import { UaEventOptions } from 'react-ga4/types/ga4'
import { RouteComponentProps } from 'react-router-dom'
import { isMobile } from 'utils/userAgent' import { isMobile } from 'utils/userAgent'
import { getCLS, getFCP, getFID, getLCP, Metric } from 'web-vitals'
import GoogleAnalyticsProvider from './GoogleAnalyticsProvider'
export const GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY = 'ga_client_id' export const GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY = 'ga_client_id'
const GOOGLE_ANALYTICS_ID: string | undefined = process.env.REACT_APP_GOOGLE_ANALYTICS_ID const GOOGLE_ANALYTICS_ID: string | undefined = process.env.REACT_APP_GOOGLE_ANALYTICS_ID
const storedClientId = window.localStorage.getItem(GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY) const storedClientId = window.localStorage.getItem(GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY)
const googleAnalytics = new GoogleAnalyticsProvider()
export function sendEvent(event: string | UaEventOptions, params?: any) {
return googleAnalytics.sendEvent(event, params)
}
export function outboundLink(
{
label,
}: {
label: string
},
hitCallback: () => unknown
) {
return googleAnalytics.outboundLink({ label }, hitCallback)
}
export function sendTiming(timingCategory: any, timingVar: any, timingValue: any, timingLabel: any) {
return googleAnalytics.gaCommandSendTiming(timingCategory, timingVar, timingValue, timingLabel)
}
if (typeof GOOGLE_ANALYTICS_ID === 'string') { if (typeof GOOGLE_ANALYTICS_ID === 'string') {
ReactGA.initialize(GOOGLE_ANALYTICS_ID, { googleAnalytics.initialize(GOOGLE_ANALYTICS_ID, {
gaOptions: { gaOptions: {
storage: 'none', storage: 'none',
storeGac: false, storeGac: false,
clientId: storedClientId ?? undefined, clientId: storedClientId ?? undefined,
}, },
}) })
ReactGA.set({ googleAnalytics.set({
anonymizeIp: true, anonymizeIp: true,
customBrowserType: !isMobile customBrowserType: !isMobile
? 'desktop' ? 'desktop'
...@@ -23,5 +50,39 @@ if (typeof GOOGLE_ANALYTICS_ID === 'string') { ...@@ -23,5 +50,39 @@ if (typeof GOOGLE_ANALYTICS_ID === 'string') {
: 'mobileRegular', : 'mobileRegular',
}) })
} else { } else {
ReactGA.initialize('test', { gtagOptions: { debug_mode: true } }) googleAnalytics.initialize('test', { gtagOptions: { debug_mode: true } })
}
function reportWebVitals({ name, delta, id }: Metric) {
sendTiming('Web Vitals', name, Math.round(name === 'CLS' ? delta * 1000 : delta), id)
}
// tracks web vitals and pageviews
export function useAnalyticsReporter({ pathname, search }: RouteComponentProps['location']) {
useEffect(() => {
getFCP(reportWebVitals)
getFID(reportWebVitals)
getLCP(reportWebVitals)
getCLS(reportWebVitals)
}, [])
const { chainId } = useActiveWeb3React()
useEffect(() => {
// cd1 - custom dimension 1 - chainId
googleAnalytics.set({ cd1: chainId ?? 0 })
}, [chainId])
useEffect(() => {
googleAnalytics.pageview(`${pathname}${search}`)
}, [pathname, search])
useEffect(() => {
// typed as 'any' in react-ga4 -.-
googleAnalytics.ga((tracker: any) => {
if (!tracker) return
const clientId = tracker.get('clientId')
window.localStorage.setItem(GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY, clientId)
})
}, [])
} }
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency, TradeType } from '@uniswap/sdk-core' import { Currency, TradeType } from '@uniswap/sdk-core'
import { sendEvent } from 'components/analytics'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import { LoadingOpacityContainer } from 'components/Loader/styled' import { LoadingOpacityContainer } from 'components/Loader/styled'
import { RowFixed } from 'components/Row' import { RowFixed } from 'components/Row'
import { MouseoverTooltipContent } from 'components/Tooltip' import { MouseoverTooltipContent } from 'components/Tooltip'
import ReactGA from 'react-ga4'
import { InterfaceTrade } from 'state/routing/types' import { InterfaceTrade } from 'state/routing/types'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { ThemedText } from 'theme' import { ThemedText } from 'theme'
...@@ -85,7 +85,7 @@ export default function GasEstimateBadge({ ...@@ -85,7 +85,7 @@ export default function GasEstimateBadge({
} }
placement="bottom" placement="bottom"
onOpen={() => onOpen={() =>
ReactGA.event({ sendEvent({
category: 'Gas', category: 'Gas',
action: 'Gas Details Tooltip Open', action: 'Gas Details Tooltip Open',
}) })
......
import { sendEvent } from 'components/analytics'
import { useEffect } from 'react' import { useEffect } from 'react'
import ReactGA from 'react-ga4'
import { ApplicationModal, setOpenModal } from 'state/application/reducer' import { ApplicationModal, setOpenModal } from 'state/application/reducer'
import { useAppDispatch } from 'state/hooks' import { useAppDispatch } from 'state/hooks'
...@@ -18,7 +18,7 @@ export default function useAccountRiskCheck(account: string | null | undefined) ...@@ -18,7 +18,7 @@ export default function useAccountRiskCheck(account: string | null | undefined)
.then((data) => { .then((data) => {
if (data.block) { if (data.block) {
dispatch(setOpenModal(ApplicationModal.BLOCKED_ACCOUNT)) dispatch(setOpenModal(ApplicationModal.BLOCKED_ACCOUNT))
ReactGA.event({ sendEvent({
category: 'Address Screening', category: 'Address Screening',
action: 'blocked', action: 'blocked',
label: account, label: account,
......
import { skipToken } from '@reduxjs/toolkit/query/react' import { skipToken } from '@reduxjs/toolkit/query/react'
import { Currency, Token } from '@uniswap/sdk-core' import { Currency, Token } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk' import { FeeAmount } from '@uniswap/v3-sdk'
import { sendEvent } from 'components/analytics'
import useBlockNumber from 'lib/hooks/useBlockNumber' import useBlockNumber from 'lib/hooks/useBlockNumber'
import ms from 'ms.macro' import ms from 'ms.macro'
import { useMemo } from 'react' import { useMemo } from 'react'
import ReactGA from 'react-ga4'
import { useFeeTierDistributionQuery } from 'state/data/enhanced' import { useFeeTierDistributionQuery } from 'state/data/enhanced'
import { FeeTierDistributionQuery } from 'state/data/generated' import { FeeTierDistributionQuery } from 'state/data/generated'
...@@ -112,7 +112,7 @@ function usePoolTVL(token0: Token | undefined, token1: Token | undefined) { ...@@ -112,7 +112,7 @@ function usePoolTVL(token0: Token | undefined, token1: Token | undefined) {
} }
if (latestBlock - (_meta?.block?.number ?? 0) > MAX_DATA_BLOCK_AGE) { if (latestBlock - (_meta?.block?.number ?? 0) > MAX_DATA_BLOCK_AGE) {
ReactGA.event('exception', { description: `Graph stale (latest block: ${latestBlock})` }) sendEvent('exception', { description: `Graph stale (latest block: ${latestBlock})` })
return { return {
isLoading, isLoading,
......
import { sendEvent } from 'components/analytics'
import { SupportedLocale } from 'constants/locales' import { SupportedLocale } from 'constants/locales'
import { LocationDescriptor } from 'history' import { LocationDescriptor } from 'history'
import useParsedQueryString from 'hooks/useParsedQueryString' import useParsedQueryString from 'hooks/useParsedQueryString'
import { stringify } from 'qs' import { stringify } from 'qs'
import { useMemo } from 'react' import { useMemo } from 'react'
import ReactGA from 'react-ga4'
import { useLocation } from 'react-router-dom' import { useLocation } from 'react-router-dom'
import { useActiveLocale } from './useActiveLocale' import { useActiveLocale } from './useActiveLocale'
...@@ -26,7 +26,7 @@ export function useLocationLinkProps(locale: SupportedLocale | null): { ...@@ -26,7 +26,7 @@ export function useLocationLinkProps(locale: SupportedLocale | null): {
search: stringify({ ...qs, lng: locale }), search: stringify({ ...qs, lng: locale }),
}, },
onClick: () => { onClick: () => {
ReactGA.event({ sendEvent({
category: 'Localization', category: 'Localization',
action: 'Switch Locale', action: 'Switch Locale',
label: `${activeLocale} -> ${locale}`, label: `${activeLocale} -> ${locale}`,
......
...@@ -3,12 +3,12 @@ import { TransactionResponse } from '@ethersproject/providers' ...@@ -3,12 +3,12 @@ import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { FeeAmount, NonfungiblePositionManager } from '@uniswap/v3-sdk' import { FeeAmount, NonfungiblePositionManager } from '@uniswap/v3-sdk'
import { sendEvent } from 'components/analytics'
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter' import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
import useActiveWeb3React from 'hooks/useActiveWeb3React' import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useParsedQueryString from 'hooks/useParsedQueryString' import useParsedQueryString from 'hooks/useParsedQueryString'
import { useCallback, useContext, useEffect, useState } from 'react' import { useCallback, useContext, useEffect, useState } from 'react'
import { AlertTriangle } from 'react-feather' import { AlertTriangle } from 'react-feather'
import ReactGA from 'react-ga4'
import { RouteComponentProps } from 'react-router-dom' import { RouteComponentProps } from 'react-router-dom'
import { Text } from 'rebass' import { Text } from 'rebass'
import { import {
...@@ -305,7 +305,7 @@ export default function AddLiquidity({ ...@@ -305,7 +305,7 @@ export default function AddLiquidity({
feeAmount: position.pool.fee, feeAmount: position.pool.fee,
}) })
setTxHash(response.hash) setTxHash(response.hash)
ReactGA.event({ sendEvent({
category: 'Liquidity', category: 'Liquidity',
action: 'Add', action: 'Add',
label: [currencies[Field.CURRENCY_A]?.symbol, currencies[Field.CURRENCY_B]?.symbol].join('/'), label: [currencies[Field.CURRENCY_A]?.symbol, currencies[Field.CURRENCY_B]?.symbol].join('/'),
......
...@@ -2,12 +2,12 @@ import { BigNumber } from '@ethersproject/bignumber' ...@@ -2,12 +2,12 @@ import { BigNumber } from '@ethersproject/bignumber'
import { TransactionResponse } from '@ethersproject/providers' import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { sendEvent } from 'components/analytics'
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter' import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
import { SwitchLocaleLink } from 'components/SwitchLocaleLink' import { SwitchLocaleLink } from 'components/SwitchLocaleLink'
import useActiveWeb3React from 'hooks/useActiveWeb3React' import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useCallback, useContext, useState } from 'react' import { useCallback, useContext, useState } from 'react'
import { Plus } from 'react-feather' import { Plus } from 'react-feather'
import ReactGA from 'react-ga4'
import { RouteComponentProps } from 'react-router-dom' import { RouteComponentProps } from 'react-router-dom'
import { Text } from 'rebass' import { Text } from 'rebass'
import { ThemeContext } from 'styled-components/macro' import { ThemeContext } from 'styled-components/macro'
...@@ -201,7 +201,7 @@ export default function AddLiquidity({ ...@@ -201,7 +201,7 @@ export default function AddLiquidity({
setTxHash(response.hash) setTxHash(response.hash)
ReactGA.event({ sendEvent({
category: 'Liquidity', category: 'Liquidity',
action: 'Add', action: 'Add',
label: [currencies[Field.CURRENCY_A]?.symbol, currencies[Field.CURRENCY_B]?.symbol].join('/'), label: [currencies[Field.CURRENCY_A]?.symbol, currencies[Field.CURRENCY_B]?.symbol].join('/'),
......
...@@ -3,11 +3,10 @@ import TopLevelModals from 'components/TopLevelModals' ...@@ -3,11 +3,10 @@ import TopLevelModals from 'components/TopLevelModals'
import ApeModeQueryParamReader from 'hooks/useApeModeQueryParamReader' import ApeModeQueryParamReader from 'hooks/useApeModeQueryParamReader'
import { lazy, Suspense } from 'react' import { lazy, Suspense } from 'react'
import { useEffect } from 'react' import { useEffect } from 'react'
import { useHistory } from 'react-router-dom' import { Redirect, Route, Switch, useHistory, useLocation } from 'react-router-dom'
import { Redirect, Route, Switch } from 'react-router-dom'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import GoogleAnalyticsReporter from '../components/analytics/GoogleAnalyticsReporter' import { useAnalyticsReporter } from '../components/analytics'
import ErrorBoundary from '../components/ErrorBoundary' import ErrorBoundary from '../components/ErrorBoundary'
import Header from '../components/Header' import Header from '../components/Header'
import Polling from '../components/Header/Polling' import Polling from '../components/Header/Polling'
...@@ -67,6 +66,7 @@ const Marginer = styled.div` ...@@ -67,6 +66,7 @@ const Marginer = styled.div`
export default function App() { export default function App() {
const history = useHistory() const history = useHistory()
useAnalyticsReporter(useLocation())
useEffect(() => { useEffect(() => {
const unlisten = history.listen(() => { const unlisten = history.listen(() => {
...@@ -79,7 +79,6 @@ export default function App() { ...@@ -79,7 +79,6 @@ export default function App() {
return ( return (
<ErrorBoundary> <ErrorBoundary>
<Route component={GoogleAnalyticsReporter} />
<Route component={DarkModeQueryParamReader} /> <Route component={DarkModeQueryParamReader} />
<Route component={ApeModeQueryParamReader} /> <Route component={ApeModeQueryParamReader} />
<Web3ReactManager> <Web3ReactManager>
......
...@@ -3,6 +3,7 @@ import { TransactionResponse } from '@ethersproject/providers' ...@@ -3,6 +3,7 @@ import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { CurrencyAmount, Fraction, Percent, Price, Token } from '@uniswap/sdk-core' import { CurrencyAmount, Fraction, Percent, Price, Token } from '@uniswap/sdk-core'
import { FeeAmount, Pool, Position, priceToClosestTick, TickMath } from '@uniswap/v3-sdk' import { FeeAmount, Pool, Position, priceToClosestTick, TickMath } from '@uniswap/v3-sdk'
import { sendEvent } from 'components/analytics'
import Badge, { BadgeVariant } from 'components/Badge' import Badge, { BadgeVariant } from 'components/Badge'
import { ButtonConfirmed } from 'components/Button' import { ButtonConfirmed } from 'components/Button'
import { BlueCard, DarkGreyCard, LightCard, YellowCard } from 'components/Card' import { BlueCard, DarkGreyCard, LightCard, YellowCard } from 'components/Card'
...@@ -23,7 +24,6 @@ import JSBI from 'jsbi' ...@@ -23,7 +24,6 @@ import JSBI from 'jsbi'
import { NEVER_RELOAD, useSingleCallResult } from 'lib/hooks/multicall' import { NEVER_RELOAD, useSingleCallResult } from 'lib/hooks/multicall'
import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react' import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'
import { AlertCircle, AlertTriangle, ArrowDown } from 'react-feather' import { AlertCircle, AlertTriangle, ArrowDown } from 'react-feather'
import ReactGA from 'react-ga4'
import { Redirect, RouteComponentProps } from 'react-router' import { Redirect, RouteComponentProps } from 'react-router'
import { Text } from 'rebass' import { Text } from 'rebass'
import { useAppDispatch } from 'state/hooks' import { useAppDispatch } from 'state/hooks'
...@@ -336,7 +336,7 @@ function V2PairMigration({ ...@@ -336,7 +336,7 @@ function V2PairMigration({
return migrator return migrator
.multicall(data, { gasLimit: calculateGasMargin(gasEstimate) }) .multicall(data, { gasLimit: calculateGasMargin(gasEstimate) })
.then((response: TransactionResponse) => { .then((response: TransactionResponse) => {
ReactGA.event({ sendEvent({
category: 'Migrate', category: 'Migrate',
action: `${isNotUniswap ? 'SushiSwap' : 'V2'}->V3`, action: `${isNotUniswap ? 'SushiSwap' : 'V2'}->V3`,
label: `${currency0.symbol}/${currency1.symbol}`, label: `${currency0.symbol}/${currency1.symbol}`,
......
...@@ -3,6 +3,7 @@ import { TransactionResponse } from '@ethersproject/providers' ...@@ -3,6 +3,7 @@ import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency, CurrencyAmount, Fraction, Percent, Price, Token } from '@uniswap/sdk-core' import { Currency, CurrencyAmount, Fraction, Percent, Price, Token } from '@uniswap/sdk-core'
import { NonfungiblePositionManager, Pool, Position } from '@uniswap/v3-sdk' import { NonfungiblePositionManager, Pool, Position } from '@uniswap/v3-sdk'
import { sendEvent } from 'components/analytics'
import Badge from 'components/Badge' import Badge from 'components/Badge'
import { ButtonConfirmed, ButtonGray, ButtonPrimary } from 'components/Button' import { ButtonConfirmed, ButtonGray, ButtonPrimary } from 'components/Button'
import { DarkCard, LightCard } from 'components/Card' import { DarkCard, LightCard } from 'components/Card'
...@@ -25,7 +26,6 @@ import { useV3PositionFromTokenId } from 'hooks/useV3Positions' ...@@ -25,7 +26,6 @@ import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
import { useSingleCallResult } from 'lib/hooks/multicall' import { useSingleCallResult } from 'lib/hooks/multicall'
import useNativeCurrency from 'lib/hooks/useNativeCurrency' import useNativeCurrency from 'lib/hooks/useNativeCurrency'
import { useCallback, useMemo, useRef, useState } from 'react' import { useCallback, useMemo, useRef, useState } from 'react'
import ReactGA from 'react-ga4'
import { Link, RouteComponentProps } from 'react-router-dom' import { Link, RouteComponentProps } from 'react-router-dom'
import { Bound } from 'state/mint/v3/actions' import { Bound } from 'state/mint/v3/actions'
import { useIsTransactionPending, useTransactionAdder } from 'state/transactions/hooks' import { useIsTransactionPending, useTransactionAdder } from 'state/transactions/hooks'
...@@ -470,7 +470,7 @@ export function PositionPage({ ...@@ -470,7 +470,7 @@ export function PositionPage({
setCollectMigrationHash(response.hash) setCollectMigrationHash(response.hash)
setCollecting(false) setCollecting(false)
ReactGA.event({ sendEvent({
category: 'Liquidity', category: 'Liquidity',
action: 'CollectV3', action: 'CollectV3',
label: [currency0ForFeeCollectionPurposes.symbol, currency1ForFeeCollectionPurposes.symbol].join('/'), label: [currency0ForFeeCollectionPurposes.symbol, currency1ForFeeCollectionPurposes.symbol].join('/'),
......
...@@ -3,6 +3,7 @@ import { TransactionResponse } from '@ethersproject/providers' ...@@ -3,6 +3,7 @@ import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { CurrencyAmount, Percent } from '@uniswap/sdk-core' import { CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { NonfungiblePositionManager } from '@uniswap/v3-sdk' import { NonfungiblePositionManager } from '@uniswap/v3-sdk'
import { sendEvent } from 'components/analytics'
import RangeBadge from 'components/Badge/RangeBadge' import RangeBadge from 'components/Badge/RangeBadge'
import { ButtonConfirmed, ButtonPrimary } from 'components/Button' import { ButtonConfirmed, ButtonPrimary } from 'components/Button'
import { LightCard } from 'components/Card' import { LightCard } from 'components/Card'
...@@ -24,7 +25,6 @@ import useTransactionDeadline from 'hooks/useTransactionDeadline' ...@@ -24,7 +25,6 @@ import useTransactionDeadline from 'hooks/useTransactionDeadline'
import { useV3PositionFromTokenId } from 'hooks/useV3Positions' import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
import useNativeCurrency from 'lib/hooks/useNativeCurrency' import useNativeCurrency from 'lib/hooks/useNativeCurrency'
import { useCallback, useMemo, useState } from 'react' import { useCallback, useMemo, useState } from 'react'
import ReactGA from 'react-ga4'
import { Redirect, RouteComponentProps } from 'react-router-dom' import { Redirect, RouteComponentProps } from 'react-router-dom'
import { Text } from 'rebass' import { Text } from 'rebass'
import { useBurnV3ActionHandlers, useBurnV3State, useDerivedV3BurnInfo } from 'state/burn/v3/hooks' import { useBurnV3ActionHandlers, useBurnV3State, useDerivedV3BurnInfo } from 'state/burn/v3/hooks'
...@@ -149,7 +149,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { ...@@ -149,7 +149,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
.getSigner() .getSigner()
.sendTransaction(newTxn) .sendTransaction(newTxn)
.then((response: TransactionResponse) => { .then((response: TransactionResponse) => {
ReactGA.event({ sendEvent({
category: 'Liquidity', category: 'Liquidity',
action: 'RemoveV3', action: 'RemoveV3',
label: [liquidityValue0.currency.symbol, liquidityValue1.currency.symbol].join('/'), label: [liquidityValue0.currency.symbol, liquidityValue1.currency.symbol].join('/'),
......
...@@ -3,11 +3,11 @@ import { Contract } from '@ethersproject/contracts' ...@@ -3,11 +3,11 @@ import { Contract } from '@ethersproject/contracts'
import { TransactionResponse } from '@ethersproject/providers' import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency, Percent } from '@uniswap/sdk-core' import { Currency, Percent } from '@uniswap/sdk-core'
import { sendEvent } from 'components/analytics'
import useActiveWeb3React from 'hooks/useActiveWeb3React' import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useV2LiquidityTokenPermit } from 'hooks/useV2LiquidityTokenPermit' import { useV2LiquidityTokenPermit } from 'hooks/useV2LiquidityTokenPermit'
import { useCallback, useContext, useMemo, useState } from 'react' import { useCallback, useContext, useMemo, useState } from 'react'
import { ArrowDown, Plus } from 'react-feather' import { ArrowDown, Plus } from 'react-feather'
import ReactGA from 'react-ga4'
import { RouteComponentProps } from 'react-router' import { RouteComponentProps } from 'react-router'
import { Text } from 'rebass' import { Text } from 'rebass'
import { ThemeContext } from 'styled-components/macro' import { ThemeContext } from 'styled-components/macro'
...@@ -275,7 +275,7 @@ export default function RemoveLiquidity({ ...@@ -275,7 +275,7 @@ export default function RemoveLiquidity({
setTxHash(response.hash) setTxHash(response.hash)
ReactGA.event({ sendEvent({
category: 'Liquidity', category: 'Liquidity',
action: 'Remove', action: 'Remove',
label: [currencyA.symbol, currencyB.symbol].join('/'), label: [currencyA.symbol, currencyB.symbol].join('/'),
......
...@@ -3,6 +3,7 @@ import { Trade } from '@uniswap/router-sdk' ...@@ -3,6 +3,7 @@ import { Trade } from '@uniswap/router-sdk'
import { Currency, CurrencyAmount, Token, TradeType } from '@uniswap/sdk-core' import { Currency, CurrencyAmount, Token, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk' import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk' import { Trade as V3Trade } from '@uniswap/v3-sdk'
import { sendEvent } from 'components/analytics'
import { NetworkAlert } from 'components/NetworkAlert/NetworkAlert' import { NetworkAlert } from 'components/NetworkAlert/NetworkAlert'
import SwapDetailsDropdown from 'components/swap/SwapDetailsDropdown' import SwapDetailsDropdown from 'components/swap/SwapDetailsDropdown'
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter' import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
...@@ -13,7 +14,6 @@ import useTransactionDeadline from 'hooks/useTransactionDeadline' ...@@ -13,7 +14,6 @@ import useTransactionDeadline from 'hooks/useTransactionDeadline'
import JSBI from 'jsbi' import JSBI from 'jsbi'
import { useCallback, useContext, useEffect, useMemo, useState } from 'react' import { useCallback, useContext, useEffect, useMemo, useState } from 'react'
import { ArrowDown, CheckCircle, HelpCircle } from 'react-feather' import { ArrowDown, CheckCircle, HelpCircle } from 'react-feather'
import ReactGA from 'react-ga4'
import { RouteComponentProps } from 'react-router-dom' import { RouteComponentProps } from 'react-router-dom'
import { Text } from 'rebass' import { Text } from 'rebass'
import { TradeState } from 'state/routing/types' import { TradeState } from 'state/routing/types'
...@@ -237,7 +237,7 @@ export default function Swap({ history }: RouteComponentProps) { ...@@ -237,7 +237,7 @@ export default function Swap({ history }: RouteComponentProps) {
} else { } else {
await approveCallback() await approveCallback()
ReactGA.event({ sendEvent({
category: 'Swap', category: 'Swap',
action: 'Approve', action: 'Approve',
label: [approvalOptimizedTradeString, approvalOptimizedTrade?.inputAmount?.currency.symbol].join('/'), label: [approvalOptimizedTradeString, approvalOptimizedTrade?.inputAmount?.currency.symbol].join('/'),
...@@ -286,12 +286,12 @@ export default function Swap({ history }: RouteComponentProps) { ...@@ -286,12 +286,12 @@ export default function Swap({ history }: RouteComponentProps) {
swapCallback() swapCallback()
.then((hash) => { .then((hash) => {
setSwapState({ attemptingTxn: false, tradeToConfirm, showConfirm, swapErrorMessage: undefined, txHash: hash }) setSwapState({ attemptingTxn: false, tradeToConfirm, showConfirm, swapErrorMessage: undefined, txHash: hash })
ReactGA.event({ sendEvent({
category: 'Swap', category: 'Swap',
action: 'transaction hash', action: 'transaction hash',
label: hash, label: hash,
}) })
ReactGA.event({ sendEvent({
category: 'Swap', category: 'Swap',
action: action:
recipient === null recipient === null
...@@ -378,7 +378,7 @@ export default function Swap({ history }: RouteComponentProps) { ...@@ -378,7 +378,7 @@ export default function Swap({ history }: RouteComponentProps) {
const handleMaxInput = useCallback(() => { const handleMaxInput = useCallback(() => {
maxInputAmount && onUserInput(Field.INPUT, maxInputAmount.toExact()) maxInputAmount && onUserInput(Field.INPUT, maxInputAmount.toExact())
ReactGA.event({ sendEvent({
category: 'Swap', category: 'Swap',
action: 'Max', action: 'Max',
}) })
......
import { skipToken } from '@reduxjs/toolkit/query/react' import { skipToken } from '@reduxjs/toolkit/query/react'
import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
import { IMetric, MetricLoggerUnit, setGlobalMetric } from '@uniswap/smart-order-router' import { IMetric, MetricLoggerUnit, setGlobalMetric } from '@uniswap/smart-order-router'
import { sendTiming } from 'components/analytics'
import { useStablecoinAmountFromFiatValue } from 'hooks/useUSDCPrice' import { useStablecoinAmountFromFiatValue } from 'hooks/useUSDCPrice'
import { useRoutingAPIArguments } from 'lib/hooks/routing/useRoutingAPIArguments' import { useRoutingAPIArguments } from 'lib/hooks/routing/useRoutingAPIArguments'
import useIsValidBlock from 'lib/hooks/useIsValidBlock' import useIsValidBlock from 'lib/hooks/useIsValidBlock'
import ms from 'ms.macro' import ms from 'ms.macro'
import { useMemo } from 'react' import { useMemo } from 'react'
import ReactGA from 'react-ga4'
import { useGetQuoteQuery } from 'state/routing/slice' import { useGetQuoteQuery } from 'state/routing/slice'
import { useClientSideRouter } from 'state/user/hooks' import { useClientSideRouter } from 'state/user/hooks'
...@@ -127,7 +127,7 @@ class GAMetric extends IMetric { ...@@ -127,7 +127,7 @@ class GAMetric extends IMetric {
} }
putMetric(key: string, value: number, unit?: MetricLoggerUnit) { putMetric(key: string, value: number, unit?: MetricLoggerUnit) {
ReactGA._gaCommandSendTiming('Routing API', `${key} | ${unit}`, value, 'client') sendTiming('Routing API', `${key} | ${unit}`, value, 'client')
} }
} }
......
import { outboundLink } from 'components/analytics'
import React, { HTMLProps } from 'react' import React, { HTMLProps } from 'react'
import { ArrowLeft, ExternalLink as LinkIconFeather, Trash, X } from 'react-feather' import { ArrowLeft, ExternalLink as LinkIconFeather, Trash, X } from 'react-feather'
import ReactGA from 'react-ga4'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import styled, { keyframes } from 'styled-components/macro' import styled, { keyframes } from 'styled-components/macro'
...@@ -175,13 +175,13 @@ function handleClickExternalLink(event: React.MouseEvent<HTMLAnchorElement>) { ...@@ -175,13 +175,13 @@ function handleClickExternalLink(event: React.MouseEvent<HTMLAnchorElement>) {
// don't prevent default, don't redirect if it's a new tab // don't prevent default, don't redirect if it's a new tab
if (target === '_blank' || event.ctrlKey || event.metaKey) { if (target === '_blank' || event.ctrlKey || event.metaKey) {
ReactGA.outboundLink({ label: anonymizedHref }, () => { outboundLink({ label: anonymizedHref }, () => {
console.debug('Fired outbound link event', anonymizedHref) console.debug('Fired outbound link event', anonymizedHref)
}) })
} else { } else {
event.preventDefault() event.preventDefault()
// send a ReactGA event and then trigger a location change // send a ReactGA event and then trigger a location change
ReactGA.outboundLink({ label: anonymizedHref }, () => { outboundLink({ label: anonymizedHref }, () => {
window.location.href = anonymizedHref window.location.href = anonymizedHref
}) })
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment