Tracking (#511)
* tracking helper functions * track everything * remove extraneous code
This commit is contained in:
parent
730b7272ce
commit
c45da8c334
|
@ -61,7 +61,7 @@ export function AddFundsButton(props: { className?: string }) {
|
|||
>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary bg-gradient-to-r from-teal-500 to-green-500 px-10 font-medium hover:from-teal-600 hover:to-green-600"
|
||||
className="btn btn-primary bg-gradient-to-r from-indigo-500 to-blue-500 px-10 font-medium hover:from-indigo-600 hover:to-blue-600"
|
||||
>
|
||||
Checkout
|
||||
</button>
|
||||
|
|
|
@ -22,9 +22,9 @@ import {
|
|||
calculateDpmPayoutAfterCorrectBet,
|
||||
getDpmOutcomeProbabilityAfterBet,
|
||||
} from 'common/calculate-dpm'
|
||||
import { firebaseLogin } from 'web/lib/firebase/users'
|
||||
import { Bet } from 'common/bet'
|
||||
import { track } from 'web/lib/service/analytics'
|
||||
import { SignUpPrompt } from '../sign-up-prompt'
|
||||
|
||||
export function AnswerBetPanel(props: {
|
||||
answer: Answer
|
||||
|
@ -183,12 +183,7 @@ export function AnswerBetPanel(props: {
|
|||
{isSubmitting ? 'Submitting...' : 'Submit trade'}
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
className="btn self-stretch whitespace-nowrap border-none bg-gradient-to-r from-teal-500 to-green-500 px-10 text-lg font-medium normal-case hover:from-teal-600 hover:to-green-600"
|
||||
onClick={firebaseLogin}
|
||||
>
|
||||
Sign up to bet!
|
||||
</button>
|
||||
<SignUpPrompt />
|
||||
)}
|
||||
</Col>
|
||||
)
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
import { firebaseLogin } from 'web/lib/firebase/users'
|
||||
import { Bet } from 'common/bet'
|
||||
import { MAX_ANSWER_LENGTH } from 'common/answer'
|
||||
import { withTracking } from 'web/lib/service/analytics'
|
||||
|
||||
export function CreateAnswerPanel(props: { contract: FreeResponseContract }) {
|
||||
const { contract } = props
|
||||
|
@ -143,7 +144,7 @@ export function CreateAnswerPanel(props: { contract: FreeResponseContract }) {
|
|||
isSubmitting && 'loading'
|
||||
)}
|
||||
disabled={!canSubmit}
|
||||
onClick={submitAnswer}
|
||||
onClick={withTracking(submitAnswer, 'submit answer')}
|
||||
>
|
||||
Submit answer & buy
|
||||
</button>
|
||||
|
@ -151,7 +152,7 @@ export function CreateAnswerPanel(props: { contract: FreeResponseContract }) {
|
|||
text && (
|
||||
<button
|
||||
className="btn self-end whitespace-nowrap border-none bg-gradient-to-r from-teal-500 to-green-500 px-10 text-lg font-medium normal-case hover:from-teal-600 hover:to-green-600"
|
||||
onClick={firebaseLogin}
|
||||
onClick={withTracking(firebaseLogin, 'answer panel sign in')}
|
||||
>
|
||||
Sign in
|
||||
</button>
|
||||
|
|
|
@ -26,6 +26,8 @@ import { EditCategoriesButton } from './feed/category-selector'
|
|||
import { CATEGORIES } from 'common/categories'
|
||||
import { Tabs } from './layout/tabs'
|
||||
import { EditFollowingButton } from './following-button'
|
||||
import { track } from '@amplitude/analytics-browser'
|
||||
import { trackCallback } from 'web/lib/service/analytics'
|
||||
|
||||
const searchClient = algoliasearch(
|
||||
'GJQPAYENIF',
|
||||
|
@ -129,11 +131,13 @@ export function ContractSearch(props: {
|
|||
input: '!pl-10 !input !input-bordered shadow-none w-[100px]',
|
||||
resetIcon: 'mt-2 hidden sm:flex',
|
||||
}}
|
||||
onBlur={trackCallback('search')}
|
||||
/>
|
||||
<select
|
||||
className="!select !select-bordered"
|
||||
value={filter}
|
||||
onChange={(e) => setFilter(e.target.value as filter)}
|
||||
onBlur={trackCallback('select search filter')}
|
||||
>
|
||||
<option value="open">Open</option>
|
||||
<option value="closed">Closed</option>
|
||||
|
@ -145,6 +149,7 @@ export function ContractSearch(props: {
|
|||
classNames={{
|
||||
select: '!select !select-bordered',
|
||||
}}
|
||||
onBlur={trackCallback('select search sort')}
|
||||
/>
|
||||
<Configure
|
||||
facetFilters={filters}
|
||||
|
@ -296,7 +301,11 @@ function CategoryFollowSelector(props: {
|
|||
]
|
||||
: []),
|
||||
]}
|
||||
onClick={(_, index) => setMode(index === 0 ? 'categories' : 'following')}
|
||||
onClick={(_, index) => {
|
||||
const mode = index === 0 ? 'categories' : 'following'
|
||||
setMode(mode)
|
||||
track(`click ${mode} tab`)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ import { getExpectedValue, getValueFromBucket } from 'common/calculate-dpm'
|
|||
import { QuickBet, ProbBar, getColor } from './quick-bet'
|
||||
import { useContractWithPreload } from 'web/hooks/use-contract'
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { track } from '@amplitude/analytics-browser'
|
||||
import { trackCallback } from 'web/lib/service/analytics'
|
||||
|
||||
export function ContractCard(props: {
|
||||
contract: Contract
|
||||
|
@ -71,12 +73,22 @@ export function ContractCard(props: {
|
|||
if (e.ctrlKey || e.metaKey) return
|
||||
|
||||
e.preventDefault()
|
||||
track('click market card', {
|
||||
slug: contract.slug,
|
||||
contractId: contract.id,
|
||||
})
|
||||
onClick()
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Link href={contractPath(contract)}>
|
||||
<a className="absolute top-0 left-0 right-0 bottom-0" />
|
||||
<a
|
||||
onClick={trackCallback('click market card', {
|
||||
slug: contract.slug,
|
||||
contractId: contract.id,
|
||||
})}
|
||||
className="absolute top-0 left-0 right-0 bottom-0"
|
||||
/>
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -2,11 +2,13 @@ import React, { Fragment } from 'react'
|
|||
import { LinkIcon } from '@heroicons/react/outline'
|
||||
import { Menu, Transition } from '@headlessui/react'
|
||||
import clsx from 'clsx'
|
||||
|
||||
import { Contract } from 'common/contract'
|
||||
import { copyToClipboard } from 'web/lib/util/copy'
|
||||
import { contractPath } from 'web/lib/firebase/contracts'
|
||||
import { ENV_CONFIG } from 'common/envs/constants'
|
||||
import { ToastClipboard } from 'web/components/toast-clipboard'
|
||||
import { track } from 'web/lib/service/analytics'
|
||||
|
||||
function copyContractUrl(contract: Contract) {
|
||||
copyToClipboard(`https://${ENV_CONFIG.domain}${contractPath(contract)}`)
|
||||
|
@ -23,7 +25,10 @@ export function CopyLinkButton(props: {
|
|||
<Menu
|
||||
as="div"
|
||||
className="relative z-10 flex-shrink-0"
|
||||
onMouseUp={() => copyContractUrl(contract)}
|
||||
onMouseUp={() => {
|
||||
copyContractUrl(contract)
|
||||
track('copy share link')
|
||||
}}
|
||||
>
|
||||
<Menu.Button
|
||||
className={clsx(
|
||||
|
|
|
@ -9,6 +9,7 @@ import { Col } from '../layout/col'
|
|||
import { useState } from 'react'
|
||||
import { updateUser, User } from 'web/lib/firebase/users'
|
||||
import { Checkbox } from '../checkbox'
|
||||
import { track } from 'web/lib/service/analytics'
|
||||
|
||||
export function CategorySelector(props: {
|
||||
category: string
|
||||
|
@ -93,7 +94,10 @@ export function EditCategoriesButton(props: {
|
|||
className,
|
||||
'btn btn-sm btn-ghost cursor-pointer gap-2 whitespace-nowrap text-sm normal-case text-gray-700'
|
||||
)}
|
||||
onClick={() => setIsOpen(true)}
|
||||
onClick={() => {
|
||||
setIsOpen(true)
|
||||
track('edit categories button')
|
||||
}}
|
||||
>
|
||||
<PencilIcon className="inline h-4 w-4" />
|
||||
Categories
|
||||
|
|
|
@ -24,6 +24,7 @@ import { Col } from 'web/components/layout/col'
|
|||
import { getProbability } from 'common/calculate'
|
||||
import { LoadingIndicator } from 'web/components/loading-indicator'
|
||||
import { PaperAirplaneIcon } from '@heroicons/react/outline'
|
||||
import { track } from 'web/lib/service/analytics'
|
||||
|
||||
export function FeedCommentThread(props: {
|
||||
contract: Contract
|
||||
|
@ -354,6 +355,7 @@ export function CommentInput(props: {
|
|||
|
||||
async function submitComment(betId: string | undefined) {
|
||||
if (!user) {
|
||||
track('sign in to comment')
|
||||
return await firebaseLogin()
|
||||
}
|
||||
if (!comment || isSubmitting) return
|
||||
|
|
|
@ -2,6 +2,7 @@ import clsx from 'clsx'
|
|||
import { useFollows } from 'web/hooks/use-follows'
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { follow, unfollow } from 'web/lib/firebase/users'
|
||||
import { withTracking } from 'web/lib/service/analytics'
|
||||
|
||||
export function FollowButton(props: {
|
||||
isFollowing: boolean | undefined
|
||||
|
@ -34,7 +35,7 @@ export function FollowButton(props: {
|
|||
small && smallStyle,
|
||||
className
|
||||
)}
|
||||
onClick={onUnfollow}
|
||||
onClick={withTracking(onUnfollow, 'unfollow')}
|
||||
>
|
||||
Following
|
||||
</button>
|
||||
|
@ -44,7 +45,7 @@ export function FollowButton(props: {
|
|||
return (
|
||||
<button
|
||||
className={clsx('btn btn-sm', small && smallStyle, className)}
|
||||
onClick={onFollow}
|
||||
onClick={withTracking(onFollow, 'follow')}
|
||||
>
|
||||
Follow
|
||||
</button>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import clsx from 'clsx'
|
||||
import { PencilIcon } from '@heroicons/react/outline'
|
||||
|
||||
import { User } from 'common/user'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useFollowers, useFollows } from 'web/hooks/use-follows'
|
||||
|
@ -10,6 +11,7 @@ import { Modal } from './layout/modal'
|
|||
import { Tabs } from './layout/tabs'
|
||||
import { useDiscoverUsers } from 'web/hooks/use-users'
|
||||
import { TextButton } from './text-button'
|
||||
import { track } from 'web/lib/service/analytics'
|
||||
|
||||
export function FollowingButton(props: { user: User }) {
|
||||
const { user } = props
|
||||
|
@ -48,7 +50,10 @@ export function EditFollowingButton(props: { user: User; className?: string }) {
|
|||
className,
|
||||
'btn btn-sm btn-ghost cursor-pointer gap-2 whitespace-nowrap text-sm normal-case text-gray-700'
|
||||
)}
|
||||
onClick={() => setIsOpen(true)}
|
||||
onClick={() => {
|
||||
setIsOpen(true)
|
||||
track('edit following button')
|
||||
}}
|
||||
>
|
||||
<PencilIcon className="inline h-4 w-4" />
|
||||
Following
|
||||
|
|
|
@ -12,6 +12,7 @@ import { Tabs } from './layout/tabs'
|
|||
import { NoLabel, YesLabel } from './outcome-label'
|
||||
import { Col } from './layout/col'
|
||||
import { InfoTooltip } from './info-tooltip'
|
||||
import { track } from 'web/lib/service/analytics'
|
||||
|
||||
export function LiquidityPanel(props: { contract: CPMMContract }) {
|
||||
const { contract } = props
|
||||
|
@ -57,7 +58,7 @@ export function LiquidityPanel(props: { contract: CPMMContract }) {
|
|||
|
||||
function AddLiquidityPanel(props: { contract: CPMMContract }) {
|
||||
const { contract } = props
|
||||
const { id: contractId } = contract
|
||||
const { id: contractId, slug } = contract
|
||||
|
||||
const user = useUser()
|
||||
|
||||
|
@ -99,6 +100,8 @@ function AddLiquidityPanel(props: { contract: CPMMContract }) {
|
|||
}
|
||||
})
|
||||
.catch((_) => setError('Server error'))
|
||||
|
||||
track('add liquidity', { amount, contractId, slug })
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -177,6 +180,8 @@ function WithdrawLiquidityPanel(props: {
|
|||
setIsLoading(false)
|
||||
})
|
||||
.catch((_) => setError('Server error'))
|
||||
|
||||
track('withdraw liquidity')
|
||||
}
|
||||
|
||||
if (isSuccess)
|
||||
|
|
|
@ -17,6 +17,7 @@ import clsx from 'clsx'
|
|||
import { useRouter } from 'next/router'
|
||||
import NotificationsIcon from 'web/components/notifications-icon'
|
||||
import { useIsIframe } from 'web/hooks/use-is-iframe'
|
||||
import { trackCallback } from 'web/lib/service/analytics'
|
||||
|
||||
function getNavigation(username: string) {
|
||||
return [
|
||||
|
@ -106,6 +107,7 @@ function NavBarItem(props: { item: Item; currentPage: string }) {
|
|||
'block w-full py-1 px-3 text-center hover:bg-indigo-200 hover:text-indigo-700',
|
||||
currentPage === item.href && 'bg-gray-200 text-indigo-700'
|
||||
)}
|
||||
onClick={trackCallback('navbar: ' + item.name)}
|
||||
>
|
||||
<item.icon className="my-1 mx-auto h-6 w-6" />
|
||||
{item.name}
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
import Link from 'next/link'
|
||||
|
||||
import { User } from 'web/lib/firebase/users'
|
||||
import { formatMoney } from 'common/util/format'
|
||||
import { Avatar } from '../avatar'
|
||||
import { trackCallback } from 'web/lib/service/analytics'
|
||||
|
||||
export function ProfileSummary(props: { user: User }) {
|
||||
const { user } = props
|
||||
return (
|
||||
<Link href={`/${user.username}`}>
|
||||
<a className="group flex flex-row items-center gap-4 rounded-md py-3 text-gray-500 hover:bg-gray-100 hover:text-gray-700">
|
||||
<a
|
||||
onClick={trackCallback('sidebar: profile')}
|
||||
className="group flex flex-row items-center gap-4 rounded-md py-3 text-gray-500 hover:bg-gray-100 hover:text-gray-700"
|
||||
>
|
||||
<Avatar avatarUrl={user.avatarUrl} username={user.username} noLink />
|
||||
|
||||
<div className="truncate">
|
||||
|
|
|
@ -26,6 +26,7 @@ import { Row } from '../layout/row'
|
|||
import NotificationsIcon from 'web/components/notifications-icon'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { IS_PRIVATE_MANIFOLD } from 'common/envs/constants'
|
||||
import { trackCallback, withTracking } from 'web/lib/service/analytics'
|
||||
|
||||
// Create an icon from the url of an image
|
||||
function IconFromUrl(url: string): React.ComponentType<{ className?: string }> {
|
||||
|
@ -125,6 +126,7 @@ function SidebarItem(props: { item: Item; currentPage: string }) {
|
|||
return (
|
||||
<Link href={item.href} key={item.name}>
|
||||
<a
|
||||
onClick={trackCallback('sidebar: ' + item.name)}
|
||||
className={clsx(
|
||||
item.href == currentPage
|
||||
? 'bg-gray-200 text-gray-900'
|
||||
|
@ -216,7 +218,11 @@ export default function Sidebar(props: { className?: string }) {
|
|||
{user && (
|
||||
<MenuButton
|
||||
menuItems={[
|
||||
{ name: 'Sign out', href: '#', onClick: () => firebaseLogout() },
|
||||
{
|
||||
name: 'Sign out',
|
||||
href: '#',
|
||||
onClick: withTracking(firebaseLogout, 'sign out'),
|
||||
},
|
||||
]}
|
||||
buttonContent={<MoreButton />}
|
||||
/>
|
||||
|
@ -237,13 +243,16 @@ export default function Sidebar(props: { className?: string }) {
|
|||
<div className={'aligncenter flex justify-center'}>
|
||||
{user ? (
|
||||
<Link href={'/create'} passHref>
|
||||
<button className={clsx(gradient, buttonStyle)}>
|
||||
<button
|
||||
className={clsx(gradient, buttonStyle)}
|
||||
onClick={trackCallback('create question button')}
|
||||
>
|
||||
Create a question
|
||||
</button>
|
||||
</Link>
|
||||
) : (
|
||||
<button
|
||||
onClick={firebaseLogin}
|
||||
onClick={withTracking(firebaseLogin, 'sign in')}
|
||||
className={clsx(gradient, buttonStyle)}
|
||||
>
|
||||
Sign in
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import React, { Fragment } from 'react'
|
||||
import { CodeIcon } from '@heroicons/react/outline'
|
||||
import { Menu, Transition } from '@headlessui/react'
|
||||
|
||||
import { Contract } from 'common/contract'
|
||||
import { contractPath } from 'web/lib/firebase/contracts'
|
||||
import { DOMAIN } from 'common/envs/constants'
|
||||
import { copyToClipboard } from 'web/lib/util/copy'
|
||||
import { ToastClipboard } from 'web/components/toast-clipboard'
|
||||
import { track } from 'web/lib/service/analytics'
|
||||
|
||||
function copyEmbedCode(contract: Contract) {
|
||||
const title = contract.question
|
||||
|
@ -26,7 +28,10 @@ export function ShareEmbedButton(props: {
|
|||
<Menu
|
||||
as="div"
|
||||
className="relative z-10 flex-shrink-0"
|
||||
onMouseUp={() => copyEmbedCode(contract)}
|
||||
onMouseUp={() => {
|
||||
copyEmbedCode(contract)
|
||||
track('copy embed code')
|
||||
}}
|
||||
>
|
||||
<Menu.Button
|
||||
className="btn btn-xs normal-case"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react'
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { firebaseLogin } from 'web/lib/firebase/users'
|
||||
import { withTracking } from 'web/lib/service/analytics'
|
||||
|
||||
export function SignUpPrompt() {
|
||||
const user = useUser()
|
||||
|
@ -8,7 +9,7 @@ export function SignUpPrompt() {
|
|||
return user === null ? (
|
||||
<button
|
||||
className="btn flex-1 whitespace-nowrap border-none bg-gradient-to-r from-teal-500 to-green-500 px-10 text-lg font-medium normal-case hover:from-teal-600 hover:to-green-600"
|
||||
onClick={firebaseLogin}
|
||||
onClick={withTracking(firebaseLogin, 'sign up to bet')}
|
||||
>
|
||||
Sign up to bet!
|
||||
</button>
|
||||
|
|
|
@ -6,6 +6,7 @@ import { Col } from './layout/col'
|
|||
import { Row } from './layout/row'
|
||||
import { TagsList } from './tags-list'
|
||||
import { MAX_TAG_LENGTH } from 'common/contract'
|
||||
import { track } from 'web/lib/service/analytics'
|
||||
|
||||
export function TagsInput(props: { contract: Contract; className?: string }) {
|
||||
const { contract, className } = props
|
||||
|
@ -24,6 +25,7 @@ export function TagsInput(props: { contract: Contract; className?: string }) {
|
|||
})
|
||||
setIsSubmitting(false)
|
||||
setTagText('')
|
||||
track('save tags')
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import clsx from 'clsx'
|
||||
import { trackCallback } from 'web/lib/service/analytics'
|
||||
|
||||
export function TweetButton(props: { className?: string; tweetText: string }) {
|
||||
const { tweetText, className } = props
|
||||
|
@ -12,6 +13,7 @@ export function TweetButton(props: { className?: string; tweetText: string }) {
|
|||
color: '#1da1f2',
|
||||
}}
|
||||
href={getTweetHref(tweetText)}
|
||||
onClick={trackCallback('share tweet')}
|
||||
target="_blank"
|
||||
>
|
||||
<img className="mr-2" src={'/twitter-logo.svg'} width={15} height={15} />
|
||||
|
|
8
web/hooks/use-tracking.ts
Normal file
8
web/hooks/use-tracking.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { track } from '@amplitude/analytics-browser'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
export const useTracking = (eventName: string, eventProperties?: any) => {
|
||||
useEffect(() => {
|
||||
track(eventName, eventProperties)
|
||||
}, [])
|
||||
}
|
|
@ -12,15 +12,24 @@ init(ENV_CONFIG.amplitudeApiKey ?? '', undefined, { includeReferrer: true })
|
|||
|
||||
export { track }
|
||||
|
||||
// convenience function
|
||||
// Convenience functions:
|
||||
|
||||
export const trackCallback =
|
||||
(eventName: string, eventProperties?: any) => () => {
|
||||
track(eventName, eventProperties)
|
||||
}
|
||||
|
||||
export const withTracking =
|
||||
(
|
||||
f: (() => void) | (() => Promise<void>),
|
||||
eventName: string,
|
||||
eventProperties?: any
|
||||
) =>
|
||||
() =>
|
||||
Promise.all([f(), track(eventName, eventProperties).promise])
|
||||
async () => {
|
||||
const promise = f()
|
||||
track(eventName, eventProperties)
|
||||
await promise
|
||||
}
|
||||
|
||||
export async function identifyUser(userId: string) {
|
||||
setUserId(userId)
|
||||
|
|
|
@ -40,6 +40,7 @@ import { useIsIframe } from 'web/hooks/use-is-iframe'
|
|||
import ContractEmbedPage from '../embed/[username]/[contractSlug]'
|
||||
import { useBets } from 'web/hooks/use-bets'
|
||||
import { AlertBox } from 'web/components/alert-box'
|
||||
import { useTracking } from 'web/hooks/use-tracking'
|
||||
|
||||
export const getStaticProps = fromPropz(getStaticPropz)
|
||||
export async function getStaticPropz(props: {
|
||||
|
@ -108,6 +109,12 @@ export function ContractPageContent(
|
|||
|
||||
const contract = useContractWithPreload(props.contract) ?? props.contract
|
||||
|
||||
useTracking('view market', {
|
||||
slug: contract.slug,
|
||||
contractId: contract.id,
|
||||
creatorId: contract.creatorId,
|
||||
})
|
||||
|
||||
const bets = useBets(contract.id) ?? props.bets
|
||||
// Sort for now to see if bug is fixed.
|
||||
comments.sort((c1, c2) => c1.createdTime - c2.createdTime)
|
||||
|
|
|
@ -5,6 +5,7 @@ import { getUserByUsername, User } from 'web/lib/firebase/users'
|
|||
import { UserPage } from 'web/components/user-page'
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import Custom404 from '../404'
|
||||
import { useTracking } from 'web/hooks/use-tracking'
|
||||
|
||||
export default function UserProfile(props: {
|
||||
tab?: 'markets' | 'comments' | 'bets'
|
||||
|
@ -12,6 +13,7 @@ export default function UserProfile(props: {
|
|||
const router = useRouter()
|
||||
const [user, setUser] = useState<User | null | 'loading'>('loading')
|
||||
const { username } = router.query as { username: string }
|
||||
|
||||
useEffect(() => {
|
||||
if (username) {
|
||||
getUserByUsername(username).then(setUser)
|
||||
|
@ -20,6 +22,8 @@ export default function UserProfile(props: {
|
|||
|
||||
const currentUser = useUser()
|
||||
|
||||
useTracking('view user profile', { username })
|
||||
|
||||
if (user === 'loading') return <></>
|
||||
|
||||
return user ? (
|
||||
|
|
|
@ -6,6 +6,8 @@ import { FundsSelector } from 'web/components/yes-no-selector'
|
|||
import { useUser } from 'web/hooks/use-user'
|
||||
import { checkoutURL } from 'web/lib/service/stripe'
|
||||
import { Page } from 'web/components/page'
|
||||
import { useTracking } from 'web/hooks/use-tracking'
|
||||
import { trackCallback } from 'web/lib/service/analytics'
|
||||
|
||||
export default function AddFundsPage() {
|
||||
const user = useUser()
|
||||
|
@ -14,6 +16,8 @@ export default function AddFundsPage() {
|
|||
2500
|
||||
)
|
||||
|
||||
useTracking('view add funds')
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<SEO
|
||||
|
@ -59,6 +63,7 @@ export default function AddFundsPage() {
|
|||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary w-full bg-gradient-to-r from-indigo-500 to-blue-500 font-medium hover:from-indigo-600 hover:to-blue-600"
|
||||
onClick={trackCallback('checkout', { amount: amountSelected })}
|
||||
>
|
||||
Checkout
|
||||
</button>
|
||||
|
|
|
@ -19,6 +19,7 @@ import { getAllCharityTxns } from 'web/lib/firebase/txns'
|
|||
import { manaToUSD } from 'common/util/format'
|
||||
import { quadraticMatches } from 'common/quadratic-funding'
|
||||
import { Txn } from 'common/txn'
|
||||
import { useTracking } from 'web/hooks/use-tracking'
|
||||
|
||||
export async function getStaticProps() {
|
||||
const txns = await getAllCharityTxns()
|
||||
|
@ -95,6 +96,8 @@ export default function Charity(props: {
|
|||
[charities, query]
|
||||
)
|
||||
|
||||
useTracking('view charity')
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<Col className="w-full rounded px-4 py-6 sm:px-8 xl:w-[125%]">
|
||||
|
|
|
@ -22,11 +22,14 @@ import { removeUndefinedProps } from 'common/util/object'
|
|||
import { CATEGORIES } from 'common/categories'
|
||||
import { ChoicesToggleGroup } from 'web/components/choices-toggle-group'
|
||||
import { track } from 'web/lib/service/analytics'
|
||||
import { useTracking } from 'web/hooks/use-tracking'
|
||||
import { useWarnUnsavedChanges } from 'web/hooks/use-warn-unsaved-changes'
|
||||
|
||||
export default function Create() {
|
||||
const [question, setQuestion] = useState('')
|
||||
|
||||
useTracking('view create page')
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<div className="mx-auto w-full max-w-2xl">
|
||||
|
|
|
@ -9,6 +9,8 @@ import { ContractSearch } from 'web/components/contract-search'
|
|||
import { Contract } from 'common/contract'
|
||||
import { ContractPageContent } from './[username]/[contractSlug]'
|
||||
import { getContractFromSlug } from 'web/lib/firebase/contracts'
|
||||
import { useTracking } from 'web/hooks/use-tracking'
|
||||
import { track } from 'web/lib/service/analytics'
|
||||
|
||||
const Home = () => {
|
||||
const user = useUser()
|
||||
|
@ -16,6 +18,8 @@ const Home = () => {
|
|||
|
||||
const router = useRouter()
|
||||
|
||||
useTracking('view home')
|
||||
|
||||
if (user === null) {
|
||||
Router.replace('/')
|
||||
return <></>
|
||||
|
@ -42,7 +46,10 @@ const Home = () => {
|
|||
<button
|
||||
type="button"
|
||||
className="fixed bottom-[70px] right-3 inline-flex items-center rounded-full border border-transparent bg-indigo-600 p-3 text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 lg:hidden"
|
||||
onClick={() => router.push('/create')}
|
||||
onClick={() => {
|
||||
router.push('/create')
|
||||
track('mobile create button')
|
||||
}}
|
||||
>
|
||||
<PlusSmIcon className="h-8 w-8" aria-hidden="true" />
|
||||
</button>
|
||||
|
|
|
@ -4,6 +4,7 @@ import { Page } from 'web/components/page'
|
|||
import { getTopCreators, getTopTraders, User } from 'web/lib/firebase/users'
|
||||
import { formatMoney } from 'common/util/format'
|
||||
import { fromPropz, usePropz } from 'web/hooks/use-propz'
|
||||
import { useTracking } from 'web/hooks/use-tracking'
|
||||
|
||||
export const getStaticProps = fromPropz(getStaticPropz)
|
||||
export async function getStaticPropz() {
|
||||
|
@ -32,6 +33,8 @@ export default function Leaderboards(props: {
|
|||
}
|
||||
const { topTraders, topCreators } = props
|
||||
|
||||
useTracking('view leaderboards')
|
||||
|
||||
return (
|
||||
<Page margin>
|
||||
<Col className="items-center gap-10 lg:flex-row">
|
||||
|
|
Loading…
Reference in New Issue
Block a user