Add more data to trending metrics (#11565)
This commit is contained in:
@@ -774,12 +774,14 @@ export type Events = {
|
|||||||
}
|
}
|
||||||
'trendingTopic:seen': {
|
'trendingTopic:seen': {
|
||||||
context: 'sidebar' | 'interstitial' | 'explore'
|
context: 'sidebar' | 'interstitial' | 'explore'
|
||||||
|
feedUri?: string
|
||||||
recId?: string
|
recId?: string
|
||||||
rank: number
|
rank: number
|
||||||
feedSliceIndex?: number
|
feedSliceIndex?: number
|
||||||
}
|
}
|
||||||
'trendingTopic:click': {
|
'trendingTopic:click': {
|
||||||
context: 'sidebar' | 'interstitial' | 'explore'
|
context: 'sidebar' | 'interstitial' | 'explore'
|
||||||
|
feedUri?: string
|
||||||
recId?: string
|
recId?: string
|
||||||
rank: number
|
rank: number
|
||||||
feedSliceIndex?: number
|
feedSliceIndex?: number
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {Trans, useLingui} from '@lingui/react/macro'
|
|||||||
import {PressableScale} from '#/lib/custom-animations/PressableScale'
|
import {PressableScale} from '#/lib/custom-animations/PressableScale'
|
||||||
import {useCallOnce} from '#/lib/once'
|
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 {makeRecordUri} from '#/lib/strings/url-helpers'
|
||||||
import {atoms as a, native, useTheme} from '#/alf'
|
import {atoms as a, native, useTheme} from '#/alf'
|
||||||
import {Link as InternalLink, type LinkProps} from '#/components/Link'
|
import {Link as InternalLink, type LinkProps} from '#/components/Link'
|
||||||
import * as Prompt from '#/components/Prompt'
|
import * as Prompt from '#/components/Prompt'
|
||||||
@@ -72,7 +72,8 @@ export function TrendingTopicLink({
|
|||||||
recId?: string
|
recId?: string
|
||||||
} & Omit<LinkProps, 'to' | 'label'>) {
|
} & Omit<LinkProps, 'to' | 'label'>) {
|
||||||
const topic = useTopic(raw)
|
const topic = useTopic(raw)
|
||||||
useTrendingTopicSeen(metricContext, rank, recId)
|
const feedUri = getTrendingTopicFeedUri(raw)
|
||||||
|
useTrendingTopicSeen(metricContext, feedUri, rank, recId)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InternalLink
|
<InternalLink
|
||||||
@@ -87,6 +88,7 @@ export function TrendingTopicLink({
|
|||||||
|
|
||||||
export function useTrendingTopicSeen(
|
export function useTrendingTopicSeen(
|
||||||
context: Metrics['trendingTopic:seen']['context'],
|
context: Metrics['trendingTopic:seen']['context'],
|
||||||
|
feedUri: string | undefined,
|
||||||
rank: number,
|
rank: number,
|
||||||
recId?: string,
|
recId?: string,
|
||||||
feedSliceIndex?: number,
|
feedSliceIndex?: number,
|
||||||
@@ -95,6 +97,7 @@ export function useTrendingTopicSeen(
|
|||||||
const trackSeen = useCallOnce(() => {
|
const trackSeen = useCallOnce(() => {
|
||||||
ax.metric('trendingTopic:seen', {
|
ax.metric('trendingTopic:seen', {
|
||||||
context,
|
context,
|
||||||
|
feedUri,
|
||||||
rank,
|
rank,
|
||||||
feedSliceIndex,
|
feedSliceIndex,
|
||||||
recId,
|
recId,
|
||||||
@@ -106,6 +109,20 @@ export function useTrendingTopicSeen(
|
|||||||
}, [trackSeen])
|
}, [trackSeen])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getTrendingTopicFeedUri(
|
||||||
|
topic: app.bsky.unspecced.defs.TrendView,
|
||||||
|
): string | undefined {
|
||||||
|
const match = topic.link.match(/^\/profile\/([^/]+)\/feed\/([^/?#]+)/)
|
||||||
|
|
||||||
|
if (!match) return undefined
|
||||||
|
|
||||||
|
return makeRecordUri(
|
||||||
|
decodeURIComponent(match[1]),
|
||||||
|
'app.bsky.feed.generator',
|
||||||
|
decodeURIComponent(match[2]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
type ParsedTrendingTopic =
|
type ParsedTrendingTopic =
|
||||||
| {
|
| {
|
||||||
type: 'topic' | 'tag' | 'starter-pack' | 'unknown'
|
type: 'topic' | 'tag' | 'starter-pack' | 'unknown'
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ 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 {
|
import {
|
||||||
|
getTrendingTopicFeedUri,
|
||||||
TrendingTopicsPrompt,
|
TrendingTopicsPrompt,
|
||||||
useTrendingTopicSeen,
|
useTrendingTopicSeen,
|
||||||
} from '#/components/TrendingTopics'
|
} from '#/components/TrendingTopics'
|
||||||
@@ -154,6 +155,7 @@ function Inner({feedSliceIndex}: {feedSliceIndex: number}) {
|
|||||||
onPress={() => {
|
onPress={() => {
|
||||||
ax.metric('trendingTopic:click', {
|
ax.metric('trendingTopic:click', {
|
||||||
context: 'interstitial',
|
context: 'interstitial',
|
||||||
|
feedUri: getTrendingTopicFeedUri(trend),
|
||||||
rank,
|
rank,
|
||||||
feedSliceIndex,
|
feedSliceIndex,
|
||||||
recId: trending.recId,
|
recId: trending.recId,
|
||||||
@@ -195,7 +197,13 @@ 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', rank, recId, feedSliceIndex)
|
useTrendingTopicSeen(
|
||||||
|
'interstitial',
|
||||||
|
getTrendingTopicFeedUri(trend),
|
||||||
|
rank,
|
||||||
|
recId,
|
||||||
|
feedSliceIndex,
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ 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 {
|
import {
|
||||||
|
getTrendingTopicFeedUri,
|
||||||
TrendingTopicsPrompt,
|
TrendingTopicsPrompt,
|
||||||
useTrendingTopicSeen,
|
useTrendingTopicSeen,
|
||||||
} from '#/components/TrendingTopics'
|
} from '#/components/TrendingTopics'
|
||||||
@@ -95,6 +96,7 @@ function Inner() {
|
|||||||
onPress={() => {
|
onPress={() => {
|
||||||
ax.metric('trendingTopic:click', {
|
ax.metric('trendingTopic:click', {
|
||||||
context: 'explore',
|
context: 'explore',
|
||||||
|
feedUri: getTrendingTopicFeedUri(trend),
|
||||||
rank,
|
rank,
|
||||||
recId: trending.recId,
|
recId: trending.recId,
|
||||||
})
|
})
|
||||||
@@ -134,7 +136,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', rank, recId)
|
useTrendingTopicSeen('explore', getTrendingTopicFeedUri(trend), rank, recId)
|
||||||
|
|
||||||
const description = useMemo(() => {
|
const description = useMemo(() => {
|
||||||
if (!trend.description) return
|
if (!trend.description) return
|
||||||
|
|||||||
+13
-11
@@ -10,12 +10,8 @@ import {AppState, type AppStateStatus} from 'react-native'
|
|||||||
import {type AtUriString, type DidString} from '@atproto/syntax'
|
import {type AtUriString, type DidString} from '@atproto/syntax'
|
||||||
import throttle from 'lodash.throttle'
|
import throttle from 'lodash.throttle'
|
||||||
|
|
||||||
import {PROD_FEEDS, STAGING_FEEDS} from '#/lib/constants'
|
import {PROD_FEEDS, STAGING_FEEDS, TRENDING_DID} from '#/lib/constants'
|
||||||
import {
|
import {type FeedSourceInfo, isFeedSourceFeedInfo} from '#/state/queries/feed'
|
||||||
type FeedSourceFeedInfo,
|
|
||||||
type FeedSourceInfo,
|
|
||||||
isFeedSourceFeedInfo,
|
|
||||||
} from '#/state/queries/feed'
|
|
||||||
import {
|
import {
|
||||||
type FeedDescriptor,
|
type FeedDescriptor,
|
||||||
type FeedPostSliceItem,
|
type FeedPostSliceItem,
|
||||||
@@ -144,7 +140,7 @@ export function useFeedFeedback(
|
|||||||
const interactionsToSend = interactions.filter(
|
const interactionsToSend = interactions.filter(
|
||||||
interaction =>
|
interaction =>
|
||||||
interaction.event &&
|
interaction.event &&
|
||||||
isInteractionAllowed(enabled, feed, interaction.event),
|
isInteractionAllowed(enabled, feed?.feedDescriptor, interaction.event),
|
||||||
)
|
)
|
||||||
|
|
||||||
if (interactionsToSend.length === 0) {
|
if (interactionsToSend.length === 0) {
|
||||||
@@ -263,22 +259,28 @@ export function useFeedFeedbackContext() {
|
|||||||
// TODO
|
// TODO
|
||||||
// We will introduce a permissions framework for 3p feeds to
|
// We will introduce a permissions framework for 3p feeds to
|
||||||
// take advantage of the feed feedback API. Until that's in
|
// take advantage of the feed feedback API. Until that's in
|
||||||
// place, we're hardcoding it to the discover feed.
|
// place, we're hardcoding it to the discover and trending feeds.
|
||||||
// -prf
|
// -prf
|
||||||
export function isDiscoverFeed(feed?: FeedDescriptor) {
|
export function isDiscoverFeed(feed?: FeedDescriptor) {
|
||||||
return !!feed && FEEDBACK_FEEDS.includes(feed)
|
return !!feed && FEEDBACK_FEEDS.includes(feed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isTrendingFeed(feed?: FeedDescriptor) {
|
||||||
|
return !!feed && feed.startsWith(`feedgen|at://${TRENDING_DID}/`)
|
||||||
|
}
|
||||||
|
|
||||||
function isInteractionAllowed(
|
function isInteractionAllowed(
|
||||||
enabled: boolean,
|
enabled: boolean,
|
||||||
feed: FeedSourceFeedInfo | undefined,
|
feed: FeedDescriptor | undefined,
|
||||||
interaction: app.bsky.feed.defs.Interaction['event'],
|
interaction: app.bsky.feed.defs.Interaction['event'],
|
||||||
) {
|
) {
|
||||||
if (!enabled || !feed) {
|
if (!enabled || !feed) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const isDiscover = isDiscoverFeed(feed.feedDescriptor)
|
if (isDiscoverFeed(feed) || isTrendingFeed(feed)) {
|
||||||
return isDiscover ? true : THIRD_PARTY_ALLOWED_INTERACTIONS.has(interaction)
|
return true
|
||||||
|
}
|
||||||
|
return THIRD_PARTY_ALLOWED_INTERACTIONS.has(interaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
function toString(interaction: app.bsky.feed.defs.Interaction): string {
|
function toString(interaction: app.bsky.feed.defs.Interaction): string {
|
||||||
|
|||||||
@@ -17,6 +17,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 {
|
import {
|
||||||
|
getTrendingTopicFeedUri,
|
||||||
TrendingTopicLink,
|
TrendingTopicLink,
|
||||||
TrendingTopicsPrompt,
|
TrendingTopicsPrompt,
|
||||||
} from '#/components/TrendingTopics'
|
} from '#/components/TrendingTopics'
|
||||||
@@ -133,6 +134,7 @@ function Inner() {
|
|||||||
onPress={() => {
|
onPress={() => {
|
||||||
ax.metric('trendingTopic:click', {
|
ax.metric('trendingTopic:click', {
|
||||||
context: 'sidebar',
|
context: 'sidebar',
|
||||||
|
feedUri: getTrendingTopicFeedUri(topic),
|
||||||
rank,
|
rank,
|
||||||
recId: trending.recId,
|
recId: trending.recId,
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user