From eafc257a82461d54951d1b5bbef4fa3f5518e8bb Mon Sep 17 00:00:00 2001 From: Dylan Jeffers Date: Thu, 5 Feb 2026 11:31:31 -0800 Subject: [PATCH 1/2] Add explore analytics --- packages/common/src/models/Analytics.ts | 42 +++++++++++++++++++ .../components/FeaturedArtistCoinTracks.tsx | 5 ++- .../components/FeaturedPlaylists.tsx | 5 ++- .../components/ForYouTracks.tsx | 5 ++- .../components/RecentlyPlayed.tsx | 5 ++- .../hooks/useExploreSectionTracking.ts | 27 ++++++++++++ .../desktop/ArtistCoinTracksSection.tsx | 4 +- .../desktop/ArtistSpotlightSection.tsx | 4 +- .../components/desktop/CollectionArtCard.tsx | 36 ++++++++++++++-- .../desktop/FeaturedPlaylistsSection.tsx | 4 +- .../desktop/FeaturedRemixContestsSection.tsx | 4 +- .../desktop/FeelingLuckySection.tsx | 4 +- .../desktop/LabelSpotlightSection.tsx | 4 +- .../desktop/RecentSearchesSection.tsx | 4 +- .../desktop/RecentlyPlayedSection.tsx | 4 +- .../desktop/RecommendedTracksSection.tsx | 4 +- .../components/desktop/TrackArtCard.tsx | 26 ++++++++++-- .../desktop/TrendingPlaylistsSection.tsx | 4 +- .../UndergroundTrendingTracksSection.tsx | 6 ++- .../components/desktop/UserArtCard.tsx | 26 ++++++++++-- .../desktop/useExploreSectionTracking.ts | 29 +++++++++++++ 21 files changed, 213 insertions(+), 39 deletions(-) create mode 100644 packages/mobile/src/screens/explore-screen/hooks/useExploreSectionTracking.ts create mode 100644 packages/web/src/pages/search-explore-page/components/desktop/useExploreSectionTracking.ts diff --git a/packages/common/src/models/Analytics.ts b/packages/common/src/models/Analytics.ts index 77cc750f3c7..8543d81f450 100644 --- a/packages/common/src/models/Analytics.ts +++ b/packages/common/src/models/Analytics.ts @@ -308,6 +308,10 @@ export enum Name { SEARCH_RESULT_SELECT = 'Search: Result Select', SEARCH_TAB_CLICK = 'Search: Tab Click', + // Explore + EXPLORE_SECTION_VIEW = 'Explore: Section View', + EXPLORE_SECTION_CLICK = 'Explore: Section Click', + // Errors ERROR_PAGE = 'Error Page', NOT_FOUND_PAGE = 'Not Found Page', @@ -1552,6 +1556,42 @@ type SearchResultSelect = { kind: 'track' | 'profile' | 'playlist' | 'album' } +// Explore +export type ExploreSectionName = + | 'Recommended Tracks' + | 'Artist Coin Tracks' + | 'Recently Played' + | 'Quick Search' + | 'Featured Playlists' + | 'Featured Remix Contests' + | 'Underground Trending Tracks' + | 'Artist Spotlight' + | 'Label Spotlight' + | 'Active Discussions' + | 'Downloads Available' + | 'Mood Grid' + | 'Trending Playlists' + | 'Most Shared' + | 'Best Selling' + | 'Recent Premium Tracks' + | 'Feeling Lucky' + | 'Recent Searches' + +type ExploreSectionView = { + eventName: Name.EXPLORE_SECTION_VIEW + section: ExploreSectionName + source: 'web' | 'mobile' +} + +type ExploreSectionClick = { + eventName: Name.EXPLORE_SECTION_CLICK + section: ExploreSectionName + source: 'web' | 'mobile' + id?: ID + kind?: 'track' | 'profile' | 'playlist' | 'album' | 'mood' | 'preset' + link?: string +} + type ListenGated = { eventName: Name.LISTEN_GATED trackId: string @@ -3127,6 +3167,8 @@ export type AllTrackingEvents = | SearchTag | SearchMoreResults | SearchResultSelect + | ExploreSectionView + | ExploreSectionClick | ListenGated | ErrorPage | NotFoundPage diff --git a/packages/mobile/src/screens/explore-screen/components/FeaturedArtistCoinTracks.tsx b/packages/mobile/src/screens/explore-screen/components/FeaturedArtistCoinTracks.tsx index 1bcc9e4d148..7e71979c9a7 100644 --- a/packages/mobile/src/screens/explore-screen/components/FeaturedArtistCoinTracks.tsx +++ b/packages/mobile/src/screens/explore-screen/components/FeaturedArtistCoinTracks.tsx @@ -4,13 +4,14 @@ import { useExploreContent } from '@audius/common/api' import { exploreMessages as messages } from '@audius/common/messages' import { QueueSource } from '@audius/common/store' -import { useDeferredElement } from '../../../hooks/useDeferredElement' +import { useExploreSectionTracking } from '../hooks/useExploreSectionTracking' import { ExploreSection } from './ExploreSection' import { TrackTileCarousel } from './TrackTileCarousel' export const FeaturedArtistCoinTracks = () => { - const { InViewWrapper, inView } = useDeferredElement() + const { InViewWrapper, inView } = + useExploreSectionTracking('Artist Coin Tracks') const { data, isPending } = useExploreContent({ enabled: inView }) return ( diff --git a/packages/mobile/src/screens/explore-screen/components/FeaturedPlaylists.tsx b/packages/mobile/src/screens/explore-screen/components/FeaturedPlaylists.tsx index 9f1c0f352f1..0bf456d6856 100644 --- a/packages/mobile/src/screens/explore-screen/components/FeaturedPlaylists.tsx +++ b/packages/mobile/src/screens/explore-screen/components/FeaturedPlaylists.tsx @@ -6,13 +6,14 @@ import { exploreMessages as messages } from '@audius/common/messages' import { useTheme } from '@audius/harmony-native' import { CollectionList } from 'app/components/collection-list' -import { useDeferredElement } from '../../../hooks/useDeferredElement' +import { useExploreSectionTracking } from '../hooks/useExploreSectionTracking' import { ExploreSection } from './ExploreSection' export const FeaturedPlaylists = () => { const { spacing } = useTheme() - const { InViewWrapper, inView } = useDeferredElement() + const { InViewWrapper, inView } = + useExploreSectionTracking('Featured Playlists') const { data: exploreContent } = useExploreContent({ enabled: inView }) const { data: playlists } = useCollections( diff --git a/packages/mobile/src/screens/explore-screen/components/ForYouTracks.tsx b/packages/mobile/src/screens/explore-screen/components/ForYouTracks.tsx index 10d021a6096..9a34e5f2398 100644 --- a/packages/mobile/src/screens/explore-screen/components/ForYouTracks.tsx +++ b/packages/mobile/src/screens/explore-screen/components/ForYouTracks.tsx @@ -5,13 +5,14 @@ import { exploreMessages as messages } from '@audius/common/messages' import { QueueSource } from '@audius/common/store' import { full } from '@audius/sdk' -import { useDeferredElement } from 'app/hooks/useDeferredElement' +import { useExploreSectionTracking } from '../hooks/useExploreSectionTracking' import { ExploreSection } from './ExploreSection' import { TrackTileCarousel } from './TrackTileCarousel' export const ForYouTracks = () => { - const { inView, InViewWrapper } = useDeferredElement() + const { inView, InViewWrapper } = + useExploreSectionTracking('Recommended Tracks') const { data: recommendedTracks, isPending } = useRecommendedTracks( { pageSize: 10, timeRange: full.GetRecommendedTracksTimeEnum.Week }, { enabled: inView } diff --git a/packages/mobile/src/screens/explore-screen/components/RecentlyPlayed.tsx b/packages/mobile/src/screens/explore-screen/components/RecentlyPlayed.tsx index 03042a85cec..18aa1c2826b 100644 --- a/packages/mobile/src/screens/explore-screen/components/RecentlyPlayed.tsx +++ b/packages/mobile/src/screens/explore-screen/components/RecentlyPlayed.tsx @@ -5,13 +5,14 @@ import { exploreMessages as messages } from '@audius/common/messages' import { useTheme } from '@audius/harmony-native' import { TrackCardList } from 'app/components/track-card-list' -import { useDeferredElement } from 'app/hooks/useDeferredElement' + +import { useExploreSectionTracking } from '../hooks/useExploreSectionTracking' import { ExploreSection } from './ExploreSection' export const RecentlyPlayedTracks = () => { const { spacing } = useTheme() - const { InViewWrapper, inView } = useDeferredElement() + const { InViewWrapper, inView } = useExploreSectionTracking('Recently Played') const { data: recentlyPlayedTracks } = useRecentlyPlayedTracks( { pageSize: 10 }, { enabled: inView } diff --git a/packages/mobile/src/screens/explore-screen/hooks/useExploreSectionTracking.ts b/packages/mobile/src/screens/explore-screen/hooks/useExploreSectionTracking.ts new file mode 100644 index 00000000000..14554fcea17 --- /dev/null +++ b/packages/mobile/src/screens/explore-screen/hooks/useExploreSectionTracking.ts @@ -0,0 +1,27 @@ +import { useEffect } from 'react' + +import { useAnalytics } from '@audius/common/hooks' +import type { ExploreSectionName } from '@audius/common/models' +import { Name } from '@audius/common/models' + +import { useDeferredElement } from 'app/hooks/useDeferredElement' + +/** + * Hook to track explore section impressions when they come into view on mobile + */ +export const useExploreSectionTracking = (sectionName: ExploreSectionName) => { + const { inView, InViewWrapper } = useDeferredElement() + const { trackEvent } = useAnalytics() + + useEffect(() => { + if (inView) { + trackEvent({ + eventName: Name.EXPLORE_SECTION_VIEW, + section: sectionName, + source: 'mobile' + }) + } + }, [inView, sectionName, trackEvent]) + + return { inView, InViewWrapper } +} diff --git a/packages/web/src/pages/search-explore-page/components/desktop/ArtistCoinTracksSection.tsx b/packages/web/src/pages/search-explore-page/components/desktop/ArtistCoinTracksSection.tsx index a56279c7d73..0ed267abeb0 100644 --- a/packages/web/src/pages/search-explore-page/components/desktop/ArtistCoinTracksSection.tsx +++ b/packages/web/src/pages/search-explore-page/components/desktop/ArtistCoinTracksSection.tsx @@ -3,10 +3,10 @@ import { exploreMessages as messages } from '@audius/common/messages' import { Carousel } from './Carousel' import { TilePairs, TileSkeletons } from './TileHelpers' -import { useDeferredElement } from './useDeferredElement' +import { useExploreSectionTracking } from './useExploreSectionTracking' export const ArtistCoinTracksSection = () => { - const { ref, inView } = useDeferredElement() + const { ref, inView } = useExploreSectionTracking('Artist Coin Tracks') const { data, isLoading, isError, isSuccess } = useExploreContent({ enabled: inView diff --git a/packages/web/src/pages/search-explore-page/components/desktop/ArtistSpotlightSection.tsx b/packages/web/src/pages/search-explore-page/components/desktop/ArtistSpotlightSection.tsx index efc79fd6c25..c8491ba69c9 100644 --- a/packages/web/src/pages/search-explore-page/components/desktop/ArtistSpotlightSection.tsx +++ b/packages/web/src/pages/search-explore-page/components/desktop/ArtistSpotlightSection.tsx @@ -5,10 +5,10 @@ import { UserCard, UserCardSkeleton } from 'components/user-card' import { useIsMobile } from 'hooks/useIsMobile' import { Carousel } from './Carousel' -import { useDeferredElement } from './useDeferredElement' +import { useExploreSectionTracking } from './useExploreSectionTracking' export const ArtistSpotlightSection = () => { - const { ref, inView } = useDeferredElement() + const { ref, inView } = useExploreSectionTracking('Artist Spotlight') const { data, isLoading, isError, isSuccess } = useExploreContent({ enabled: inView }) diff --git a/packages/web/src/pages/search-explore-page/components/desktop/CollectionArtCard.tsx b/packages/web/src/pages/search-explore-page/components/desktop/CollectionArtCard.tsx index b1f207b8b47..7e1e7cf042c 100644 --- a/packages/web/src/pages/search-explore-page/components/desktop/CollectionArtCard.tsx +++ b/packages/web/src/pages/search-explore-page/components/desktop/CollectionArtCard.tsx @@ -1,7 +1,13 @@ import { useCallback, useState } from 'react' import { useCollection, useUser } from '@audius/common/api' -import { ID, SquareSizes } from '@audius/common/models' +import { useAnalytics } from '@audius/common/hooks' +import { + ID, + SquareSizes, + ExploreSectionName, + Name +} from '@audius/common/models' import { Flex } from '@audius/harmony' import { useNavigate } from 'react-router' @@ -11,23 +17,47 @@ import { UserLink } from 'components/link/UserLink' import PerspectiveCard from 'components/perspective-card/PerspectiveCard' import { FavoriteStats } from 'components/stats/FavoriteStats' import { RepostStats } from 'components/stats/RepostStats' +import { useIsMobile } from 'hooks/useIsMobile' import { UserListEntityType } from 'store/application/ui/userListModal/types' type CollectionArtCardProps = { id: ID + sectionName?: ExploreSectionName } const ARTWORK_SIZE = 240 -export const CollectionArtCard = ({ id }: CollectionArtCardProps) => { +export const CollectionArtCard = ({ + id, + sectionName +}: CollectionArtCardProps) => { const [isPerspectiveDisabled] = useState(false) const navigate = useNavigate() + const { trackEvent } = useAnalytics() + const isMobile = useIsMobile() const { data: partialCollection } = useCollection(id) const goToPlaylist = useCallback(() => { if (!partialCollection?.permalink) return + if (sectionName) { + trackEvent({ + eventName: Name.EXPLORE_SECTION_CLICK, + section: sectionName, + source: isMobile ? 'mobile' : 'web', + id, + kind: 'playlist', + link: partialCollection.permalink + }) + } navigate(partialCollection.permalink) - }, [navigate, partialCollection?.permalink]) + }, [ + navigate, + partialCollection?.permalink, + sectionName, + id, + trackEvent, + isMobile + ]) const { data: user } = useUser(partialCollection?.playlist_owner_id) diff --git a/packages/web/src/pages/search-explore-page/components/desktop/FeaturedPlaylistsSection.tsx b/packages/web/src/pages/search-explore-page/components/desktop/FeaturedPlaylistsSection.tsx index d6dd668b7f7..2677d92060b 100644 --- a/packages/web/src/pages/search-explore-page/components/desktop/FeaturedPlaylistsSection.tsx +++ b/packages/web/src/pages/search-explore-page/components/desktop/FeaturedPlaylistsSection.tsx @@ -5,10 +5,10 @@ import { CollectionCard, CollectionCardSkeleton } from 'components/collection' import { useIsMobile } from 'hooks/useIsMobile' import { Carousel } from './Carousel' -import { useDeferredElement } from './useDeferredElement' +import { useExploreSectionTracking } from './useExploreSectionTracking' export const FeaturedPlaylistsSection = () => { - const { ref, inView } = useDeferredElement() + const { ref, inView } = useExploreSectionTracking('Featured Playlists') const { data, isLoading, isError, isSuccess } = useExploreContent({ enabled: inView diff --git a/packages/web/src/pages/search-explore-page/components/desktop/FeaturedRemixContestsSection.tsx b/packages/web/src/pages/search-explore-page/components/desktop/FeaturedRemixContestsSection.tsx index 2edcff8bbfc..2eb0f9cbff1 100644 --- a/packages/web/src/pages/search-explore-page/components/desktop/FeaturedRemixContestsSection.tsx +++ b/packages/web/src/pages/search-explore-page/components/desktop/FeaturedRemixContestsSection.tsx @@ -8,10 +8,10 @@ import { import { useIsMobile } from 'hooks/useIsMobile' import { Carousel } from './Carousel' -import { useDeferredElement } from './useDeferredElement' +import { useExploreSectionTracking } from './useExploreSectionTracking' export const FeaturedRemixContestsSection = () => { - const { ref, inView } = useDeferredElement() + const { ref, inView } = useExploreSectionTracking('Featured Remix Contests') const { data, isLoading, isError, isSuccess } = useExploreContent({ enabled: inView diff --git a/packages/web/src/pages/search-explore-page/components/desktop/FeelingLuckySection.tsx b/packages/web/src/pages/search-explore-page/components/desktop/FeelingLuckySection.tsx index 477fb1295e2..a5d2280882e 100644 --- a/packages/web/src/pages/search-explore-page/components/desktop/FeelingLuckySection.tsx +++ b/packages/web/src/pages/search-explore-page/components/desktop/FeelingLuckySection.tsx @@ -13,10 +13,10 @@ import { TrackTile as MobileTrackTile } from 'components/track/mobile/TrackTile' import { TrackTileSize } from 'components/track/types' import { useIsMobile } from 'hooks/useIsMobile' -import { useDeferredElement } from './useDeferredElement' +import { useExploreSectionTracking } from './useExploreSectionTracking' export const FeelingLuckySection = () => { - const { ref, inView } = useDeferredElement() + const { ref, inView } = useExploreSectionTracking('Feeling Lucky') const isMobile = useIsMobile() const { data: feelingLuckyTrack, diff --git a/packages/web/src/pages/search-explore-page/components/desktop/LabelSpotlightSection.tsx b/packages/web/src/pages/search-explore-page/components/desktop/LabelSpotlightSection.tsx index ecd1f2d0789..54798769302 100644 --- a/packages/web/src/pages/search-explore-page/components/desktop/LabelSpotlightSection.tsx +++ b/packages/web/src/pages/search-explore-page/components/desktop/LabelSpotlightSection.tsx @@ -5,10 +5,10 @@ import { UserCard, UserCardSkeleton } from 'components/user-card' import { useIsMobile } from 'hooks/useIsMobile' import { Carousel } from './Carousel' -import { useDeferredElement } from './useDeferredElement' +import { useExploreSectionTracking } from './useExploreSectionTracking' export const LabelSpotlightSection = () => { - const { ref, inView } = useDeferredElement() + const { ref, inView } = useExploreSectionTracking('Label Spotlight') const { data, isLoading, isError, isSuccess } = useExploreContent({ enabled: inView }) diff --git a/packages/web/src/pages/search-explore-page/components/desktop/RecentSearchesSection.tsx b/packages/web/src/pages/search-explore-page/components/desktop/RecentSearchesSection.tsx index ae4dd6b9c76..8bd91ffa43d 100644 --- a/packages/web/src/pages/search-explore-page/components/desktop/RecentSearchesSection.tsx +++ b/packages/web/src/pages/search-explore-page/components/desktop/RecentSearchesSection.tsx @@ -3,10 +3,10 @@ import { Flex } from '@audius/harmony' import { useIsMobile } from 'hooks/useIsMobile' import { RecentSearches } from 'pages/search-page/RecentSearches' -import { useDeferredElement } from './useDeferredElement' +import { useExploreSectionTracking } from './useExploreSectionTracking' export const RecentSearchesSection = () => { - const { ref, inView } = useDeferredElement() + const { ref, inView } = useExploreSectionTracking('Recent Searches') const isMobile = useIsMobile() return ( diff --git a/packages/web/src/pages/search-explore-page/components/desktop/RecentlyPlayedSection.tsx b/packages/web/src/pages/search-explore-page/components/desktop/RecentlyPlayedSection.tsx index 5129f05ffea..e4a8ea2a399 100644 --- a/packages/web/src/pages/search-explore-page/components/desktop/RecentlyPlayedSection.tsx +++ b/packages/web/src/pages/search-explore-page/components/desktop/RecentlyPlayedSection.tsx @@ -5,10 +5,10 @@ import { TrackCard, TrackCardSkeleton } from 'components/track/TrackCard' import { useIsMobile } from 'hooks/useIsMobile' import { Carousel } from './Carousel' -import { useDeferredElement } from './useDeferredElement' +import { useExploreSectionTracking } from './useExploreSectionTracking' export const RecentlyPlayedSection = () => { - const { ref, inView } = useDeferredElement() + const { ref, inView } = useExploreSectionTracking('Recently Played') const { data, isLoading, isError, isSuccess } = useRecentlyPlayedTracks( { pageSize: 10 }, { enabled: inView } diff --git a/packages/web/src/pages/search-explore-page/components/desktop/RecommendedTracksSection.tsx b/packages/web/src/pages/search-explore-page/components/desktop/RecommendedTracksSection.tsx index a066ba8433e..7931dd42ff6 100644 --- a/packages/web/src/pages/search-explore-page/components/desktop/RecommendedTracksSection.tsx +++ b/packages/web/src/pages/search-explore-page/components/desktop/RecommendedTracksSection.tsx @@ -4,10 +4,10 @@ import { full } from '@audius/sdk' import { Carousel } from './Carousel' import { TilePairs, TileSkeletons } from './TileHelpers' -import { useDeferredElement } from './useDeferredElement' +import { useExploreSectionTracking } from './useExploreSectionTracking' export const RecommendedTracksSection = () => { - const { ref, inView } = useDeferredElement() + const { ref, inView } = useExploreSectionTracking('Recommended Tracks') const { data, isLoading, isError, isSuccess } = useRecommendedTracks( { pageSize: 10, diff --git a/packages/web/src/pages/search-explore-page/components/desktop/TrackArtCard.tsx b/packages/web/src/pages/search-explore-page/components/desktop/TrackArtCard.tsx index f329a006a77..03744f91c30 100644 --- a/packages/web/src/pages/search-explore-page/components/desktop/TrackArtCard.tsx +++ b/packages/web/src/pages/search-explore-page/components/desktop/TrackArtCard.tsx @@ -1,7 +1,13 @@ import { useCallback } from 'react' import { useRemixContest, useTrack } from '@audius/common/api' -import { ID, SquareSizes } from '@audius/common/models' +import { useAnalytics } from '@audius/common/hooks' +import { + ID, + SquareSizes, + ExploreSectionName, + Name +} from '@audius/common/models' import { dayjs, formatContestDeadlineWithStatus } from '@audius/common/utils' import { Flex, Skeleton, Text } from '@audius/harmony' import { useNavigate } from 'react-router' @@ -10,9 +16,11 @@ import { TrackLink } from 'components/link/TrackLink' import { UserLink } from 'components/link/UserLink' import PerspectiveCard from 'components/perspective-card/PerspectiveCard' import { TrackArtwork } from 'components/track/TrackArtwork' +import { useIsMobile } from 'hooks/useIsMobile' type TrackArtCardProps = { id: ID + sectionName?: ExploreSectionName } const messages = { @@ -29,8 +37,10 @@ const messages = { const ARTWORK_SIZE = 240 -export const TrackArtCard = ({ id }: TrackArtCardProps) => { +export const TrackArtCard = ({ id, sectionName }: TrackArtCardProps) => { const navigate = useNavigate() + const { trackEvent } = useAnalytics() + const isMobile = useIsMobile() const { data: track, isLoading: isTrackLoading } = useTrack(id) const { data: contest, isLoading: isContestLoading } = useRemixContest(id) @@ -39,8 +49,18 @@ export const TrackArtCard = ({ id }: TrackArtCardProps) => { const goToTrack = useCallback(() => { if (!track?.permalink) return + if (sectionName) { + trackEvent({ + eventName: Name.EXPLORE_SECTION_CLICK, + section: sectionName, + source: isMobile ? 'mobile' : 'web', + id, + kind: 'track', + link: track.permalink + }) + } navigate(track.permalink) - }, [navigate, track?.permalink]) + }, [navigate, track?.permalink, sectionName, id, trackEvent, isMobile]) if (!track) return null diff --git a/packages/web/src/pages/search-explore-page/components/desktop/TrendingPlaylistsSection.tsx b/packages/web/src/pages/search-explore-page/components/desktop/TrendingPlaylistsSection.tsx index 2ca65ab9c2e..b400fd2e7ac 100644 --- a/packages/web/src/pages/search-explore-page/components/desktop/TrendingPlaylistsSection.tsx +++ b/packages/web/src/pages/search-explore-page/components/desktop/TrendingPlaylistsSection.tsx @@ -17,7 +17,7 @@ import { MOBILE_TILE_WIDTH, TILE_WIDTH } from './constants' -import { useDeferredElement } from './useDeferredElement' +import { useExploreSectionTracking } from './useExploreSectionTracking' type TileType = typeof DesktopCollectionTile | typeof MobileCollectionTile @@ -119,7 +119,7 @@ const CollectionLineupCarousel = ({ } export const TrendingPlaylistsSection = () => { - const { ref, inView } = useDeferredElement() + const { ref, inView } = useExploreSectionTracking('Trending Playlists') const isMobile = useIsMobile() const size = isMobile ? TrackTileSize.SMALL : TrackTileSize.LARGE const { lineup, isError, isSuccess, isLoading, play, pause, togglePlay } = diff --git a/packages/web/src/pages/search-explore-page/components/desktop/UndergroundTrendingTracksSection.tsx b/packages/web/src/pages/search-explore-page/components/desktop/UndergroundTrendingTracksSection.tsx index d5b5d1e108b..ad03c21d18e 100644 --- a/packages/web/src/pages/search-explore-page/components/desktop/UndergroundTrendingTracksSection.tsx +++ b/packages/web/src/pages/search-explore-page/components/desktop/UndergroundTrendingTracksSection.tsx @@ -6,10 +6,12 @@ import { Status } from '@audius/common/models' import { Carousel } from './Carousel' import { TilePairs, TileSkeletons } from './TileHelpers' -import { useDeferredElement } from './useDeferredElement' +import { useExploreSectionTracking } from './useExploreSectionTracking' export const UndergroundTrendingTracksSection = () => { - const { ref, inView } = useDeferredElement() + const { ref, inView } = useExploreSectionTracking( + 'Underground Trending Tracks' + ) const { data: undergroundTrendingTracks, isLoading, diff --git a/packages/web/src/pages/search-explore-page/components/desktop/UserArtCard.tsx b/packages/web/src/pages/search-explore-page/components/desktop/UserArtCard.tsx index 5b68ed06a18..62a50119e6a 100644 --- a/packages/web/src/pages/search-explore-page/components/desktop/UserArtCard.tsx +++ b/packages/web/src/pages/search-explore-page/components/desktop/UserArtCard.tsx @@ -2,7 +2,13 @@ import { useCallback, useEffect } from 'react' import { useUser } from '@audius/common/api' import { imageBlank as placeholderArt } from '@audius/common/assets' -import { SquareSizes, ID } from '@audius/common/models' +import { useAnalytics } from '@audius/common/hooks' +import { + SquareSizes, + ID, + ExploreSectionName, + Name +} from '@audius/common/models' import { formatCount, route } from '@audius/common/utils' import cn from 'classnames' import { connect } from 'react-redux' @@ -38,6 +44,7 @@ type OwnProps = { index: number isLoading?: boolean setDidLoad?: (index: number) => void + sectionName?: ExploreSectionName } type UserArtCardProps = OwnProps & @@ -58,14 +65,27 @@ const UserArtCard = g( user, setFollowerUser, setModalVisibility, - goToRoute + goToRoute, + sectionName }) => { const { user_id, name, handle, follower_count } = user + const { trackEvent } = useAnalytics() + const isMobile = typeof window !== 'undefined' && window.innerWidth < 768 const goToProfile = useCallback(() => { + if (sectionName) { + trackEvent({ + eventName: Name.EXPLORE_SECTION_CLICK, + section: sectionName, + source: isMobile ? 'mobile' : 'web', + id: user_id, + kind: 'profile', + link: profilePage(handle) + }) + } const link = profilePage(handle) goToRoute(link) - }, [handle, goToRoute]) + }, [handle, goToRoute, sectionName, user_id, trackEvent, isMobile]) const onClickFollowers = useCallback(() => { setFollowerUser(user_id) diff --git a/packages/web/src/pages/search-explore-page/components/desktop/useExploreSectionTracking.ts b/packages/web/src/pages/search-explore-page/components/desktop/useExploreSectionTracking.ts new file mode 100644 index 00000000000..b5237ea450b --- /dev/null +++ b/packages/web/src/pages/search-explore-page/components/desktop/useExploreSectionTracking.ts @@ -0,0 +1,29 @@ +import { useEffect } from 'react' + +import { useAnalytics } from '@audius/common/hooks' +import { ExploreSectionName, Name } from '@audius/common/models' + +import { useIsMobile } from 'hooks/useIsMobile' + +import { useDeferredElement } from './useDeferredElement' + +/** + * Hook to track explore section impressions when they come into view + */ +export const useExploreSectionTracking = (sectionName: ExploreSectionName) => { + const { ref, inView } = useDeferredElement() + const { trackEvent } = useAnalytics() + const isMobile = useIsMobile() + + useEffect(() => { + if (inView) { + trackEvent({ + eventName: Name.EXPLORE_SECTION_VIEW, + section: sectionName, + source: isMobile ? 'mobile' : 'web' + }) + } + }, [inView, sectionName, isMobile, trackEvent]) + + return { ref, inView } +} From 84b5817ebe5969a504c30fcbe6f32bf8d5ddb63a Mon Sep 17 00:00:00 2001 From: Dylan Jeffers Date: Mon, 9 Feb 2026 13:09:21 -0800 Subject: [PATCH 2/2] Fixes --- .../search-explore-page/components/desktop/UserArtCard.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/web/src/pages/search-explore-page/components/desktop/UserArtCard.tsx b/packages/web/src/pages/search-explore-page/components/desktop/UserArtCard.tsx index 62a50119e6a..99c6d0d11a0 100644 --- a/packages/web/src/pages/search-explore-page/components/desktop/UserArtCard.tsx +++ b/packages/web/src/pages/search-explore-page/components/desktop/UserArtCard.tsx @@ -17,6 +17,7 @@ import { Dispatch } from 'redux' import DynamicImage from 'components/dynamic-image/DynamicImage' import PerspectiveCard from 'components/perspective-card/PerspectiveCard' import UserBadges from 'components/user-badges/UserBadges' +import { useIsMobile } from 'hooks/useIsMobile' import { useProfilePicture } from 'hooks/useProfilePicture' import { setUsers, @@ -70,7 +71,7 @@ const UserArtCard = g( }) => { const { user_id, name, handle, follower_count } = user const { trackEvent } = useAnalytics() - const isMobile = typeof window !== 'undefined' && window.innerWidth < 768 + const isMobile = useIsMobile() const goToProfile = useCallback(() => { if (sectionName) {