Log rank and parent index with trending topic events (#11331)

This commit is contained in:
DS Boyce
2026-07-29 16:14:44 -07:00
committed by GitHub
parent 15c6c7955d
commit 91517af01c
7 changed files with 143 additions and 98 deletions
+4
View File
@@ -756,10 +756,14 @@ export type Events = {
'trendingTopic:seen': {
context: 'sidebar' | 'interstitial' | 'explore'
recId?: string
rank: number
feedSliceIndex?: number
}
'trendingTopic:click': {
context: 'sidebar' | 'interstitial' | 'explore'
recId?: string
rank: number
feedSliceIndex?: number
}
'trendingVideos:show': {
context: 'settings'
+11 -2
View File
@@ -13,16 +13,18 @@ import {type Metrics, useAnalytics} from '#/analytics'
export function TrendingTopicLink({
topic: raw,
metricContext,
rank,
recId,
children,
...rest
}: {
topic: AppBskyUnspeccedDefs.TrendView
metricContext: Metrics['trendingTopic:seen']['context']
rank: number
recId?: string
} & Omit<LinkProps, 'to' | 'label'>) {
const topic = useTopic(raw)
useTrendingTopicSeen(metricContext, recId)
useTrendingTopicSeen(metricContext, rank, recId)
return (
<InternalLink
@@ -37,11 +39,18 @@ export function TrendingTopicLink({
export function useTrendingTopicSeen(
context: Metrics['trendingTopic:seen']['context'],
rank: number,
recId?: string,
feedSliceIndex?: number,
) {
const ax = useAnalytics()
const trackSeen = useCallOnce(() => {
ax.metric('trendingTopic:seen', {context, recId})
ax.metric('trendingTopic:seen', {
context,
rank,
feedSliceIndex,
recId,
})
})
useEffect(() => {
@@ -32,15 +32,21 @@ import {useAnalytics} from '#/analytics'
const TOPIC_COUNT = 3
export function FeedTrendingTopicsInterstitial() {
export function FeedTrendingTopicsInterstitial({
feedSliceIndex,
}: {
feedSliceIndex: number
}) {
const {enabled} = useTrendingConfig()
const {trendingDisabled} = useTrendingSettings()
const {rightNavVisible} = useLayoutBreakpoints()
return enabled && !trendingDisabled && !rightNavVisible ? <Inner /> : null
return enabled && !trendingDisabled && !rightNavVisible ? (
<Inner feedSliceIndex={feedSliceIndex} />
) : null
}
function Inner() {
function Inner({feedSliceIndex}: {feedSliceIndex: number}) {
const t = useTheme()
const {t: l} = useLingui()
const gutters = useGutters([0, 'base'])
@@ -132,20 +138,26 @@ function Inner() {
? Array.from({length: TOPIC_COUNT}).map((_, i) => (
<TrendingTopicRowSkeleton key={i} rank={i + 1} />
))
: trending?.trends?.map((trend, index) => (
<TrendRow
key={trend.link}
trend={trend}
rank={index + 1}
recId={trending.recId}
onPress={() => {
ax.metric('trendingTopic:click', {
context: 'interstitial',
recId: trending.recId,
})
}}
/>
))}
: trending?.trends?.map((trend, index) => {
const rank = index + 1
return (
<TrendRow
key={trend.link}
trend={trend}
rank={rank}
feedSliceIndex={feedSliceIndex}
recId={trending.recId}
onPress={() => {
ax.metric('trendingTopic:click', {
context: 'interstitial',
rank,
feedSliceIndex,
recId: trending.recId,
})
}}
/>
)
})}
</View>
</View>
</View>
@@ -166,11 +178,13 @@ function Inner() {
function TrendRow({
trend,
rank,
feedSliceIndex,
recId,
onPress,
}: ViewStyleProp & {
trend: AppBskyUnspeccedDefs.TrendView
rank: number
feedSliceIndex: number
recId?: string
children?: React.ReactNode
onPress?: () => void
@@ -180,7 +194,7 @@ function TrendRow({
const actors = useModerateTrendingActors(trend.actors)
const formattedPostCount = formatCount(i18n, trend.postCount)
useTrendingTopicSeen('interstitial', recId)
useTrendingTopicSeen('interstitial', rank, recId, feedSliceIndex)
return (
<Link
+29 -24
View File
@@ -98,30 +98,35 @@ export function Inner() {
</View>
) : !trending?.trends ? null : (
<>
{trending.trends.map(topic => (
<TrendingTopicLink
key={topic.link}
topic={topic}
metricContext="interstitial"
recId={trending.recId}
onPress={() => {
ax.metric('trendingTopic:click', {
context: 'interstitial',
recId: trending.recId,
})
}}>
<View style={[a.py_lg]}>
<Text
style={[
t.atoms.text_contrast_medium,
a.text_sm,
a.font_semi_bold,
]}>
{topic.topic}
</Text>
</View>
</TrendingTopicLink>
))}
{trending.trends.map((topic, index) => {
const rank = index + 1
return (
<TrendingTopicLink
key={topic.link}
topic={topic}
metricContext="interstitial"
rank={rank}
recId={trending.recId}
onPress={() => {
ax.metric('trendingTopic:click', {
context: 'interstitial',
rank,
recId: trending.recId,
})
}}>
<View style={[a.py_lg]}>
<Text
style={[
t.atoms.text_contrast_medium,
a.text_sm,
a.font_semi_bold,
]}>
{topic.topic}
</Text>
</View>
</TrendingTopicLink>
)
})}
<Button
label={l`Hide trending topics`}
size="tiny"
@@ -79,20 +79,24 @@ function Inner() {
? Array.from({length: topicCount}).map((__, i) => (
<TrendingTopicRowSkeleton key={i} />
))
: trending?.trends.map((trend, index) => (
<TrendRow
key={trend.link}
trend={trend}
rank={index + 1}
recId={trending.recId}
onPress={() => {
ax.metric('trendingTopic:click', {
context: 'explore',
recId: trending.recId,
})
}}
/>
))}
: trending?.trends.map((trend, index) => {
const rank = index + 1
return (
<TrendRow
key={trend.link}
trend={trend}
rank={rank}
recId={trending.recId}
onPress={() => {
ax.metric('trendingTopic:click', {
context: 'explore',
rank,
recId: trending.recId,
})
}}
/>
)
})}
</View>
<Prompt.Basic
@@ -128,7 +132,7 @@ export function TrendRow({
const actors = useModerateTrendingActors(trend.actors)
const formattedPostCount = formatCount(i18n, trend.postCount)
useTrendingTopicSeen('explore', recId)
useTrendingTopicSeen('explore', rank, recId)
const description = useMemo(() => {
if (!trend.description) return
+5 -1
View File
@@ -159,6 +159,7 @@ type FeedRow =
| {
type: 'interstitialFeedTrendingTopics'
key: string
feedSliceIndex: number
}
| {
type: 'interstitialTrendingVideos'
@@ -583,6 +584,7 @@ let PostFeed = ({
arr.push({
type: 'interstitialFeedTrendingTopics',
key: 'interstitialFeedTrendingTopics-' + sliceIndex,
feedSliceIndex: sliceIndex,
})
} else if (sliceIndex === trendingIndices.videos) {
if (areVideoFeedsEnabled && !trendingVideoDisabled) {
@@ -858,7 +860,9 @@ let PostFeed = ({
} else if (row.type === 'interstitialTrending') {
return <TrendingInterstitial />
} else if (row.type === 'interstitialFeedTrendingTopics') {
return <FeedTrendingTopicsInterstitial />
return (
<FeedTrendingTopicsInterstitial feedSliceIndex={row.feedSliceIndex} />
)
} else if (row.type === 'liveEventFeedsAndTrendingBanner') {
return <DiscoverFeedLiveEventFeedsAndTrendingBanner />
} else if (row.type === 'composerPrompt') {
@@ -119,44 +119,49 @@ function Inner() {
))
) : !trending?.trends ? null : (
<>
{trending.trends.slice(0, DEFAULT_LIMIT).map((topic, i) => (
<TrendingTopicLink
key={topic.link}
topic={topic}
metricContext="sidebar"
recId={trending.recId}
onPress={() => {
ax.metric('trendingTopic:click', {
context: 'sidebar',
recId: trending.recId,
})
}}>
{({hovered}) => (
<View style={[a.flex_1, a.flex_row, a.gap_xs]}>
<Text
style={[
a.text_sm,
a.leading_snug,
t.atoms.text_contrast_low,
{minWidth: 16},
]}>
{i + 1}.
</Text>
<Text
style={[
a.flex_1,
a.text_sm,
a.leading_snug,
hovered
? [t.atoms.text, a.underline]
: t.atoms.text_contrast_medium,
]}>
{topic.displayName ?? topic.topic}
</Text>
</View>
)}
</TrendingTopicLink>
))}
{trending.trends.slice(0, DEFAULT_LIMIT).map((topic, i) => {
const rank = i + 1
return (
<TrendingTopicLink
key={topic.link}
topic={topic}
metricContext="sidebar"
rank={rank}
recId={trending.recId}
onPress={() => {
ax.metric('trendingTopic:click', {
context: 'sidebar',
rank,
recId: trending.recId,
})
}}>
{({hovered}) => (
<View style={[a.flex_1, a.flex_row, a.gap_xs]}>
<Text
style={[
a.text_sm,
a.leading_snug,
t.atoms.text_contrast_low,
{minWidth: 16},
]}>
{rank}.
</Text>
<Text
style={[
a.flex_1,
a.text_sm,
a.leading_snug,
hovered
? [t.atoms.text, a.underline]
: t.atoms.text_contrast_medium,
]}>
{topic.displayName ?? topic.topic}
</Text>
</View>
)}
</TrendingTopicLink>
)
})}
</>
)}
</View>