Add trendingTopic:seen metric (#11309)

This commit is contained in:
DS Boyce
2026-07-27 17:06:10 -07:00
committed by GitHub
parent a5f0e8839a
commit e4ba1b4378
6 changed files with 54 additions and 16 deletions
+4
View File
@@ -750,6 +750,10 @@ export type Events = {
'trendingTopics:hide': { 'trendingTopics:hide': {
context: 'settings' | 'sidebar' | 'interstitial' | 'explore:trending' context: 'settings' | 'sidebar' | 'interstitial' | 'explore:trending'
} }
'trendingTopic:seen': {
context: 'sidebar' | 'interstitial' | 'explore'
recId?: string
}
'trendingTopic:click': { 'trendingTopic:click': {
context: 'sidebar' | 'interstitial' | 'explore' context: 'sidebar' | 'interstitial' | 'explore'
recId?: string recId?: string
+29 -9
View File
@@ -1,22 +1,28 @@
import {useMemo} from 'react' import {useEffect, useMemo} from 'react'
import {type AppBskyUnspeccedDefs, type AtUri} from '@atproto/api' import {type AppBskyUnspeccedDefs, type AtUri} from '@atproto/api'
import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react/macro'
import {useLingui} from '@lingui/react'
import {PressableScale} from '#/lib/custom-animations/PressableScale' import {PressableScale} from '#/lib/custom-animations/PressableScale'
import {useCallOnce} from '#/lib/once'
// import {makeProfileLink} from '#/lib/routes/links' // import {makeProfileLink} from '#/lib/routes/links'
// import {feedUriToHref} from '#/lib/strings/url-helpers' // import {feedUriToHref} from '#/lib/strings/url-helpers'
import {native} from '#/alf' import {native} from '#/alf'
import {Link as InternalLink, type LinkProps} from '#/components/Link' import {Link as InternalLink, type LinkProps} from '#/components/Link'
import {type Metrics, useAnalytics} from '#/analytics'
export function TrendingTopicLink({ export function TrendingTopicLink({
topic: raw, topic: raw,
metricContext,
recId,
children, children,
...rest ...rest
}: { }: {
topic: AppBskyUnspeccedDefs.TrendView topic: AppBskyUnspeccedDefs.TrendView
metricContext: Metrics['trendingTopic:seen']['context']
recId?: string
} & Omit<LinkProps, 'to' | 'label'>) { } & Omit<LinkProps, 'to' | 'label'>) {
const topic = useTopic(raw) const topic = useTopic(raw)
useTrendingTopicSeen(metricContext, recId)
return ( return (
<InternalLink <InternalLink
@@ -29,6 +35,20 @@ export function TrendingTopicLink({
) )
} }
export function useTrendingTopicSeen(
context: Metrics['trendingTopic:seen']['context'],
recId?: string,
) {
const ax = useAnalytics()
const trackSeen = useCallOnce(() => {
ax.metric('trendingTopic:seen', {context, recId})
})
useEffect(() => {
trackSeen()
}, [trackSeen])
}
type ParsedTrendingTopic = type ParsedTrendingTopic =
| { | {
type: 'topic' | 'tag' | 'starter-pack' | 'unknown' type: 'topic' | 'tag' | 'starter-pack' | 'unknown'
@@ -48,14 +68,14 @@ type ParsedTrendingTopic =
export function useTopic( export function useTopic(
raw: AppBskyUnspeccedDefs.TrendView, raw: AppBskyUnspeccedDefs.TrendView,
): ParsedTrendingTopic { ): ParsedTrendingTopic {
const {_} = useLingui() const {t: l} = useLingui()
return useMemo(() => { return useMemo(() => {
const {topic: displayName, link} = raw const {topic: displayName, link} = raw
if (link.startsWith('/search')) { if (link.startsWith('/search')) {
return { return {
type: 'topic', type: 'topic',
label: _(msg`Browse posts about ${displayName}`), label: l`Browse posts about ${displayName}`,
displayName, displayName,
uri: undefined, uri: undefined,
url: link, url: link,
@@ -63,7 +83,7 @@ export function useTopic(
} else if (link.startsWith('/hashtag')) { } else if (link.startsWith('/hashtag')) {
return { return {
type: 'tag', type: 'tag',
label: _(msg`Browse posts tagged with ${displayName}`), label: l`Browse posts tagged with ${displayName}`,
displayName, displayName,
// displayName: displayName.replace(/^#/, ''), // displayName: displayName.replace(/^#/, ''),
uri: undefined, uri: undefined,
@@ -72,7 +92,7 @@ export function useTopic(
} else if (link.startsWith('/starter-pack')) { } else if (link.startsWith('/starter-pack')) {
return { return {
type: 'starter-pack', type: 'starter-pack',
label: _(msg`Browse starter pack ${displayName}`), label: l`Browse starter pack ${displayName}`,
displayName, displayName,
uri: undefined, uri: undefined,
url: link, url: link,
@@ -109,10 +129,10 @@ export function useTopic(
return { return {
type: 'unknown', type: 'unknown',
label: _(msg`Browse topic ${displayName}`), label: l`Browse topic ${displayName}`,
displayName, displayName,
uri: undefined, uri: undefined,
url: link, url: link,
} }
}, [_, raw]) }, [l, raw])
} }
@@ -26,6 +26,7 @@ import {Trending3_Stroke2_Corner1_Rounded as TrendingIcon} from '#/components/ic
import {Link} from '#/components/Link' import {Link} from '#/components/Link'
import * as Prompt from '#/components/Prompt' import * as Prompt from '#/components/Prompt'
import {SubtleHover} from '#/components/SubtleHover' import {SubtleHover} from '#/components/SubtleHover'
import {useTrendingTopicSeen} from '#/components/TrendingTopics'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import {useAnalytics} from '#/analytics' import {useAnalytics} from '#/analytics'
@@ -136,9 +137,11 @@ function Inner() {
key={trend.link} key={trend.link}
trend={trend} trend={trend}
rank={index + 1} rank={index + 1}
recId={trending.recId}
onPress={() => { onPress={() => {
ax.metric('trendingTopic:click', { ax.metric('trendingTopic:click', {
context: 'interstitial', context: 'interstitial',
recId: trending.recId,
}) })
}} }}
/> />
@@ -163,10 +166,12 @@ function Inner() {
function TrendRow({ function TrendRow({
trend, trend,
rank, rank,
recId,
onPress, onPress,
}: ViewStyleProp & { }: ViewStyleProp & {
trend: AppBskyUnspeccedDefs.TrendView trend: AppBskyUnspeccedDefs.TrendView
rank: number rank: number
recId?: string
children?: React.ReactNode children?: React.ReactNode
onPress?: () => void onPress?: () => void
}) { }) {
@@ -175,6 +180,7 @@ function TrendRow({
const actors = useModerateTrendingActors(trend.actors) const actors = useModerateTrendingActors(trend.actors)
const formattedPostCount = formatCount(i18n, trend.postCount) const formattedPostCount = formatCount(i18n, trend.postCount)
useTrendingTopicSeen('interstitial', recId)
return ( return (
<Link <Link
+8 -7
View File
@@ -1,7 +1,6 @@
import {useCallback} from 'react' import {useCallback} from 'react'
import {ScrollView, View} from 'react-native' import {ScrollView, View} from 'react-native'
import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react/macro'
import {useLingui} from '@lingui/react'
import { import {
useTrendingSettings, useTrendingSettings,
@@ -30,7 +29,7 @@ export function TrendingInterstitial() {
export function Inner() { export function Inner() {
const t = useTheme() const t = useTheme()
const {_} = useLingui() const {t: l} = useLingui()
const ax = useAnalytics() const ax = useAnalytics()
const gutters = useGutters([0, 'base', 0, 'base']) const gutters = useGutters([0, 'base', 0, 'base'])
const trendingPrompt = Prompt.usePromptControl() const trendingPrompt = Prompt.usePromptControl()
@@ -103,6 +102,8 @@ export function Inner() {
<TrendingTopicLink <TrendingTopicLink
key={topic.link} key={topic.link}
topic={topic} topic={topic}
metricContext="interstitial"
recId={trending.recId}
onPress={() => { onPress={() => {
ax.metric('trendingTopic:click', { ax.metric('trendingTopic:click', {
context: 'interstitial', context: 'interstitial',
@@ -122,7 +123,7 @@ export function Inner() {
</TrendingTopicLink> </TrendingTopicLink>
))} ))}
<Button <Button
label={_(msg`Hide trending topics`)} label={l`Hide trending topics`}
size="tiny" size="tiny"
variant="ghost" variant="ghost"
color="secondary" color="secondary"
@@ -138,9 +139,9 @@ export function Inner() {
<Prompt.Basic <Prompt.Basic
control={trendingPrompt} control={trendingPrompt}
title={_(msg`Hide trending topics?`)} title={l`Hide trending topics?`}
description={_(msg`You can update this later from your settings.`)} description={l`You can update this later from your settings.`}
confirmButtonCta={_(msg`Hide`)} confirmButtonCta={l`Hide`}
onConfirm={onConfirmHide} onConfirm={onConfirmHide}
/> />
</View> </View>
@@ -24,6 +24,7 @@ import {Link} from '#/components/Link'
import * as Prompt from '#/components/Prompt' import * as Prompt from '#/components/Prompt'
import {RichText} from '#/components/RichText' import {RichText} from '#/components/RichText'
import {SubtleHover} from '#/components/SubtleHover' import {SubtleHover} from '#/components/SubtleHover'
import {useTrendingTopicSeen} from '#/components/TrendingTopics'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import {useAnalytics} from '#/analytics' import {useAnalytics} from '#/analytics'
import * as ModuleHeader from '../components/ModuleHeader' import * as ModuleHeader from '../components/ModuleHeader'
@@ -71,6 +72,7 @@ function Inner() {
key={trend.link} key={trend.link}
trend={trend} trend={trend}
rank={index + 1} rank={index + 1}
recId={trending.recId}
onPress={() => { onPress={() => {
ax.metric('trendingTopic:click', { ax.metric('trendingTopic:click', {
context: 'explore', context: 'explore',
@@ -98,11 +100,13 @@ function Inner() {
export function TrendRow({ export function TrendRow({
trend, trend,
rank, rank,
recId,
children, children,
onPress, onPress,
}: ViewStyleProp & { }: ViewStyleProp & {
trend: AppBskyUnspeccedDefs.TrendView trend: AppBskyUnspeccedDefs.TrendView
rank: number rank: number
recId?: string
children?: React.ReactNode children?: React.ReactNode
onPress?: () => void onPress?: () => void
}) { }) {
@@ -112,6 +116,7 @@ export function TrendRow({
const actors = useModerateTrendingActors(trend.actors) const actors = useModerateTrendingActors(trend.actors)
const formattedPostCount = formatCount(i18n, trend.postCount) const formattedPostCount = formatCount(i18n, trend.postCount)
useTrendingTopicSeen('explore', recId)
const description = useMemo(() => { const description = useMemo(() => {
if (!trend.description) return if (!trend.description) return
@@ -94,6 +94,8 @@ function Inner() {
<TrendingTopicLink <TrendingTopicLink
key={topic.link} key={topic.link}
topic={topic} topic={topic}
metricContext="sidebar"
recId={trending.recId}
onPress={() => { onPress={() => {
ax.metric('trendingTopic:click', { ax.metric('trendingTopic:click', {
context: 'sidebar', context: 'sidebar',