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
This commit is contained in:
Nate Wienert 2023-07-20 10:28:08 -10:00 committed by GitHub
parent 0ca68bb140
commit 83172dc5ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 132 additions and 35 deletions

@ -168,7 +168,7 @@
"@sentry/types": "^7.45.0",
"@types/react-window-infinite-loader": "^1.0.6",
"@uniswap/analytics": "^1.3.1",
"@uniswap/analytics-events": "^2.13.0",
"@uniswap/analytics-events": "^2.14.0",
"@uniswap/conedison": "^1.8.0",
"@uniswap/governance": "^1.0.2",
"@uniswap/liquidity-staker": "^1.0.2",

@ -1,9 +1,8 @@
import { sendAnalyticsEvent } from '@uniswap/analytics'
import { InterfaceElementName, InterfaceEventName, SharedEventName } from '@uniswap/analytics-events'
import { InterfaceElementName } from '@uniswap/analytics-events'
import { PropsWithChildren, useCallback } from 'react'
import styled from 'styled-components/macro'
import { ClickableStyle } from 'theme'
import { isIOS } from 'utils/userAgent'
import { openDownloadApp } from 'utils/openDownloadApp'
const StyledButton = styled.button<{ padded?: boolean; branded?: boolean }>`
${ClickableStyle}
@ -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
export function DownloadButton({
onClick,
@ -62,7 +44,7 @@ export function DownloadButton({
const onButtonClick = useCallback(() => {
// handles any actions required by the parent, i.e. cancelling wallet connection attempt or dismissing an ad
onClick?.()
openDownloadApp(element)
openDownloadApp({ element })
}, [element, onClick])
return (

@ -2,7 +2,6 @@ import { Trans } from '@lingui/macro'
import { InterfaceElementName } from '@uniswap/analytics-events'
import walletBannerPhoneImageSrc from 'assets/images/wallet_banner_phone_image.png'
import { ReactComponent as AppleLogo } from 'assets/svg/apple_logo.svg'
import { openDownloadApp, openWalletMicrosite } from 'components/AccountDrawer/DownloadButton'
import { BaseButton } from 'components/Button'
import { AutoColumn } from 'components/Column'
import { OpacityHoverState } from 'components/Common'
@ -14,6 +13,7 @@ import { useHideUniswapWalletBanner } from 'state/user/hooks'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
import { Z_INDEX } from 'theme/zIndex'
import { openDownloadApp, openWalletMicrosite } from 'utils/openDownloadApp'
import { isIOS, isMobileSafari } from 'utils/userAgent'
const PopupContainer = styled.div<{ show: boolean }>`
@ -119,7 +119,11 @@ export default function UniswapWalletBanner() {
<>
<BannerButton
backgroundColor="white"
onClick={() => openDownloadApp(InterfaceElementName.UNISWAP_WALLET_BANNER_DOWNLOAD_BUTTON)}
onClick={() =>
openDownloadApp({
element: InterfaceElementName.UNISWAP_WALLET_BANNER_DOWNLOAD_BUTTON,
})
}
>
<AppleLogo width={14} height={14} />
<ThemedText.LabelSmall color="black" marginLeft="5px">
@ -127,14 +131,14 @@ export default function UniswapWalletBanner() {
</ThemedText.LabelSmall>
</BannerButton>
<BannerButton backgroundColor="black" onClick={openWalletMicrosite}>
<BannerButton backgroundColor="black" onClick={() => openWalletMicrosite()}>
<ThemedText.LabelSmall color="white">
<Trans>Learn more</Trans>
</ThemedText.LabelSmall>
</BannerButton>
</>
) : (
<BannerButton backgroundColor="white" width="125px" onClick={openWalletMicrosite}>
<BannerButton backgroundColor="white" width="125px" onClick={() => openWalletMicrosite()}>
<ThemedText.LabelSmall color="black">
<Trans>Learn more</Trans>
</ThemedText.LabelSmall>

@ -1,6 +1,5 @@
import { t, Trans } from '@lingui/macro'
import { InterfaceElementName } from '@uniswap/analytics-events'
import { openDownloadApp } from 'components/AccountDrawer/DownloadButton'
import FeatureFlagModal from 'components/FeatureFlagModal/FeatureFlagModal'
import { PrivacyPolicyModal } from 'components/PrivacyPolicy'
import { useOnClickOutside } from 'hooks/useOnClickOutside'
@ -22,6 +21,7 @@ import { NavLink, NavLinkProps } from 'react-router-dom'
import { useToggleModal } from 'state/application/hooks'
import styled, { useTheme } from 'styled-components/macro'
import { isDevelopmentEnv, isStagingEnv } from 'utils/env'
import { openDownloadApp } from 'utils/openDownloadApp'
import { ReactComponent as AppleLogo } from '../../assets/svg/apple_logo.svg'
import { ApplicationModal } from '../../state/application/reducer'
@ -150,7 +150,13 @@ export const MenuDropdown = () => {
</PrimaryMenuRow.Text>
</PrimaryMenuRow>
</Box>
<Box onClick={() => openDownloadApp(InterfaceElementName.UNISWAP_WALLET_MODAL_DOWNLOAD_BUTTON)}>
<Box
onClick={() =>
openDownloadApp({
element: InterfaceElementName.UNISWAP_WALLET_MODAL_DOWNLOAD_BUTTON,
})
}
>
<PrimaryMenuRow close={toggleOpen}>
<Icon>
<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`
</div>
<a
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
height="20"
@ -4512,7 +4512,7 @@ exports[`disable nft on landing page renders nft information and card 1`] = `
</div>
<a
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
height="20"

@ -0,0 +1,14 @@
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()
})

@ -0,0 +1,14 @@
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', () => {
expect(container).toHaveTextContent('Explore NFTs')
expect(container).toHaveTextContent('Buy and sell NFTs across marketplaces to find more listings at better prices.')
})
it('does not render nft information and card', () => {
mocked(useDisableNFTRoutes).mockReturnValue(true)
const { container } = render(<Landing />)

@ -21,6 +21,7 @@ import { BREAKPOINTS } from 'theme'
import { useIsDarkMode } from 'theme/components/ThemeToggle'
import { TRANSITION_DURATIONS } from 'theme/styles'
import { Z_INDEX } from 'theme/zIndex'
import { getDownloadAppLinkProps } from 'utils/openDownloadApp'
const PageContainer = styled.div`
position: absolute;
@ -388,7 +389,13 @@ export default function Landing() {
<LearnMoreArrow />
</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" />
Download the Uniswap Wallet for iOS
</DownloadWalletLink>

@ -0,0 +1,69 @@
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 @@
"@typescript-eslint/types" "5.59.1"
eslint-visitor-keys "^3.3.0"
"@uniswap/analytics-events@^2.13.0":
version "2.13.0"
resolved "https://registry.yarnpkg.com/@uniswap/analytics-events/-/analytics-events-2.13.0.tgz#9356efe311031ac751da563e7b8eeebcbe477574"
integrity sha512-rjlnxzKaswhQtP9w7rWJ79sqrLY1EigkCyc91yHNpbldTmF+a8Xxoec63Y6CsOqtsICX/CardR5dcXBSbFLL2A==
"@uniswap/analytics-events@^2.14.0":
version "2.14.0"
resolved "https://registry.npmjs.org/@uniswap/analytics-events/-/analytics-events-2.14.0.tgz#f7f6196577cc10aa4e73dc82d54944b36cf6aaf8"
integrity sha512-1CaXZLqoPVanMfmm/DSoLR7aja3JGKjXS0qZLVCMTNQTC7gpUp2boMM69WrOyTIH/AQ32jhhvPD/QoPs9P6lFw==
"@uniswap/analytics@^1.3.1":
version "1.3.1"