Check Analytics (#2106)

* fix sign in event tracking

* add missing analytics events

* add more missing analytics

* fix like and unrepost event tracking

* reset onEndReachedThreshold
zio/stable
Ansh 2023-12-06 11:45:01 -06:00 committed by GitHub
parent 7229cda5a5
commit 8e541d753a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 41 additions and 22 deletions

View File

@ -41,12 +41,6 @@ interface TrackPropertiesMap {
'Post:ThreadMute': {} // CAN BE SERVER
'Post:ThreadUnmute': {} // CAN BE SERVER
'Post:Reply': {} // CAN BE SERVER
// FEED ITEM events
'FeedItem:PostReply': {} // CAN BE SERVER
'FeedItem:PostRepost': {} // CAN BE SERVER
'FeedItem:PostLike': {} // CAN BE SERVER
'FeedItem:PostDelete': {} // CAN BE SERVER
'FeedItem:ThreadMute': {} // CAN BE SERVER
// PROFILE events
'Profile:Follow': {
username: string
@ -79,7 +73,6 @@ interface TrackPropertiesMap {
'Settings:AddAccountButtonClicked': {}
'Settings:ChangeHandleButtonClicked': {}
'Settings:InvitecodesButtonClicked': {}
'Settings:ContentfilteringButtonClicked': {}
'Settings:SignOutButtonClicked': {}
'Settings:ContentlanguagesButtonClicked': {}
// MENU events
@ -104,6 +97,8 @@ interface TrackPropertiesMap {
'Lists:Unmute': {} // CAN BE SERVER
'Lists:Block': {} // CAN BE SERVER
'Lists:Unblock': {} // CAN BE SERVER
'Lists:Delete': {} // CAN BE SERVER
'Lists:Share': {} // CAN BE SERVER
// CUSTOM FEED events
'CustomFeed:Save': {}
'CustomFeed:Unsave': {}
@ -134,6 +129,7 @@ interface TrackPropertiesMap {
'Onboarding:Skipped': {}
'Onboarding:Reset': {}
'Onboarding:SuggestedFollowFollowed': {}
'Onboarding:CustomFeedAdded': {}
}
interface ScreenPropertiesMap {

View File

@ -1,5 +1,6 @@
import React from 'react'
import * as persisted from '#/state/persisted'
import {track} from '#/lib/analytics/analytics'
type StateContext = persisted.Schema['mutedThreads']
type ToggleContext = (uri: string) => boolean
@ -19,9 +20,11 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
if (arr.includes(uri)) {
arr = arr.filter(v => v !== uri)
muted = false
track('Post:ThreadUnmute')
} else {
arr = arr.concat([uri])
muted = true
track('Post:ThreadMute')
}
persisted.write('mutedThreads', arr)
return arr

View File

@ -4,6 +4,7 @@ import {useQuery, useMutation, useQueryClient} from '@tanstack/react-query'
import {getAgent} from '#/state/session'
import {updatePostShadow} from '#/state/cache/post-shadow'
import {track} from '#/lib/analytics/analytics'
export const RQKEY = (postUri: string) => ['post', postUri]
@ -73,6 +74,7 @@ export function usePostLikeMutation() {
updatePostShadow(variables.uri, {
likeUri: data.uri,
})
track('Post:Like')
},
onError(error, variables) {
// revert the optimistic update
@ -92,6 +94,7 @@ export function usePostUnlikeMutation() {
>({
mutationFn: async ({likeUri}) => {
await getAgent().deleteLike(likeUri)
track('Post:Unlike')
},
onMutate(variables) {
// optimistically update the post-shadow
@ -129,6 +132,7 @@ export function usePostRepostMutation() {
updatePostShadow(variables.uri, {
repostUri: data.uri,
})
track('Post:Repost')
},
onError(error, variables) {
// revert the optimistic update
@ -148,6 +152,7 @@ export function usePostUnrepostMutation() {
>({
mutationFn: async ({repostUri}) => {
await getAgent().deleteRepost(repostUri)
track('Post:Unrepost')
},
onMutate(variables) {
// optimistically update the post-shadow
@ -173,6 +178,7 @@ export function usePostDeleteMutation() {
},
onSuccess(data, variables) {
updatePostShadow(variables.uri, {isDeleted: true})
track('Post:Delete')
},
})
}

View File

@ -21,6 +21,7 @@ import {useToggleMutationQueue} from '#/lib/hooks/useToggleMutationQueue'
import {RQKEY as RQKEY_MY_MUTED} from './my-muted-accounts'
import {RQKEY as RQKEY_MY_BLOCKED} from './my-blocked-accounts'
import {STALE} from '#/state/queries'
import {track} from '#/lib/analytics/analytics'
export const RQKEY = (did: string) => ['profile', did]
@ -188,6 +189,7 @@ function useProfileFollowMutation() {
updateProfileShadow(variables.did, {
followingUri: data.uri,
})
track('Profile:Follow', {username: variables.did})
}
},
onError(error, variables) {
@ -208,6 +210,7 @@ function useProfileUnfollowMutation() {
{did: string; followUri: string; skipOptimistic?: boolean}
>({
mutationFn: async ({followUri}) => {
track('Profile:Unfollow', {username: followUri})
return await getAgent().deleteFollow(followUri)
},
onMutate(variables) {

View File

@ -10,6 +10,7 @@ import {IS_PROD} from '#/lib/constants'
import {emitSessionLoaded, emitSessionDropped} from '../events'
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
import {useCloseAllActiveElements} from '#/state/util'
import {track} from '#/lib/analytics/analytics'
let __globalAgent: BskyAgent = PUBLIC_BSKY_AGENT
@ -270,6 +271,8 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
},
logger.DebugContext.session,
)
track('Sign In', {resumedSession: false})
},
[upsertAccount, queryClient],
)

View File

@ -120,8 +120,6 @@ export const LoginForm = ({
} else {
setError(cleanError(errMsg))
}
} finally {
track('Sign In', {resumedSession: false})
}
}

View File

@ -17,6 +17,7 @@ import {
useRemoveFeedMutation,
} from '#/state/queries/preferences'
import {logger} from '#/logger'
import {useAnalytics} from '#/lib/analytics/analytics'
export function RecommendedFeedsItem({
item,
@ -36,6 +37,7 @@ export function RecommendedFeedsItem({
variables: removedFeed,
reset: resetRemoveFeed,
} = useRemoveFeedMutation()
const {track} = useAnalytics()
if (!item || !preferences) return null
@ -56,6 +58,7 @@ export function RecommendedFeedsItem({
try {
await pinFeed({uri: item.uri})
resetPinFeed()
track('Onboarding:CustomFeedAdded')
} catch (e) {
Toast.show('There was an issue contacting your server')
logger.error('Failed to pin feed', {error: e})

View File

@ -294,7 +294,7 @@ let Feed = ({
scrollEventThrottle={scrollEventThrottle}
indicatorStyle={theme.colorScheme === 'dark' ? 'white' : 'black'}
onEndReached={onEndReached}
onEndReachedThreshold={2}
onEndReachedThreshold={2} // number of posts left to trigger load more
removeClippedSubviews={true}
contentOffset={{x: 0, y: headerOffset * -1}}
extraData={extraData}

View File

@ -25,7 +25,6 @@ import {PostSandboxWarning} from '../util/PostSandboxWarning'
import {PreviewableUserAvatar} from '../util/UserAvatar'
import {s} from 'lib/styles'
import {usePalette} from 'lib/hooks/usePalette'
import {useAnalytics} from 'lib/analytics/analytics'
import {sanitizeDisplayName} from 'lib/strings/display-names'
import {sanitizeHandle} from 'lib/strings/handles'
import {makeProfileLink} from 'lib/routes/links'
@ -102,7 +101,6 @@ let FeedItemInner = ({
}): React.ReactNode => {
const {openComposer} = useComposerControls()
const pal = usePalette('default')
const {track} = useAnalytics()
const [limitLines, setLimitLines] = useState(
() => countLines(richText.text) >= MAX_POST_LINES,
)
@ -121,7 +119,6 @@ let FeedItemInner = ({
}, [record?.reply])
const onPressReply = React.useCallback(() => {
track('FeedItem:PostReply')
openComposer({
replyTo: {
uri: post.uri,
@ -134,7 +131,7 @@ let FeedItemInner = ({
},
},
})
}, [post, record, track, openComposer])
}, [post, record, openComposer])
const onPressShowMore = React.useCallback(() => {
setLimitLines(false)

View File

@ -571,7 +571,7 @@ function AboutSection({
const scrollHandler = useAnimatedScrollHandler(onScroll)
const [likeUri, setLikeUri] = React.useState(feedInfo.likeUri)
const {hasSession} = useSession()
const {track} = useAnalytics()
const {mutateAsync: likeFeed, isPending: isLikePending} = useLikeMutation()
const {mutateAsync: unlikeFeed, isPending: isUnlikePending} =
useUnlikeMutation()
@ -586,9 +586,11 @@ function AboutSection({
if (isLiked && likeUri) {
await unlikeFeed({uri: likeUri})
track('CustomFeed:Unlike')
setLikeUri('')
} else {
const res = await likeFeed({uri: feedInfo.uri, cid: feedInfo.cid})
track('CustomFeed:Like')
setLikeUri(res.uri)
}
} catch (err) {
@ -597,7 +599,7 @@ function AboutSection({
)
logger.error('Failed up toggle like', {error: err})
}
}, [likeUri, isLiked, feedInfo, likeFeed, unlikeFeed])
}, [likeUri, isLiked, feedInfo, likeFeed, unlikeFeed, track])
return (
<ScrollView

View File

@ -62,6 +62,7 @@ import {
useUnpinFeedMutation,
} from '#/state/queries/preferences'
import {logger} from '#/logger'
import {useAnalytics} from '#/lib/analytics/analytics'
const SECTION_TITLES_CURATE = ['Posts', 'About']
const SECTION_TITLES_MOD = ['About']
@ -267,6 +268,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
useUnpinFeedMutation()
const isPending = isPinPending || isUnpinPending
const {data: preferences} = usePreferencesQuery()
const {track} = useAnalytics()
const isPinned = preferences?.feeds?.pinned?.includes(list.uri)
@ -297,6 +299,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
try {
await listMuteMutation.mutateAsync({uri: list.uri, mute: true})
Toast.show('List muted')
track('Lists:Mute')
} catch {
Toast.show(
'There was an issue. Please check your internet connection and try again.',
@ -307,18 +310,19 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
closeModal()
},
})
}, [openModal, closeModal, list, listMuteMutation, _])
}, [openModal, closeModal, list, listMuteMutation, track, _])
const onUnsubscribeMute = useCallback(async () => {
try {
await listMuteMutation.mutateAsync({uri: list.uri, mute: false})
Toast.show('List unmuted')
track('Lists:Unmute')
} catch {
Toast.show(
'There was an issue. Please check your internet connection and try again.',
)
}
}, [list, listMuteMutation])
}, [list, listMuteMutation, track])
const onSubscribeBlock = useCallback(() => {
openModal({
@ -332,6 +336,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
try {
await listBlockMutation.mutateAsync({uri: list.uri, block: true})
Toast.show('List blocked')
track('Lists:Block')
} catch {
Toast.show(
'There was an issue. Please check your internet connection and try again.',
@ -342,18 +347,19 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
closeModal()
},
})
}, [openModal, closeModal, list, listBlockMutation, _])
}, [openModal, closeModal, list, listBlockMutation, track, _])
const onUnsubscribeBlock = useCallback(async () => {
try {
await listBlockMutation.mutateAsync({uri: list.uri, block: false})
Toast.show('List unblocked')
track('Lists:Unblock')
} catch {
Toast.show(
'There was an issue. Please check your internet connection and try again.',
)
}
}, [list, listBlockMutation])
}, [list, listBlockMutation, track])
const onPressEdit = useCallback(() => {
openModal({
@ -370,6 +376,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
async onPressConfirm() {
await listDeleteMutation.mutateAsync({uri: list.uri})
Toast.show('List deleted')
track('Lists:Delete')
if (navigation.canGoBack()) {
navigation.goBack()
} else {
@ -377,7 +384,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
}
},
})
}, [openModal, list, listDeleteMutation, navigation, _])
}, [openModal, list, listDeleteMutation, navigation, track, _])
const onPressReport = useCallback(() => {
openModal({
@ -390,7 +397,8 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
const onPressShare = useCallback(() => {
const url = toShareUrl(`/profile/${list.creator.did}/lists/${rkey}`)
shareUrl(url)
}, [list, rkey])
track('Lists:Share')
}, [list, rkey, track])
const dropdownItems: DropdownItem[] = useMemo(() => {
let items: DropdownItem[] = [