feat(telemetry): product interaction events

- h2h_viewed from match card, dock, profile, stats, predictions
- reaction_sent with emoji and surface; score_report_opened from all
  three report entry points
- stats_filtered and stats_sorted on stats route and profile
- rules/teams/players/bracket/tournament view events with sources
- match_history_viewed, badge_viewed, player_searched (count only)
This commit is contained in:
2026-08-26 23:04:36 -07:00
parent fc65fdb451
commit f593b2c7b8
25 changed files with 747 additions and 629 deletions
@@ -399,7 +399,7 @@ export const MatchCard: React.FC<MatchCardProps> = ({
</Sheet>
</Flex>
{!showControls && <MatchReport match={match} compact />}
{!showControls && <MatchReport match={match} compact source="match_card" />}
</Stack>
);
};
@@ -24,6 +24,7 @@ import { MatchReport } from "./match-report";
import Sheet from "@/components/sheet/sheet";
import { useSheet } from "@/hooks/use-sheet";
import { Trans, useLingui } from "@lingui/react/macro";
import { track } from "@/lib/telemetry/client";
const EASE: [number, number, number, number] = [0.32, 0.72, 0, 1];
@@ -155,7 +156,7 @@ const MatchDock = ({ match, onClose }: MatchDockProps) => {
ended={ended}
/>
<MatchReport match={match} />
<MatchReport match={match} source="match_dock" />
<Group justify="space-between" wrap="nowrap" gap="sm">
<Box style={{ flex: 1, minWidth: 0 }}>
@@ -166,7 +167,7 @@ const MatchDock = ({ match, onClose }: MatchDockProps) => {
</Center>
}
>
<EmojiBar matchId={match.id} />
<EmojiBar matchId={match.id} source="match_dock" />
</Suspense>
</Box>
{!hasPrivate && (
@@ -174,7 +175,10 @@ const MatchDock = ({ match, onClose }: MatchDockProps) => {
<ActionIcon
variant="subtle"
size="sm"
onClick={h2hSheet.open}
onClick={() => {
track("h2h_viewed", { source: "match_card" });
h2hSheet.open();
}}
aria-label={t`View head-to-head`}
w={40}
style={{ flexShrink: 0 }}
@@ -13,6 +13,7 @@ import Sheet from "@/components/sheet/sheet";
import { MatchForm } from "./match-form";
import toast from "@/lib/sonner";
import { Trans, useLingui } from "@lingui/react/macro";
import { track } from "@/lib/telemetry/client";
const teamId = (t: Match["home"]): string | undefined =>
!t ? undefined : typeof t === "string" ? t : t.id;
@@ -26,9 +27,10 @@ const teamName = (t: Match["home"]): string | undefined =>
interface MatchReportProps {
match: Match;
compact?: boolean;
source?: string;
}
export const MatchReport: React.FC<MatchReportProps> = ({ match, compact }) => {
export const MatchReport: React.FC<MatchReportProps> = ({ match, compact, source }) => {
const { user } = useAuth();
const formSheet = useSheet();
const { t } = useLingui();
@@ -129,8 +131,9 @@ export const MatchReport: React.FC<MatchReportProps> = ({ match, compact }) => {
const openForm = useCallback(() => {
setAcknowledgedReport(pendingSignature);
track("score_report_opened", source ? { source } : undefined);
formSheet.open();
}, [pendingSignature, formSheet.open]);
}, [pendingSignature, formSheet.open, source]);
const dismissTakeover = useCallback(() => {
setAcknowledgedReport(pendingSignature);