Files
supabase/apps/studio/lib/telemetry/track.ts
T
Sean Oliver 73e3143b0c Add type-safe event tracking utility (#39745)
Adds a clean, type-safe wrapper for telemetry event tracking that automatically injects project and organization context.

- Export TelemetryGroups type from telemetry-constants
- Add useTrack() hook with full TypeScript event validation
- Refactor project creation events to use new API
- Reduces boilerplate from ~10 lines to ~2 lines per event
2025-10-24 18:25:26 +00:00

62 lines
1.8 KiB
TypeScript

import { sendTelemetryEvent } from 'common'
import { TelemetryEvent, TelemetryGroups } from 'common/telemetry-constants'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { API_URL } from 'lib/constants'
import { useRouter } from 'next/router'
import { useCallback } from 'react'
type EventMap = {
[E in TelemetryEvent as E['action']]: E
}
type PropertiesForAction<A extends keyof EventMap> = EventMap[A] extends { properties: infer P }
? P
: never
type HasProperties<A extends keyof EventMap> = EventMap[A] extends { properties: any }
? true
: false
/**
* Hook for type-safe telemetry event tracking with automatic project/org context injection.
*
* @example
* const track = useTrack()
* track('table_created', { method: 'sql_editor', schema_name: 'public' })
* track('help_button_clicked')
*/
export const useTrack = () => {
const { data: project } = useSelectedProjectQuery()
const { data: org } = useSelectedOrganizationQuery()
const router = useRouter()
const track = useCallback(
<A extends keyof EventMap>(
action: A,
...args: HasProperties<A> extends true
? [properties: PropertiesForAction<A>, groupOverrides?: Partial<TelemetryGroups>]
: [properties?: undefined, groupOverrides?: Partial<TelemetryGroups>]
) => {
const [properties, groupOverrides] = args
const groups = {
...(project?.ref && { project: project.ref }),
...(org?.slug && { organization: org.slug }),
...groupOverrides,
}
const event = {
action,
...(properties && { properties }),
...(groups && { groups }),
} as EventMap[A]
sendTelemetryEvent(API_URL, event, router.pathname)
},
[project?.ref, org?.slug, router.pathname]
)
return track
}