fix: anonymize outbound link events sent to google analytics

fixes https://github.com/Uniswap/uniswap-interface/issues/1729
This commit is contained in:
Moody Salem 2021-05-28 09:08:53 -05:00
parent 7f1def300d
commit d866d79578
No known key found for this signature in database
GPG Key ID: 8CB5CD10385138DB

@ -197,6 +197,52 @@ export const UniTokenAnimated = styled.img`
filter: drop-shadow(0px 2px 4px rgba(0, 0, 0, 0.15)); filter: drop-shadow(0px 2px 4px rgba(0, 0, 0, 0.15));
` `
const ETHERSCAN_HOSTNAMES: { [hostname: string]: true } = {
'etherscan.io': true,
'ropsten.etherscan.io': true,
'rinkeby.etherscan.io': true,
'kovan.etherscan.io': true,
'goerli.etherscan.io': true,
}
/**
* Returns the anonymized version of the given href, i.e. one that does not leak user information
* @param href the anonymized version of the given href
*/
function anonymizeLink(href: string): string {
try {
const url = new URL(href)
if (ETHERSCAN_HOSTNAMES[url.hostname]) {
return `${url.hostname}/${url.pathname.split('/')[1]}/***`
}
return href
} catch (error) {
console.error('Failed to anonymize outbound link', error)
return href
}
}
function useHandleClickLinkCallback() {
return useCallback((event: React.MouseEvent<HTMLAnchorElement>) => {
const { target, href } = event.currentTarget
const anonymizedHref = anonymizeLink(href)
// don't prevent default, don't redirect if it's a new tab
if (target === '_blank' || event.ctrlKey || event.metaKey) {
ReactGA.outboundLink({ label: anonymizedHref }, () => {
console.debug('Fired outbound link event', anonymizedHref)
})
} else {
event.preventDefault()
// send a ReactGA event and then trigger a location change
ReactGA.outboundLink({ label: anonymizedHref }, () => {
window.location.href = anonymizedHref
})
}
}, [])
}
/** /**
* Outbound link that handles firing google analytics events * Outbound link that handles firing google analytics events
*/ */
@ -206,24 +252,7 @@ export function ExternalLink({
rel = 'noopener noreferrer', rel = 'noopener noreferrer',
...rest ...rest
}: Omit<HTMLProps<HTMLAnchorElement>, 'as' | 'ref' | 'onClick'> & { href: string }) { }: Omit<HTMLProps<HTMLAnchorElement>, 'as' | 'ref' | 'onClick'> & { href: string }) {
const handleClick = useCallback( return <StyledLink target={target} rel={rel} href={href} onClick={useHandleClickLinkCallback()} {...rest} />
(event: React.MouseEvent<HTMLAnchorElement>) => {
// don't prevent default, don't redirect if it's a new tab
if (target === '_blank' || event.ctrlKey || event.metaKey) {
ReactGA.outboundLink({ label: href }, () => {
console.debug('Fired outbound link event', href)
})
} else {
event.preventDefault()
// send a ReactGA event and then trigger a location change
ReactGA.outboundLink({ label: href }, () => {
window.location.href = href
})
}
},
[href, target]
)
return <StyledLink target={target} rel={rel} href={href} onClick={handleClick} {...rest} />
} }
export function ExternalLinkIcon({ export function ExternalLinkIcon({
@ -232,25 +261,8 @@ export function ExternalLinkIcon({
rel = 'noopener noreferrer', rel = 'noopener noreferrer',
...rest ...rest
}: Omit<HTMLProps<HTMLAnchorElement>, 'as' | 'ref' | 'onClick'> & { href: string }) { }: Omit<HTMLProps<HTMLAnchorElement>, 'as' | 'ref' | 'onClick'> & { href: string }) {
const handleClick = useCallback(
(event: React.MouseEvent<HTMLAnchorElement>) => {
// don't prevent default, don't redirect if it's a new tab
if (target === '_blank' || event.ctrlKey || event.metaKey) {
ReactGA.outboundLink({ label: href }, () => {
console.debug('Fired outbound link event', href)
})
} else {
event.preventDefault()
// send a ReactGA event and then trigger a location change
ReactGA.outboundLink({ label: href }, () => {
window.location.href = href
})
}
},
[href, target]
)
return ( return (
<LinkIconWrapper target={target} rel={rel} href={href} onClick={handleClick} {...rest}> <LinkIconWrapper target={target} rel={rel} href={href} onClick={useHandleClickLinkCallback()} {...rest}>
<LinkIcon /> <LinkIcon />
</LinkIconWrapper> </LinkIconWrapper>
) )