Commit 83172dc5 authored by Nate Wienert's avatar Nate Wienert Committed by GitHub

feat: add tracking params and go straight to app store for iOS for the landing...

feat: add tracking params and go straight to app store for iOS for the landing page wallet CTA (#6732)

* feat: add tracking params and go straight to app store for iOS for the landing page wallet CTA
parent 0ca68bb1
import { sendAnalyticsEvent } from '@uniswap/analytics' import { InterfaceElementName } from '@uniswap/analytics-events'
import { InterfaceElementName, InterfaceEventName, SharedEventName } from '@uniswap/analytics-events'
import { PropsWithChildren, useCallback } from 'react' import { PropsWithChildren, useCallback } from 'react'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { ClickableStyle } from 'theme' import { ClickableStyle } from 'theme'
import { isIOS } from 'utils/userAgent' import { openDownloadApp } from 'utils/openDownloadApp'
const StyledButton = styled.button<{ padded?: boolean; branded?: boolean }>` const StyledButton = styled.button<{ padded?: boolean; branded?: boolean }>`
${ClickableStyle} ${ClickableStyle}
...@@ -32,23 +31,6 @@ function BaseButton({ onClick, branded, children }: PropsWithChildren<{ onClick? ...@@ -32,23 +31,6 @@ function BaseButton({ onClick, branded, children }: PropsWithChildren<{ onClick?
) )
} }
const APP_STORE_LINK = 'https://apps.apple.com/app/apple-store/id6443944476?pt=123625782&ct=In-App-Banners&mt=8'
const MICROSITE_LINK = 'https://wallet.uniswap.org/'
const openAppStore = () => {
window.open(APP_STORE_LINK, /* target = */ 'uniswap_wallet_appstore')
}
export const openWalletMicrosite = () => {
sendAnalyticsEvent(InterfaceEventName.UNISWAP_WALLET_MICROSITE_OPENED)
window.open(MICROSITE_LINK, /* target = */ 'uniswap_wallet_microsite')
}
export function openDownloadApp(element: InterfaceElementName) {
sendAnalyticsEvent(SharedEventName.ELEMENT_CLICKED, { element })
if (isIOS) openAppStore()
else openWalletMicrosite()
}
// Launches App Store if on an iOS device, else navigates to Uniswap Wallet microsite // Launches App Store if on an iOS device, else navigates to Uniswap Wallet microsite
export function DownloadButton({ export function DownloadButton({
onClick, onClick,
...@@ -62,7 +44,7 @@ export function DownloadButton({ ...@@ -62,7 +44,7 @@ export function DownloadButton({
const onButtonClick = useCallback(() => { const onButtonClick = useCallback(() => {
// handles any actions required by the parent, i.e. cancelling wallet connection attempt or dismissing an ad // handles any actions required by the parent, i.e. cancelling wallet connection attempt or dismissing an ad
onClick?.() onClick?.()
openDownloadApp(element) openDownloadApp({ element })
}, [element, onClick]) }, [element, onClick])
return ( return (
......
...@@ -2,7 +2,6 @@ import { Trans } from '@lingui/macro' ...@@ -2,7 +2,6 @@ import { Trans } from '@lingui/macro'
import { InterfaceElementName } from '@uniswap/analytics-events' import { InterfaceElementName } from '@uniswap/analytics-events'
import walletBannerPhoneImageSrc from 'assets/images/wallet_banner_phone_image.png' import walletBannerPhoneImageSrc from 'assets/images/wallet_banner_phone_image.png'
import { ReactComponent as AppleLogo } from 'assets/svg/apple_logo.svg' import { ReactComponent as AppleLogo } from 'assets/svg/apple_logo.svg'
import { openDownloadApp, openWalletMicrosite } from 'components/AccountDrawer/DownloadButton'
import { BaseButton } from 'components/Button' import { BaseButton } from 'components/Button'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import { OpacityHoverState } from 'components/Common' import { OpacityHoverState } from 'components/Common'
...@@ -14,6 +13,7 @@ import { useHideUniswapWalletBanner } from 'state/user/hooks' ...@@ -14,6 +13,7 @@ import { useHideUniswapWalletBanner } from 'state/user/hooks'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { ThemedText } from 'theme' import { ThemedText } from 'theme'
import { Z_INDEX } from 'theme/zIndex' import { Z_INDEX } from 'theme/zIndex'
import { openDownloadApp, openWalletMicrosite } from 'utils/openDownloadApp'
import { isIOS, isMobileSafari } from 'utils/userAgent' import { isIOS, isMobileSafari } from 'utils/userAgent'
const PopupContainer = styled.div<{ show: boolean }>` const PopupContainer = styled.div<{ show: boolean }>`
...@@ -119,7 +119,11 @@ export default function UniswapWalletBanner() { ...@@ -119,7 +119,11 @@ export default function UniswapWalletBanner() {
<> <>
<BannerButton <BannerButton
backgroundColor="white" backgroundColor="white"
onClick={() => openDownloadApp(InterfaceElementName.UNISWAP_WALLET_BANNER_DOWNLOAD_BUTTON)} onClick={() =>
openDownloadApp({
element: InterfaceElementName.UNISWAP_WALLET_BANNER_DOWNLOAD_BUTTON,
})
}
> >
<AppleLogo width={14} height={14} /> <AppleLogo width={14} height={14} />
<ThemedText.LabelSmall color="black" marginLeft="5px"> <ThemedText.LabelSmall color="black" marginLeft="5px">
...@@ -127,14 +131,14 @@ export default function UniswapWalletBanner() { ...@@ -127,14 +131,14 @@ export default function UniswapWalletBanner() {
</ThemedText.LabelSmall> </ThemedText.LabelSmall>
</BannerButton> </BannerButton>
<BannerButton backgroundColor="black" onClick={openWalletMicrosite}> <BannerButton backgroundColor="black" onClick={() => openWalletMicrosite()}>
<ThemedText.LabelSmall color="white"> <ThemedText.LabelSmall color="white">
<Trans>Learn more</Trans> <Trans>Learn more</Trans>
</ThemedText.LabelSmall> </ThemedText.LabelSmall>
</BannerButton> </BannerButton>
</> </>
) : ( ) : (
<BannerButton backgroundColor="white" width="125px" onClick={openWalletMicrosite}> <BannerButton backgroundColor="white" width="125px" onClick={() => openWalletMicrosite()}>
<ThemedText.LabelSmall color="black"> <ThemedText.LabelSmall color="black">
<Trans>Learn more</Trans> <Trans>Learn more</Trans>
</ThemedText.LabelSmall> </ThemedText.LabelSmall>
......
import { t, Trans } from '@lingui/macro' import { t, Trans } from '@lingui/macro'
import { InterfaceElementName } from '@uniswap/analytics-events' import { InterfaceElementName } from '@uniswap/analytics-events'
import { openDownloadApp } from 'components/AccountDrawer/DownloadButton'
import FeatureFlagModal from 'components/FeatureFlagModal/FeatureFlagModal' import FeatureFlagModal from 'components/FeatureFlagModal/FeatureFlagModal'
import { PrivacyPolicyModal } from 'components/PrivacyPolicy' import { PrivacyPolicyModal } from 'components/PrivacyPolicy'
import { useOnClickOutside } from 'hooks/useOnClickOutside' import { useOnClickOutside } from 'hooks/useOnClickOutside'
...@@ -22,6 +21,7 @@ import { NavLink, NavLinkProps } from 'react-router-dom' ...@@ -22,6 +21,7 @@ import { NavLink, NavLinkProps } from 'react-router-dom'
import { useToggleModal } from 'state/application/hooks' import { useToggleModal } from 'state/application/hooks'
import styled, { useTheme } from 'styled-components/macro' import styled, { useTheme } from 'styled-components/macro'
import { isDevelopmentEnv, isStagingEnv } from 'utils/env' import { isDevelopmentEnv, isStagingEnv } from 'utils/env'
import { openDownloadApp } from 'utils/openDownloadApp'
import { ReactComponent as AppleLogo } from '../../assets/svg/apple_logo.svg' import { ReactComponent as AppleLogo } from '../../assets/svg/apple_logo.svg'
import { ApplicationModal } from '../../state/application/reducer' import { ApplicationModal } from '../../state/application/reducer'
...@@ -150,7 +150,13 @@ export const MenuDropdown = () => { ...@@ -150,7 +150,13 @@ export const MenuDropdown = () => {
</PrimaryMenuRow.Text> </PrimaryMenuRow.Text>
</PrimaryMenuRow> </PrimaryMenuRow>
</Box> </Box>
<Box onClick={() => openDownloadApp(InterfaceElementName.UNISWAP_WALLET_MODAL_DOWNLOAD_BUTTON)}> <Box
onClick={() =>
openDownloadApp({
element: InterfaceElementName.UNISWAP_WALLET_MODAL_DOWNLOAD_BUTTON,
})
}
>
<PrimaryMenuRow close={toggleOpen}> <PrimaryMenuRow close={toggleOpen}>
<Icon> <Icon>
<AppleLogo width="24px" height="24px" fill={theme.textPrimary} /> <AppleLogo width="24px" height="24px" fill={theme.textPrimary} />
......
...@@ -2006,7 +2006,7 @@ exports[`disable nft on landing page does not render nft information and card 1` ...@@ -2006,7 +2006,7 @@ exports[`disable nft on landing page does not render nft information and card 1`
</div> </div>
<a <a
class="9 c58" class="9 c58"
href="https://wallet.uniswap.org/" href="https://wallet.uniswap.org/?utm_source=home_page&utm_medium=webapp&utm_campaign=wallet_microsite&utm_id=1"
> >
<svg <svg
height="20" height="20"
...@@ -4512,7 +4512,7 @@ exports[`disable nft on landing page renders nft information and card 1`] = ` ...@@ -4512,7 +4512,7 @@ exports[`disable nft on landing page renders nft information and card 1`] = `
</div> </div>
<a <a
class="9 c58" class="9 c58"
href="https://wallet.uniswap.org/" href="https://wallet.uniswap.org/?utm_source=home_page&utm_medium=webapp&utm_campaign=wallet_microsite&utm_id=1"
> >
<svg <svg
height="20" height="20"
......
import { render } from 'test-utils/render'
import Landing from '.'
jest.mock('utils/userAgent', () => {
return {
isIOS: true,
}
})
it('renders ios microsite link', () => {
const { container } = render(<Landing />)
expect(container.innerHTML.includes(`https://apps.apple.com/app/apple-store/id6443944476`)).toBeTruthy()
})
import { render } from 'test-utils/render'
import Landing from '.'
jest.mock('utils/userAgent', () => {
return {
isIOS: false,
}
})
it('renders non-ios microsite link', () => {
const { container } = render(<Landing />)
expect(container.innerHTML.includes(`https://wallet.uniswap.org/?utm_source=home_page`)).toBeTruthy()
})
...@@ -18,6 +18,7 @@ describe('disable nft on landing page', () => { ...@@ -18,6 +18,7 @@ describe('disable nft on landing page', () => {
expect(container).toHaveTextContent('Explore NFTs') expect(container).toHaveTextContent('Explore NFTs')
expect(container).toHaveTextContent('Buy and sell NFTs across marketplaces to find more listings at better prices.') expect(container).toHaveTextContent('Buy and sell NFTs across marketplaces to find more listings at better prices.')
}) })
it('does not render nft information and card', () => { it('does not render nft information and card', () => {
mocked(useDisableNFTRoutes).mockReturnValue(true) mocked(useDisableNFTRoutes).mockReturnValue(true)
const { container } = render(<Landing />) const { container } = render(<Landing />)
......
...@@ -21,6 +21,7 @@ import { BREAKPOINTS } from 'theme' ...@@ -21,6 +21,7 @@ import { BREAKPOINTS } from 'theme'
import { useIsDarkMode } from 'theme/components/ThemeToggle' import { useIsDarkMode } from 'theme/components/ThemeToggle'
import { TRANSITION_DURATIONS } from 'theme/styles' import { TRANSITION_DURATIONS } from 'theme/styles'
import { Z_INDEX } from 'theme/zIndex' import { Z_INDEX } from 'theme/zIndex'
import { getDownloadAppLinkProps } from 'utils/openDownloadApp'
const PageContainer = styled.div` const PageContainer = styled.div`
position: absolute; position: absolute;
...@@ -388,7 +389,13 @@ export default function Landing() { ...@@ -388,7 +389,13 @@ export default function Landing() {
<LearnMoreArrow /> <LearnMoreArrow />
</LearnMoreContainer> </LearnMoreContainer>
<DownloadWalletLink href="https://wallet.uniswap.org/"> <DownloadWalletLink
{...getDownloadAppLinkProps({
// landing page specific tracking params
microSiteParams: `utm_source=home_page&utm_medium=webapp&utm_campaign=wallet_microsite&utm_id=1`,
appStoreParams: `ct=Uniswap-Home-Page&mt=8`,
})}
>
<AppleLogo width="20" height="20" /> <AppleLogo width="20" height="20" />
Download the Uniswap Wallet for iOS Download the Uniswap Wallet for iOS
</DownloadWalletLink> </DownloadWalletLink>
......
import { sendAnalyticsEvent } from '@uniswap/analytics'
import { InterfaceElementName, InterfaceEventName } from '@uniswap/analytics-events'
import { isIOS } from 'utils/userAgent'
const APP_STORE_LINK = 'https://apps.apple.com/app/apple-store/id6443944476'
const MICROSITE_LINK = 'https://wallet.uniswap.org/'
type OpenDownloadAppOptions = {
element?: InterfaceElementName
appStoreParams?: string
microSiteParams?: string
}
const defaultDownloadAppOptions = {
appStoreParams: `pt=123625782&ct=In-App-Banners&mt=8`,
}
/**
* Note: openDownloadApp and getDownloadAppLink are equivalent functions, the first just runs imperatively
* and adds an analytics event, where the other only returns a link. Typically you'll use both:
*
* <a href={getDownloadAppLink(options)} onClick={() => openDownloadApp(options)} />
*
* This way with JS disabled and when hovering the <a /> you see and nav to the full href properly,
* but with JS on it will send the analytics event before navigating to the href.
*
* I've added a helper `getDownloadAppLinkProps` that unifies this behavior into one thing.
*/
export function openDownloadApp(options: OpenDownloadAppOptions = defaultDownloadAppOptions) {
if (isIOS) {
openAppStore({ element: options?.element, urlParamString: options?.appStoreParams })
} else {
openWalletMicrosite({ element: options?.element, urlParamString: options?.microSiteParams })
}
}
// if you need this by itself can add export, not used externally for now
const getDownloadAppLink = (options: OpenDownloadAppOptions = defaultDownloadAppOptions) =>
isIOS
? linkWithParams(APP_STORE_LINK, options?.appStoreParams)
: linkWithParams(MICROSITE_LINK, options?.microSiteParams)
export const getDownloadAppLinkProps = (options: OpenDownloadAppOptions = defaultDownloadAppOptions) => {
return {
href: getDownloadAppLink(options),
onClick(e: { preventDefault: () => void }) {
e.preventDefault()
openDownloadApp(options)
},
}
}
type AnalyticsLinkOptions = {
element?: InterfaceElementName
urlParamString?: string
}
const openAppStore = (options?: AnalyticsLinkOptions) => {
sendAnalyticsEvent(InterfaceEventName.UNISWAP_WALLET_APP_DOWNLOAD_OPENED, { element: options?.element })
window.open(linkWithParams(APP_STORE_LINK, options?.urlParamString), /* target = */ 'uniswap_wallet_appstore')
}
export const openWalletMicrosite = (options?: AnalyticsLinkOptions) => {
sendAnalyticsEvent(InterfaceEventName.UNISWAP_WALLET_MICROSITE_OPENED, { element: options?.element })
window.open(linkWithParams(MICROSITE_LINK, options?.urlParamString), /* target = */ 'uniswap_wallet_microsite')
}
const linkWithParams = (link: string, params?: string) => link + (params ? `?${params}` : '')
...@@ -6212,10 +6212,10 @@ ...@@ -6212,10 +6212,10 @@
"@typescript-eslint/types" "5.59.1" "@typescript-eslint/types" "5.59.1"
eslint-visitor-keys "^3.3.0" eslint-visitor-keys "^3.3.0"
"@uniswap/analytics-events@^2.13.0": "@uniswap/analytics-events@^2.14.0":
version "2.13.0" version "2.14.0"
resolved "https://registry.yarnpkg.com/@uniswap/analytics-events/-/analytics-events-2.13.0.tgz#9356efe311031ac751da563e7b8eeebcbe477574" resolved "https://registry.npmjs.org/@uniswap/analytics-events/-/analytics-events-2.14.0.tgz#f7f6196577cc10aa4e73dc82d54944b36cf6aaf8"
integrity sha512-rjlnxzKaswhQtP9w7rWJ79sqrLY1EigkCyc91yHNpbldTmF+a8Xxoec63Y6CsOqtsICX/CardR5dcXBSbFLL2A== integrity sha512-1CaXZLqoPVanMfmm/DSoLR7aja3JGKjXS0qZLVCMTNQTC7gpUp2boMM69WrOyTIH/AQ32jhhvPD/QoPs9P6lFw==
"@uniswap/analytics@^1.3.1": "@uniswap/analytics@^1.3.1":
version "1.3.1" version "1.3.1"
......
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