From ceb8e129b7109cb00ce5810f41a057781e08f57c Mon Sep 17 00:00:00 2001 From: sliptype Date: Fri, 2 Aug 2024 16:16:30 -0500 Subject: [PATCH 1/2] Add analytics for search v2 --- packages/common/src/api/search.ts | 49 ++++++++++++++++--- packages/common/src/models/Analytics.ts | 33 +++++++++++-- .../search-results/AllResults.tsx | 30 +++++++++--- .../search-results/PlaylistResults.tsx | 48 +++++++++++++----- .../search-results/ProfileResults.tsx | 48 +++++++++++++----- .../search-results/TrackResults.tsx | 41 +++++++++++----- .../common/store/cache/tracks/sagaHelpers.ts | 20 ++++++++ .../search-results/AlbumResults.tsx | 16 ++++-- .../search-results/PlaylistResults.tsx | 16 ++++-- .../search-results/ProfileResults.tsx | 16 ++++-- .../components/desktop/SearchPageContent.jsx | 2 +- 11 files changed, 255 insertions(+), 64 deletions(-) diff --git a/packages/common/src/api/search.ts b/packages/common/src/api/search.ts index 6ec9c6b9217..94c75b72363 100644 --- a/packages/common/src/api/search.ts +++ b/packages/common/src/api/search.ts @@ -1,8 +1,9 @@ import { Mood } from '@audius/sdk' +import { make } from 'common/store/analytics/actions' import { isEmpty } from 'lodash' import { createApi } from '~/audius-query' -import { UserTrackMetadata } from '~/models' +import { Name, SearchSource, UserTrackMetadata } from '~/models' import { ID } from '~/models/Identifiers' import { FeatureFlags } from '~/services' import { SearchKind } from '~/store' @@ -28,6 +29,7 @@ type getSearchArgs = { category?: SearchCategory limit?: number offset?: number + source?: SearchSource } & SearchFilters const getMinMaxFromBpm = (bpm?: string) => { @@ -48,10 +50,17 @@ const searchApi = createApi({ getSearchResults: { fetch: async ( args: getSearchArgs, - { apiClient, audiusBackend, getFeatureEnabled } + { apiClient, audiusBackend, getFeatureEnabled, dispatch } ) => { - const { category, currentUserId, query, limit, offset, ...filters } = - args + const { + category, + currentUserId, + query, + limit, + offset, + source = 'search results page', + ...filters + } = args const isUSDCEnabled = await getFeatureEnabled( FeatureFlags.USDC_PURCHASES @@ -70,7 +79,7 @@ const searchApi = createApi({ const [bpmMin, bpmMax] = getMinMaxFromBpm(filters.bpm) const searchTags = async () => { - return await audiusBackend.searchTags({ + const searchParams = { userTagCount: 1, kind, query: query.toLowerCase().slice(1), @@ -80,11 +89,24 @@ const searchApi = createApi({ bpmMin, bpmMax, key: formatMusicalKey(filters.key) - }) + } + + // Fire analytics only for the first page of results + if (offset === 0) { + dispatch( + make(Name.SEARCH_TAG_SEARCH, { + term: query, + source, + ...searchParams + }) + ) + } + + return await audiusBackend.searchTags(searchParams) } const search = async () => { - return await apiClient.getSearchFull({ + const searchParams = { kind, currentUserId, query, @@ -95,7 +117,18 @@ const searchApi = createApi({ bpmMin, bpmMax, key: formatMusicalKey(filters.key) - }) + } + // Fire analytics only for the first page of results + if (offset === 0) { + dispatch( + make(Name.SEARCH_SEARCH, { + term: query, + source, + ...searchParams + }) + ) + } + return await apiClient.getSearchFull(searchParams) } const results = query?.[0] === '#' ? await searchTags() : await search() diff --git a/packages/common/src/models/Analytics.ts b/packages/common/src/models/Analytics.ts index da970438d11..b817ea7d6a4 100644 --- a/packages/common/src/models/Analytics.ts +++ b/packages/common/src/models/Analytics.ts @@ -221,6 +221,8 @@ export enum Name { // Track Edits TRACK_EDIT_ACCESS_CHANGED = 'Track Edit: Access Changed', + TRACK_EDIT_BPM_CHANGED = 'Track Edit: BPM Changed', + TRACK_EDIT_MUSICAL_KEY_CHANGED = 'Track Edit: Musical Key Changed', // Collection Edits COLLECTION_EDIT_ACCESS_CHANGED = 'Collection Edit: Access Changed', @@ -1167,6 +1169,20 @@ type TrackEditAccessChanged = { to: TrackAccessType } +type TrackEditBpmChanged = { + eventName: Name.TRACK_EDIT_BPM_CHANGED + id: number + from: number + to: number +} + +type TrackEditMusicalKeyChanged = { + eventName: Name.TRACK_EDIT_MUSICAL_KEY_CHANGED + id: number + from: string + to: string +} + // Collection Edits type CollectionEditAccessChanged = { eventName: Name.COLLECTION_EDIT_ACCESS_CHANGED @@ -1444,33 +1460,40 @@ type ModalClosed = { name: string } +export type SearchSource = + | 'autocomplete' + | 'search results page' + | 'more results page' + // Search type SearchTerm = { eventName: Name.SEARCH_SEARCH term: string - source: 'autocomplete' | 'search results page' | 'more results page' + source: SearchSource } type SearchTag = { eventName: Name.SEARCH_TAG_SEARCH tag: string - source: 'autocomplete' | 'search results page' | 'more results page' + source: SearchSource } type SearchMoreResults = { eventName: Name.SEARCH_MORE_RESULTS term: string - source: 'autocomplete' | 'search results page' | 'more results page' + source: SearchSource } type SearchResultSelect = { eventName: Name.SEARCH_RESULT_SELECT term: string - source: 'autocomplete' | 'search results page' | 'more results page' + source: SearchSource id: ID kind: 'track' | 'profile' | 'playlist' | 'album' } +// This event is no longer fired with search v2 +// Use page views instead type SearchTabClick = { eventName: Name.SEARCH_TAB_CLICK term: string @@ -2515,6 +2538,8 @@ export type AllTrackingEvents = | TrackDownloadSuccessfulDownloadSingle | TrackDownloadFailedDownloadSingle | TrackEditAccessChanged + | TrackEditBpmChanged + | TrackEditMusicalKeyChanged | CollectionEditAccessChanged | CollectionEdit | TrackUploadSuccess diff --git a/packages/mobile/src/screens/search-screen-v2/search-results/AllResults.tsx b/packages/mobile/src/screens/search-screen-v2/search-results/AllResults.tsx index ba2be0e3daa..98bf43623d5 100644 --- a/packages/mobile/src/screens/search-screen-v2/search-results/AllResults.tsx +++ b/packages/mobile/src/screens/search-screen-v2/search-results/AllResults.tsx @@ -1,6 +1,6 @@ import { useCallback, useMemo } from 'react' -import { Kind, Status } from '@audius/common/models' +import { Kind, Name, Status } from '@audius/common/models' import { searchActions, type SearchItem as SearchItemType @@ -11,10 +11,11 @@ import { useDispatch } from 'react-redux' import { Box, Divider, Flex, Text } from '@audius/harmony-native' import { SectionList } from 'app/components/core' +import { make, track as record } from 'app/services/analytics' import { NoResultsTile } from '../NoResultsTile' import { SearchItem, SearchItemSkeleton } from '../SearchItem' -import { useGetSearchResults } from '../searchState' +import { useGetSearchResults, useSearchQuery } from '../searchState' const { addItem: addRecentSearch } = searchActions @@ -38,13 +39,28 @@ export const SearchSectionHeader = (props: SearchSectionHeaderProps) => { const AllResultsItem = ({ item }: { - item: SearchItemType & { status?: Status } + item: SearchItemType & { status?: Status; isAlbum?: boolean } }) => { const dispatch = useDispatch() + const [query] = useSearchQuery() const handlePress = useCallback(() => { dispatch(addRecentSearch({ searchItem: item })) - }, [item, dispatch]) + + record( + make({ + eventName: Name.SEARCH_RESULT_SELECT, + term: query, + source: 'search results page', + id: item.id, + kind: { + [Kind.COLLECTIONS]: item.isAlbum ? 'album' : 'playlist', + [Kind.TRACKS]: 'track', + [Kind.USERS]: 'profile' + }[item.kind] + }) + ) + }, [item, dispatch, query]) return item.status === Status.LOADING ? ( @@ -115,14 +131,16 @@ export const AllResults = () => { title: 'playlists', data: data.playlists.map(({ playlist_id }) => ({ id: playlist_id, - kind: Kind.COLLECTIONS + kind: Kind.COLLECTIONS, + isAlbum: false })) }, { title: 'albums', data: data.albums.map(({ playlist_id }) => ({ id: playlist_id, - kind: Kind.COLLECTIONS + kind: Kind.COLLECTIONS, + isAlbum: true })) } ].filter((section) => section.data.length > 0) diff --git a/packages/mobile/src/screens/search-screen-v2/search-results/PlaylistResults.tsx b/packages/mobile/src/screens/search-screen-v2/search-results/PlaylistResults.tsx index be669d49e13..f4adc652db5 100644 --- a/packages/mobile/src/screens/search-screen-v2/search-results/PlaylistResults.tsx +++ b/packages/mobile/src/screens/search-screen-v2/search-results/PlaylistResults.tsx @@ -1,13 +1,21 @@ -import { Kind, Status } from '@audius/common/models' +import { useCallback } from 'react' + +import type { ID } from '@audius/common/models' +import { Kind, Name, Status } from '@audius/common/models' import { searchActions } from '@audius/common/store' import { useDispatch } from 'react-redux' import { Flex, useTheme } from '@audius/harmony-native' import { CollectionList } from 'app/components/collection-list/CollectionList' +import { make, track as record } from 'app/services/analytics' import { NoResultsTile } from '../NoResultsTile' import { SearchCatalogTile } from '../SearchCatalogTile' -import { useGetSearchResults, useIsEmptySearch } from '../searchState' +import { + useGetSearchResults, + useIsEmptySearch, + useSearchQuery +} from '../searchState' const { addItem: addRecentSearch } = searchActions @@ -15,9 +23,34 @@ export const PlaylistResults = () => { const dispatch = useDispatch() const { spacing } = useTheme() const { data, status } = useGetSearchResults('playlists') + const [query] = useSearchQuery() const isEmptySearch = useIsEmptySearch() const hasNoResults = (!data || data.length === 0) && status === Status.SUCCESS + const handlePress = useCallback( + (id: ID) => { + dispatch( + addRecentSearch({ + searchItem: { + kind: Kind.COLLECTIONS, + id + } + }) + ) + + record( + make({ + eventName: Name.SEARCH_RESULT_SELECT, + term: query, + source: 'search results page', + id, + kind: 'playlist' + }) + ) + }, + [dispatch, query] + ) + if (isEmptySearch) return return ( @@ -33,16 +66,7 @@ export const PlaylistResults = () => { keyboardShouldPersistTaps='handled' isLoading={status === Status.LOADING} collection={data as any[]} - onCollectionPress={(id) => { - dispatch( - addRecentSearch({ - searchItem: { - kind: Kind.COLLECTIONS, - id - } - }) - ) - }} + onCollectionPress={handlePress} /> )} diff --git a/packages/mobile/src/screens/search-screen-v2/search-results/ProfileResults.tsx b/packages/mobile/src/screens/search-screen-v2/search-results/ProfileResults.tsx index 356d20f08ef..346d494b19d 100644 --- a/packages/mobile/src/screens/search-screen-v2/search-results/ProfileResults.tsx +++ b/packages/mobile/src/screens/search-screen-v2/search-results/ProfileResults.tsx @@ -1,13 +1,21 @@ -import { Kind, Status } from '@audius/common/models' +import { useCallback } from 'react' + +import type { ID } from '@audius/common/models' +import { Kind, Name, Status } from '@audius/common/models' import { searchActions } from '@audius/common/store' import { useDispatch } from 'react-redux' import { Flex, useTheme } from '@audius/harmony-native' import { UserList } from 'app/components/user-list' +import { make, track as record } from 'app/services/analytics' import { NoResultsTile } from '../NoResultsTile' import { SearchCatalogTile } from '../SearchCatalogTile' -import { useGetSearchResults, useIsEmptySearch } from '../searchState' +import { + useGetSearchResults, + useIsEmptySearch, + useSearchQuery +} from '../searchState' const { addItem: addRecentSearch } = searchActions @@ -15,9 +23,34 @@ export const ProfileResults = () => { const dispatch = useDispatch() const { spacing } = useTheme() const { data, status } = useGetSearchResults('users') + const [query] = useSearchQuery() const isEmptySearch = useIsEmptySearch() const hasNoResults = (!data || data.length === 0) && status === Status.SUCCESS + const handlePress = useCallback( + (id: ID) => { + dispatch( + addRecentSearch({ + searchItem: { + kind: Kind.USERS, + id + } + }) + ) + + record( + make({ + eventName: Name.SEARCH_RESULT_SELECT, + term: query, + source: 'search results page', + id, + kind: 'profile' + }) + ) + }, + [dispatch, query] + ) + if (isEmptySearch) return return ( @@ -33,16 +66,7 @@ export const ProfileResults = () => { }} profiles={data} isLoading={status === Status.LOADING} - onCardPress={(id) => { - dispatch( - addRecentSearch({ - searchItem: { - kind: Kind.USERS, - id - } - }) - ) - }} + onCardPress={handlePress} /> )} diff --git a/packages/mobile/src/screens/search-screen-v2/search-results/TrackResults.tsx b/packages/mobile/src/screens/search-screen-v2/search-results/TrackResults.tsx index c7419767709..74896073a55 100644 --- a/packages/mobile/src/screens/search-screen-v2/search-results/TrackResults.tsx +++ b/packages/mobile/src/screens/search-screen-v2/search-results/TrackResults.tsx @@ -1,6 +1,7 @@ import { useCallback, useEffect } from 'react' -import { Kind, Status } from '@audius/common/models' +import type { ID } from '@audius/common/models' +import { Kind, Name, Status } from '@audius/common/models' import { lineupSelectors, searchResultsPageTracksLineupActions, @@ -14,6 +15,7 @@ import { useDebounce } from 'react-use' import { Flex } from '@audius/harmony-native' import { Lineup } from 'app/components/lineup' +import { make, track as record } from 'app/services/analytics' import { NoResultsTile } from '../NoResultsTile' import { SearchCatalogTile } from '../SearchCatalogTile' @@ -76,6 +78,31 @@ export const TrackResults = () => { [getResults] ) + const handlePress = useCallback( + (id: ID) => { + Keyboard.dismiss() + dispatch( + addRecentSearch({ + searchItem: { + kind: Kind.TRACKS, + id + } + }) + ) + + record( + make({ + eventName: Name.SEARCH_RESULT_SELECT, + term: query, + source: 'search results page', + id, + kind: 'track' + }) + ) + }, + [dispatch, query] + ) + if (isEmptySearch) return if ( (!lineup || lineup.entries.length === 0) && @@ -91,17 +118,7 @@ export const TrackResults = () => { lineup={lineup} loadMore={loadMore} keyboardShouldPersistTaps='handled' - onPressItem={(id) => { - Keyboard.dismiss() - dispatch( - addRecentSearch({ - searchItem: { - kind: Kind.TRACKS, - id - } - }) - ) - }} + onPressItem={handlePress} /> ) diff --git a/packages/web/src/common/store/cache/tracks/sagaHelpers.ts b/packages/web/src/common/store/cache/tracks/sagaHelpers.ts index afde7d21913..37970c89c09 100644 --- a/packages/web/src/common/store/cache/tracks/sagaHelpers.ts +++ b/packages/web/src/common/store/cache/tracks/sagaHelpers.ts @@ -59,4 +59,24 @@ export function* recordEditTrackAnalytics(prevTrack: Track, newTrack: Track) { }) ) } + + if (prevTrack.bpm !== newTrack.bpm) { + yield* put( + make(Name.TRACK_EDIT_BPM_CHANGED, { + id: newTrack.track_id, + from: prevTrack.bpm, + to: newTrack.bpm + }) + ) + } + + if (prevTrack.musical_key !== newTrack.musical_key) { + yield* put( + make(Name.TRACK_EDIT_MUSICAL_KEY_CHANGED, { + id: newTrack.track_id, + from: prevTrack.musical_key, + to: newTrack.musical_key + }) + ) + } } diff --git a/packages/web/src/pages/search-page-v2/search-results/AlbumResults.tsx b/packages/web/src/pages/search-page-v2/search-results/AlbumResults.tsx index 0788d651c23..5dfc8f8b309 100644 --- a/packages/web/src/pages/search-page-v2/search-results/AlbumResults.tsx +++ b/packages/web/src/pages/search-page-v2/search-results/AlbumResults.tsx @@ -1,17 +1,18 @@ import { useCallback } from 'react' -import { ID, Kind, Status } from '@audius/common/models' +import { ID, Kind, Name, Status } from '@audius/common/models' import { searchActions } from '@audius/common/store' import { Box, Flex, Text, useTheme } from '@audius/harmony' import { range } from 'lodash' import { useDispatch } from 'react-redux' +import { make } from 'common/store/analytics/actions' import { CollectionCard } from 'components/collection' import { useIsMobile } from 'hooks/useIsMobile' import { NoResultsTile } from '../NoResultsTile' import { SortMethodFilterButton } from '../SortMethodFilterButton' -import { useGetSearchResults } from '../utils' +import { useGetSearchResults, useSearchParams } from '../utils' const { addItem: addRecentSearch } = searchActions @@ -27,6 +28,7 @@ type AlbumResultsProps = { export const AlbumResults = (props: AlbumResultsProps) => { const { limit = 100, ids, skeletonCount = 10 } = props + const { query } = useSearchParams() const isMobile = useIsMobile() const dispatch = useDispatch() @@ -45,8 +47,16 @@ export const AlbumResults = (props: AlbumResultsProps) => { }) ) } + dispatch( + make(Name.SEARCH_RESULT_SELECT, { + term: query, + source: 'search results page', + id, + kind: 'playlist' + }) + ) }, - [dispatch] + [dispatch, query] ) return ( diff --git a/packages/web/src/pages/search-page-v2/search-results/PlaylistResults.tsx b/packages/web/src/pages/search-page-v2/search-results/PlaylistResults.tsx index 0372afc5ae5..9d8d43b8bc5 100644 --- a/packages/web/src/pages/search-page-v2/search-results/PlaylistResults.tsx +++ b/packages/web/src/pages/search-page-v2/search-results/PlaylistResults.tsx @@ -1,17 +1,18 @@ import { useCallback } from 'react' -import { ID, Kind, Status } from '@audius/common/models' +import { ID, Kind, Name, Status } from '@audius/common/models' import { searchActions } from '@audius/common/store' import { Box, Flex, Text, useTheme } from '@audius/harmony' import { range } from 'lodash' import { useDispatch } from 'react-redux' +import { make } from 'common/store/analytics/actions' import { CollectionCard } from 'components/collection' import { useIsMobile } from 'hooks/useIsMobile' import { NoResultsTile } from '../NoResultsTile' import { SortMethodFilterButton } from '../SortMethodFilterButton' -import { useGetSearchResults } from '../utils' +import { useGetSearchResults, useSearchParams } from '../utils' const { addItem: addRecentSearch } = searchActions @@ -29,6 +30,7 @@ type PlaylistResultsProps = { export const PlaylistResults = (props: PlaylistResultsProps) => { const { limit = 100, ids, skeletonCount = 10 } = props + const { query } = useSearchParams() const isMobile = useIsMobile() const dispatch = useDispatch() @@ -46,9 +48,17 @@ export const PlaylistResults = (props: PlaylistResultsProps) => { } }) ) + dispatch( + make(Name.SEARCH_RESULT_SELECT, { + term: query, + source: 'search results page', + id, + kind: 'playlist' + }) + ) } }, - [dispatch] + [dispatch, query] ) return ( diff --git a/packages/web/src/pages/search-page-v2/search-results/ProfileResults.tsx b/packages/web/src/pages/search-page-v2/search-results/ProfileResults.tsx index fcafd2d2d75..6a62352d035 100644 --- a/packages/web/src/pages/search-page-v2/search-results/ProfileResults.tsx +++ b/packages/web/src/pages/search-page-v2/search-results/ProfileResults.tsx @@ -1,17 +1,18 @@ import { useCallback } from 'react' -import { ID, Kind, Status } from '@audius/common/models' +import { ID, Kind, Name, Status } from '@audius/common/models' import { searchActions } from '@audius/common/store' import { Box, Flex, Text, useTheme } from '@audius/harmony' import { range } from 'lodash' import { useDispatch } from 'react-redux' +import { make } from 'common/store/analytics/actions' import { UserCard } from 'components/user-card' import { useIsMobile } from 'hooks/useIsMobile' import { NoResultsTile } from '../NoResultsTile' import { SortMethodFilterButton } from '../SortMethodFilterButton' -import { useGetSearchResults } from '../utils' +import { useGetSearchResults, useSearchParams } from '../utils' const { addItem: addRecentSearch } = searchActions @@ -28,6 +29,7 @@ type ProfileResultsProps = { export const ProfileResults = (props: ProfileResultsProps) => { const { limit = 100, ids, skeletonCount = 10 } = props + const { query } = useSearchParams() const isMobile = useIsMobile() const dispatch = useDispatch() @@ -45,9 +47,17 @@ export const ProfileResults = (props: ProfileResultsProps) => { } }) ) + dispatch( + make(Name.SEARCH_RESULT_SELECT, { + term: query, + source: 'search results page', + id, + kind: 'profile' + }) + ) } }, - [dispatch] + [dispatch, query] ) return ( diff --git a/packages/web/src/pages/search-page/components/desktop/SearchPageContent.jsx b/packages/web/src/pages/search-page/components/desktop/SearchPageContent.jsx index d8370a8f457..c5c5c17c279 100644 --- a/packages/web/src/pages/search-page/components/desktop/SearchPageContent.jsx +++ b/packages/web/src/pages/search-page/components/desktop/SearchPageContent.jsx @@ -125,7 +125,7 @@ class SearchPageContent extends Component { const onClickTile = (trackId, source) => { this.props.dispatch( make(Name.SEARCH_RESULT_SELECT, { - searchText, + term: searchText, kind: 'track', id: trackId, source From b6dd87513815aaad34644ff912ad0f3886036317 Mon Sep 17 00:00:00 2001 From: sliptype Date: Fri, 2 Aug 2024 16:43:56 -0500 Subject: [PATCH 2/2] Pass analytics through AudiusQueryContext --- packages/common/src/api/search.ts | 13 +++++----- .../src/audius-query/AudiusQueryContext.ts | 25 ++++++++++++++++++- .../mobile/src/app/AudiusQueryProvider.tsx | 4 ++- packages/web/src/app/AudiusQueryProvider.tsx | 4 ++- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/packages/common/src/api/search.ts b/packages/common/src/api/search.ts index 94c75b72363..ba1d9c4f3e3 100644 --- a/packages/common/src/api/search.ts +++ b/packages/common/src/api/search.ts @@ -1,5 +1,4 @@ import { Mood } from '@audius/sdk' -import { make } from 'common/store/analytics/actions' import { isEmpty } from 'lodash' import { createApi } from '~/audius-query' @@ -50,7 +49,7 @@ const searchApi = createApi({ getSearchResults: { fetch: async ( args: getSearchArgs, - { apiClient, audiusBackend, getFeatureEnabled, dispatch } + { apiClient, audiusBackend, getFeatureEnabled, analytics } ) => { const { category, @@ -93,8 +92,9 @@ const searchApi = createApi({ // Fire analytics only for the first page of results if (offset === 0) { - dispatch( - make(Name.SEARCH_TAG_SEARCH, { + analytics.track( + analytics.make({ + eventName: Name.SEARCH_SEARCH, term: query, source, ...searchParams @@ -120,8 +120,9 @@ const searchApi = createApi({ } // Fire analytics only for the first page of results if (offset === 0) { - dispatch( - make(Name.SEARCH_SEARCH, { + analytics.track( + analytics.make({ + eventName: Name.SEARCH_SEARCH, term: query, source, ...searchParams diff --git a/packages/common/src/audius-query/AudiusQueryContext.ts b/packages/common/src/audius-query/AudiusQueryContext.ts index 265bbc9d986..57f1630d297 100644 --- a/packages/common/src/audius-query/AudiusQueryContext.ts +++ b/packages/common/src/audius-query/AudiusQueryContext.ts @@ -12,7 +12,11 @@ import { RemoteConfigInstance } from '~/services/index' -import { ReportToSentryArgs } from '../models' +import { + AllTrackingEvents, + AnalyticsEvent, + ReportToSentryArgs +} from '../models' export type AudiusQueryContextType = { apiClient: AudiusAPIClient @@ -27,6 +31,22 @@ export type AudiusQueryContextType = { flag: FeatureFlags, fallbackFlag?: FeatureFlags ) => Promise | boolean + analytics: { + init: (isMobile: boolean) => Promise + track: (event: AnalyticsEvent, callback?: () => void) => Promise + identify: ( + handle: string, + traits?: Record, + options?: Record, + callback?: () => void + ) => Promise + make: ( + event: T + ) => { + eventName: string + properties: any + } + } } export const AudiusQueryContext = createContext( @@ -72,6 +92,9 @@ export function* getAudiusQueryContext(): Generator< >('remoteConfigInstance'), reportToSentry: yield* getContext( 'reportToSentry' + ), + analytics: yield* getContext( + 'analytics' ) } } diff --git a/packages/mobile/src/app/AudiusQueryProvider.tsx b/packages/mobile/src/app/AudiusQueryProvider.tsx index 15a5ace2ef1..2dabc4be179 100644 --- a/packages/mobile/src/app/AudiusQueryProvider.tsx +++ b/packages/mobile/src/app/AudiusQueryProvider.tsx @@ -3,6 +3,7 @@ import type { ReactNode } from 'react' import { AudiusQueryContext } from '@audius/common/audius-query' import { env } from 'app/env' +import * as analytics from 'app/services/analytics' import { apiClient } from 'app/services/audius-api-client' import { audiusBackendInstance } from 'app/services/audius-backend-instance' import { @@ -26,7 +27,8 @@ export const audiusQueryContext = { env, fetch, remoteConfigInstance, - getFeatureEnabled + getFeatureEnabled, + analytics } export const AudiusQueryProvider = (props: AudiusQueryProviderProps) => { diff --git a/packages/web/src/app/AudiusQueryProvider.tsx b/packages/web/src/app/AudiusQueryProvider.tsx index 2d0e2140e68..3bde186219e 100644 --- a/packages/web/src/app/AudiusQueryProvider.tsx +++ b/packages/web/src/app/AudiusQueryProvider.tsx @@ -3,6 +3,7 @@ import { ReactNode } from 'react' import { AudiusQueryContext } from '@audius/common/audius-query' import { useDispatch } from 'react-redux' +import * as analytics from 'services/analytics' import { apiClient } from 'services/audius-api-client' import { audiusBackendInstance } from 'services/audius-backend/audius-backend-instance' import { audiusSdk } from 'services/audius-sdk' @@ -29,7 +30,8 @@ export const AudiusQueryProvider = (props: AudiusQueryProviderProps) => { env, fetch, remoteConfigInstance, - getFeatureEnabled + getFeatureEnabled, + analytics }} > {children}