feat: Collection page log events (#4971)
* Log collection page view * Make property names/intention more clear * Remove console log * Add event for Activity tab * Filter events (buy now, marketplaces, and price range) * Handle trait items * Bump collection stats mobile padding * Use shouldLogImpression to conditionally fire event * Adding back trace on Collection page, still necessary * Add back address property * Drop Buy Now log, not part of first set * Update filter properties to match spreadsheet * Only trigger price range log if inputs contain a value * Fix ordering on Page Names * Capitalize text * Add constant for filter types * Add chainId as property
This commit is contained in:
parent
e2fea4a5fb
commit
d86120a257
@ -14,6 +14,9 @@ export enum EventName {
|
|||||||
PAGE_VIEWED = 'Page Viewed',
|
PAGE_VIEWED = 'Page Viewed',
|
||||||
NAVBAR_SEARCH_SELECTED = 'Navbar Search Selected',
|
NAVBAR_SEARCH_SELECTED = 'Navbar Search Selected',
|
||||||
NAVBAR_SEARCH_EXITED = 'Navbar Search Exited',
|
NAVBAR_SEARCH_EXITED = 'Navbar Search Exited',
|
||||||
|
NFT_ACTIVITY_SELECTED = 'NFT Activity Selected',
|
||||||
|
NFT_FILTER_OPENED = 'NFT Collection Filter Opened',
|
||||||
|
NFT_FILTER_SELECTED = 'NFT Filter Selected',
|
||||||
SWAP_AUTOROUTER_VISUALIZATION_EXPANDED = 'Swap Autorouter Visualization Expanded',
|
SWAP_AUTOROUTER_VISUALIZATION_EXPANDED = 'Swap Autorouter Visualization Expanded',
|
||||||
SWAP_DETAILS_EXPANDED = 'Swap Details Expanded',
|
SWAP_DETAILS_EXPANDED = 'Swap Details Expanded',
|
||||||
SWAP_MAX_TOKEN_AMOUNT_SELECTED = 'Swap Max Token Amount Selected',
|
SWAP_MAX_TOKEN_AMOUNT_SELECTED = 'Swap Max Token Amount Selected',
|
||||||
@ -74,6 +77,7 @@ export enum SWAP_PRICE_UPDATE_USER_RESPONSE {
|
|||||||
* Known pages in the app. Highest order context.
|
* Known pages in the app. Highest order context.
|
||||||
*/
|
*/
|
||||||
export enum PageName {
|
export enum PageName {
|
||||||
|
NFT_COLLECTION_PAGE = 'nft-collection-page',
|
||||||
NFT_DETAILS_PAGE = 'nft-details-page',
|
NFT_DETAILS_PAGE = 'nft-details-page',
|
||||||
TOKEN_DETAILS_PAGE = 'token-details',
|
TOKEN_DETAILS_PAGE = 'token-details',
|
||||||
TOKENS_PAGE = 'tokens-page',
|
TOKENS_PAGE = 'tokens-page',
|
||||||
@ -116,6 +120,9 @@ export enum ElementName {
|
|||||||
IMPORT_TOKEN_BUTTON = 'import-token-button',
|
IMPORT_TOKEN_BUTTON = 'import-token-button',
|
||||||
MAX_TOKEN_AMOUNT_BUTTON = 'max-token-amount-button',
|
MAX_TOKEN_AMOUNT_BUTTON = 'max-token-amount-button',
|
||||||
NAVBAR_SEARCH_INPUT = 'navbar-search-input',
|
NAVBAR_SEARCH_INPUT = 'navbar-search-input',
|
||||||
|
NFT_ACTIVITY_TAB = 'nft-activity-tab',
|
||||||
|
NFT_FILTER_BUTTON = 'nft-filter-button',
|
||||||
|
NFT_FILTER_OPTION = 'nft-filter-option',
|
||||||
PRICE_UPDATE_ACCEPT_BUTTON = 'price-update-accept-button',
|
PRICE_UPDATE_ACCEPT_BUTTON = 'price-update-accept-button',
|
||||||
SWAP_BUTTON = 'swap-button',
|
SWAP_BUTTON = 'swap-button',
|
||||||
SWAP_DETAILS_DROPDOWN = 'swap-details-dropdown',
|
SWAP_DETAILS_DROPDOWN = 'swap-details-dropdown',
|
||||||
@ -137,3 +144,12 @@ export enum Event {
|
|||||||
onSelect = 'onSelect',
|
onSelect = 'onSelect',
|
||||||
// alphabetize additional events.
|
// alphabetize additional events.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Known Filter Types for NFTs
|
||||||
|
*/
|
||||||
|
export enum FilterTypes {
|
||||||
|
MARKETPLACE = 'Marketplace',
|
||||||
|
PRICE_RANGE = 'Price Range',
|
||||||
|
TRAIT = 'Trait',
|
||||||
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { ElementName, Event, EventName } from 'analytics/constants'
|
||||||
|
import { TraceEvent } from 'analytics/TraceEvent'
|
||||||
import { Box } from 'nft/components/Box'
|
import { Box } from 'nft/components/Box'
|
||||||
import { Row } from 'nft/components/Flex'
|
import { Row } from 'nft/components/Flex'
|
||||||
import { useIsCollectionLoading } from 'nft/hooks'
|
import { useIsCollectionLoading } from 'nft/hooks'
|
||||||
@ -27,6 +29,11 @@ export const ActivitySwitcher = ({
|
|||||||
>
|
>
|
||||||
Items
|
Items
|
||||||
</Box>
|
</Box>
|
||||||
|
<TraceEvent
|
||||||
|
events={[Event.onClick]}
|
||||||
|
element={ElementName.NFT_ACTIVITY_TAB}
|
||||||
|
name={EventName.NFT_ACTIVITY_SELECTED}
|
||||||
|
>
|
||||||
<Box
|
<Box
|
||||||
as="button"
|
as="button"
|
||||||
className={!showActivity ? styles.activitySwitcherToggle : styles.selectedActivitySwitcherToggle}
|
className={!showActivity ? styles.activitySwitcherToggle : styles.selectedActivitySwitcherToggle}
|
||||||
@ -34,6 +41,7 @@ export const ActivitySwitcher = ({
|
|||||||
>
|
>
|
||||||
Activity
|
Activity
|
||||||
</Box>
|
</Box>
|
||||||
|
</TraceEvent>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
import { useWeb3React } from '@web3-react/core'
|
||||||
|
import { ElementName, Event, EventName } from 'analytics/constants'
|
||||||
|
import { TraceEvent } from 'analytics/TraceEvent'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import { loadingAnimation } from 'components/Loader/styled'
|
import { loadingAnimation } from 'components/Loader/styled'
|
||||||
import useDebounce from 'hooks/useDebounce'
|
import useDebounce from 'hooks/useDebounce'
|
||||||
@ -104,6 +107,7 @@ export const LoadingButton = styled.div`
|
|||||||
`
|
`
|
||||||
|
|
||||||
export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerified }: CollectionNftsProps) => {
|
export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerified }: CollectionNftsProps) => {
|
||||||
|
const { chainId } = useWeb3React()
|
||||||
const traits = useCollectionFilters((state) => state.traits)
|
const traits = useCollectionFilters((state) => state.traits)
|
||||||
const minPrice = useCollectionFilters((state) => state.minPrice)
|
const minPrice = useCollectionFilters((state) => state.minPrice)
|
||||||
const maxPrice = useCollectionFilters((state) => state.maxPrice)
|
const maxPrice = useCollectionFilters((state) => state.maxPrice)
|
||||||
@ -356,12 +360,20 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie
|
|||||||
<Box backgroundColor="backgroundFloating" width="full" style={{ backdropFilter: 'blur(24px)' }}>
|
<Box backgroundColor="backgroundFloating" width="full" style={{ backdropFilter: 'blur(24px)' }}>
|
||||||
<ActionsContainer>
|
<ActionsContainer>
|
||||||
<Row gap="12">
|
<Row gap="12">
|
||||||
|
<TraceEvent
|
||||||
|
events={[Event.onClick]}
|
||||||
|
element={ElementName.NFT_FILTER_BUTTON}
|
||||||
|
name={EventName.NFT_FILTER_OPENED}
|
||||||
|
shouldLogImpression={!isFiltersExpanded}
|
||||||
|
properties={{ collection_address: contractAddress, chain_id: chainId }}
|
||||||
|
>
|
||||||
<FilterButton
|
<FilterButton
|
||||||
isMobile={isMobile}
|
isMobile={isMobile}
|
||||||
isFiltersExpanded={isFiltersExpanded}
|
isFiltersExpanded={isFiltersExpanded}
|
||||||
onClick={() => setFiltersExpanded(!isFiltersExpanded)}
|
onClick={() => setFiltersExpanded(!isFiltersExpanded)}
|
||||||
collectionCount={collectionNfts?.[0]?.totalCount ?? 0}
|
collectionCount={collectionNfts?.[0]?.totalCount ?? 0}
|
||||||
/>
|
/>
|
||||||
|
</TraceEvent>
|
||||||
<SortDropdown dropDownOptions={sortDropDownOptions} />
|
<SortDropdown dropDownOptions={sortDropDownOptions} />
|
||||||
<CollectionSearch />
|
<CollectionSearch />
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -277,7 +277,7 @@ const StatsRow = ({ stats, isMobile, ...props }: { stats: GenieCollection; isMob
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row gap={{ sm: '20', md: '60' }} {...props}>
|
<Row gap={{ sm: '36', md: '60' }} {...props}>
|
||||||
{isCollectionStatsLoading && statsLoadingSkeleton}
|
{isCollectionStatsLoading && statsLoadingSkeleton}
|
||||||
{stats.floorPrice ? (
|
{stats.floorPrice ? (
|
||||||
<StatsItem label="Global floor" isMobile={isMobile ?? false}>
|
<StatsItem label="Global floor" isMobile={isMobile ?? false}>
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { sendAnalyticsEvent } from 'analytics'
|
||||||
|
import { EventName, FilterTypes } from 'analytics/constants'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import { Box } from 'nft/components/Box'
|
import { Box } from 'nft/components/Box'
|
||||||
import * as styles from 'nft/components/collection/Filters.css'
|
import * as styles from 'nft/components/collection/Filters.css'
|
||||||
@ -48,6 +50,7 @@ const MarketplaceItem = ({
|
|||||||
removeMarket(value)
|
removeMarket(value)
|
||||||
setCheckboxSelected(false)
|
setCheckboxSelected(false)
|
||||||
}
|
}
|
||||||
|
sendAnalyticsEvent(EventName.NFT_FILTER_SELECTED, { filter_type: FilterTypes.MARKETPLACE })
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import 'rc-slider/assets/index.css'
|
import 'rc-slider/assets/index.css'
|
||||||
|
|
||||||
|
import { sendAnalyticsEvent } from 'analytics'
|
||||||
|
import { EventName, FilterTypes } from 'analytics/constants'
|
||||||
import { Box } from 'nft/components/Box'
|
import { Box } from 'nft/components/Box'
|
||||||
import { Row } from 'nft/components/Flex'
|
import { Row } from 'nft/components/Flex'
|
||||||
import { NumericInput } from 'nft/components/layout/Input'
|
import { NumericInput } from 'nft/components/layout/Input'
|
||||||
@ -54,6 +56,8 @@ export const PriceRange = () => {
|
|||||||
const handleBlur: FocusEventHandler<HTMLInputElement> = (e) => {
|
const handleBlur: FocusEventHandler<HTMLInputElement> = (e) => {
|
||||||
e.currentTarget.placeholder = placeholderText
|
e.currentTarget.placeholder = placeholderText
|
||||||
setPlaceholderText('')
|
setPlaceholderText('')
|
||||||
|
if (minPrice || maxPrice)
|
||||||
|
sendAnalyticsEvent(EventName.NFT_FILTER_SELECTED, { filter_type: FilterTypes.PRICE_RANGE })
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateMinPriceRange = (v: FormEvent<HTMLInputElement>) => {
|
const updateMinPriceRange = (v: FormEvent<HTMLInputElement>) => {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { sendAnalyticsEvent } from 'analytics'
|
||||||
|
import { EventName, FilterTypes } from 'analytics/constants'
|
||||||
import useDebounce from 'hooks/useDebounce'
|
import useDebounce from 'hooks/useDebounce'
|
||||||
import { Box } from 'nft/components/Box'
|
import { Box } from 'nft/components/Box'
|
||||||
import { Column, Row } from 'nft/components/Flex'
|
import { Column, Row } from 'nft/components/Flex'
|
||||||
@ -53,6 +55,7 @@ const TraitItem = ({
|
|||||||
removeTrait(trait)
|
removeTrait(trait)
|
||||||
setCheckboxSelected(false)
|
setCheckboxSelected(false)
|
||||||
}
|
}
|
||||||
|
sendAnalyticsEvent(EventName.NFT_FILTER_SELECTED, { filter_type: FilterTypes.TRAIT })
|
||||||
}
|
}
|
||||||
|
|
||||||
const showFullTraitName = shouldShow && trait_type === trait.trait_type && trait_value === trait.trait_value
|
const showFullTraitName = shouldShow && trait_type === trait.trait_type && trait_value === trait.trait_value
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
import { useWeb3React } from '@web3-react/core'
|
||||||
|
import { PageName } from 'analytics/constants'
|
||||||
|
import { Trace } from 'analytics/Trace'
|
||||||
import { MobileHoverBag } from 'nft/components/bag/MobileHoverBag'
|
import { MobileHoverBag } from 'nft/components/bag/MobileHoverBag'
|
||||||
import { AnimatedBox, Box } from 'nft/components/Box'
|
import { AnimatedBox, Box } from 'nft/components/Box'
|
||||||
import { Activity, ActivitySwitcher, CollectionNfts, CollectionStats, Filters } from 'nft/components/collection'
|
import { Activity, ActivitySwitcher, CollectionNfts, CollectionStats, Filters } from 'nft/components/collection'
|
||||||
@ -25,6 +28,7 @@ const Collection = () => {
|
|||||||
const isActivityToggled = pathname.includes('/activity')
|
const isActivityToggled = pathname.includes('/activity')
|
||||||
const setMarketCount = useCollectionFilters((state) => state.setMarketCount)
|
const setMarketCount = useCollectionFilters((state) => state.setMarketCount)
|
||||||
const isBagExpanded = useBag((state) => state.bagExpanded)
|
const isBagExpanded = useBag((state) => state.bagExpanded)
|
||||||
|
const { chainId } = useWeb3React()
|
||||||
|
|
||||||
const { data: collectionStats, isLoading } = useQuery(['collectionStats', contractAddress], () =>
|
const { data: collectionStats, isLoading } = useQuery(['collectionStats', contractAddress], () =>
|
||||||
CollectionStatsFetcher(contractAddress as string)
|
CollectionStatsFetcher(contractAddress as string)
|
||||||
@ -61,6 +65,11 @@ const Collection = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<Trace
|
||||||
|
page={PageName.NFT_COLLECTION_PAGE}
|
||||||
|
properties={{ collection_address: contractAddress, chain_id: chainId }}
|
||||||
|
shouldLogImpression
|
||||||
|
>
|
||||||
<Column width="full">
|
<Column width="full">
|
||||||
{contractAddress ? (
|
{contractAddress ? (
|
||||||
<>
|
<>
|
||||||
@ -130,6 +139,7 @@ const Collection = () => {
|
|||||||
!isLoading && <div className={styles.noCollectionAssets}>No collection assets exist at this address</div>
|
!isLoading && <div className={styles.noCollectionAssets}>No collection assets exist at this address</div>
|
||||||
)}
|
)}
|
||||||
</Column>
|
</Column>
|
||||||
|
</Trace>
|
||||||
<MobileHoverBag />
|
<MobileHoverBag />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user