diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx index 268a5ff5b8..926d27baa3 100644 --- a/src/components/FeedInterstitials.tsx +++ b/src/components/FeedInterstitials.tsx @@ -196,6 +196,7 @@ export function SuggestedFollowsProfile({did}: {did: string}) { @@ -222,10 +223,12 @@ export function ProfileGrid({ isSuggestionsLoading, error, profiles, + recId, viewContext = 'feed', }: { isSuggestionsLoading: boolean profiles: AppBskyActorDefs.ProfileViewDetailed[] + recId?: number error: Error | null viewContext: 'profile' | 'feed' }) { @@ -249,12 +252,19 @@ export function ProfileGrid({ )) ) : error || !profiles.length ? null : ( <> - {profiles.slice(0, maxLength).map(profile => ( + {profiles.slice(0, maxLength).map((profile, index) => ( { - logEvent('feed:interstitial:profileCard:press', {}) + logEvent('suggestedUser:press', { + logContext: + viewContext === 'feed' + ? 'InterstitialDiscover' + : 'InterstitialProfile', + recId, + position: index, + }) }} style={[ a.flex_1, @@ -282,6 +292,17 @@ export function ProfileGrid({ logContext="FeedInterstitial" shape="round" colorInverted + onFollow={() => { + logEvent('suggestedUser:follow', { + logContext: + viewContext === 'feed' + ? 'InterstitialDiscover' + : 'InterstitialProfile', + location: 'Card', + recId, + position: index, + }) + }} /> diff --git a/src/components/ProfileCard.tsx b/src/components/ProfileCard.tsx index 7bec14b9cc..78d86ab362 100644 --- a/src/components/ProfileCard.tsx +++ b/src/components/ProfileCard.tsx @@ -286,6 +286,7 @@ export type FollowButtonProps = { logContext: LogEvents['profile:follow']['logContext'] & LogEvents['profile:unfollow']['logContext'] colorInverted?: boolean + onFollow?: () => void } & Partial export function FollowButton(props: FollowButtonProps) { @@ -299,6 +300,7 @@ export function FollowButtonInner({ moderationOpts, logContext, onPress: onPressProp, + onFollow, colorInverted, ...rest }: FollowButtonProps) { @@ -325,6 +327,7 @@ export function FollowButtonInner({ ), ) onPressProp?.(e) + onFollow?.() } catch (err: any) { if (err?.name !== 'AbortError') { Toast.show(_(msg`An issue occurred, please try again.`), 'xmark') diff --git a/src/lib/statsig/events.ts b/src/lib/statsig/events.ts index af759e94e2..8aac7cd2da 100644 --- a/src/lib/statsig/events.ts +++ b/src/lib/statsig/events.ts @@ -165,6 +165,26 @@ export type LogEvents = { | 'PostOnboardingFindFollows' | 'ImmersiveVideo' } + 'suggestedUser:follow': { + logContext: + | 'Explore' + | 'InterstitialDiscover' + | 'InterstitialProfile' + | 'Profile' + location: 'Card' | 'Profile' + recId?: number + position: number + } + 'suggestedUser:press': { + logContext: 'Explore' | 'InterstitialDiscover' | 'InterstitialProfile' + recId?: number + position: number + } + 'suggestedUser:seen': { + logContext: 'Explore' | 'InterstitialDiscover' | 'InterstitialProfile' + recId?: number + position: number + } 'profile:unfollow': { logContext: | 'RecommendedFollowsItem' @@ -220,7 +240,6 @@ export type LogEvents = { domain: string } - 'feed:interstitial:profileCard:press': {} 'feed:interstitial:feedCard:press': {} 'profile:header:suggestedFollowsCard:press': {} diff --git a/src/state/queries/suggested-follows.ts b/src/state/queries/suggested-follows.ts index 22033c0a8c..0a2343150c 100644 --- a/src/state/queries/suggested-follows.ts +++ b/src/state/queries/suggested-follows.ts @@ -120,7 +120,7 @@ export function useSuggestedFollowsByActorQuery({ const suggestions = res.data.isFallback ? [] : res.data.suggestions.filter(profile => !profile.viewer?.following) - return {suggestions} + return {suggestions, recId: res.data.recId} }, enabled, }) diff --git a/src/view/com/profile/FollowButton.tsx b/src/view/com/profile/FollowButton.tsx index c2d76316e6..ff58dc9455 100644 --- a/src/view/com/profile/FollowButton.tsx +++ b/src/view/com/profile/FollowButton.tsx @@ -14,12 +14,14 @@ export function FollowButton({ profile, labelStyle, logContext, + onFollow, }: { unfollowedType?: ButtonType followedType?: ButtonType profile: Shadow labelStyle?: StyleProp logContext: 'ProfileCard' | 'StarterPackProfilesList' + onFollow?: () => void }) { const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue( profile, @@ -30,6 +32,7 @@ export function FollowButton({ const onPressFollow = async () => { try { await queueFollow() + onFollow?.() } catch (e: any) { if (e?.name !== 'AbortError') { Toast.show(_(msg`An issue occurred, please try again.`), 'xmark') diff --git a/src/view/com/profile/ProfileCard.tsx b/src/view/com/profile/ProfileCard.tsx index eab8611dd4..f710d7b4e7 100644 --- a/src/view/com/profile/ProfileCard.tsx +++ b/src/view/com/profile/ProfileCard.tsx @@ -184,6 +184,7 @@ export function ProfileCardWithFollowBtn({ noBg, noBorder, onPress, + onFollow, logContext = 'ProfileCard', showKnownFollowers, }: { @@ -191,6 +192,7 @@ export function ProfileCardWithFollowBtn({ noBg?: boolean noBorder?: boolean onPress?: () => void + onFollow?: () => void logContext?: 'ProfileCard' | 'StarterPackProfilesList' showKnownFollowers?: boolean }) { @@ -206,7 +208,11 @@ export function ProfileCardWithFollowBtn({ isMe ? undefined : profileShadow => ( - + ) } onPress={onPress} diff --git a/src/view/screens/Search/Explore.tsx b/src/view/screens/Search/Explore.tsx index c5af9607b3..520e103a4f 100644 --- a/src/view/screens/Search/Explore.tsx +++ b/src/view/screens/Search/Explore.tsx @@ -10,6 +10,7 @@ import { import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' +import {logEvent} from '#/lib/statsig/statsig' import {cleanError} from '#/lib/strings/errors' import {logger} from '#/logger' import {isNative, isWeb} from '#/platform/detection' @@ -259,6 +260,7 @@ type ExploreScreenItems = type: 'profile' key: string profile: AppBskyActorDefs.ProfileView + recId?: number } | { type: 'feed' @@ -383,6 +385,7 @@ export function Explore() { type: 'profile', key: actor.did, profile: actor, + recId: page.recId, }) } } @@ -511,7 +514,7 @@ export function Explore() { ]) const renderItem = React.useCallback( - ({item}: {item: ExploreScreenItems}) => { + ({item, index}: {item: ExploreScreenItems; index: number}) => { switch (item.type) { case 'header': { return ( @@ -540,6 +543,21 @@ export function Explore() { noBg noBorder showKnownFollowers + onPress={() => { + logEvent('suggestedUser:press', { + logContext: 'Explore', + recId: item.recId, + position: index, + }) + }} + onFollow={() => { + logEvent('suggestedUser:follow', { + logContext: 'Explore', + location: 'Card', + recId: item.recId, + position: index, + }) + }} /> )