supabase/telemetry-standards
PostHog event tracking standards for Supabase Studio. Use when adding useTrack() calls, defining events in packages/common/telemetry-constants.ts, implementing tracking for a new feature, or reviewing PRs for telemetry compliance. Covers event naming, property conventions, approved patterns, and implementation guide.
npx skills add https://github.com/supabase/supabase --skill telemetry-standards
Standards for PostHog event tracking in apps/studio/. Apply these when
reviewing PRs that touch tracking or when implementing new tracking.
Format: [object]_[verb] in snake_case
Approved verbs only (canonical list — derived from packages/common/telemetry-constants.ts):
opened, clicked, submitted, created, removed, updated, intended, evaluated, added,
enabled, disabled, copied, exposed, failed, converted, closed, completed, applied, sent, moved
Flag these:
click_product_card → should be product_card_clickedproductCardClicked → should be product_card_clickedGood examples:
product_card_clickedbackup_button_clickedsql_query_submittedCommon mistakes with corrections:
database_saved → save_button_clicked or database_updated (unapproved verb)click_backup_button → backup_button_clicked (wrong order)dashboardViewed → don't track passive views on page loadcomponent_rendered → don't track — no user interactionCasing: camelCase preferred for new events. The codebase has existing snake_case properties (e.g., schema_name, table_name) — when adding properties to an existing event, match its established convention.
Names must be self-explanatory:
{ productType: 'database', planTier: 'pro' }{ assistantType: 'sql', suggestionType: 'optimization' }Flag these:
label, value, name, dataassistantType in one event, aiType in a related event)dashboard_viewed, sidebar_appeared, page_loaded)DO track: user clicks, form submissions, explicit opens/closes, user-initiated actions.
Exception: _exposed events for A/B experiment exposure tracking are valid even though they fire on render.
Never track PII (emails, names, IPs, etc.) in event properties.
Import useTrack from lib/telemetry/track (within apps/studio/). Never use useSendEventMutation (deprecated).
import { useTrack } from 'lib/telemetry/track'
const MyComponent = () => {
const track = useTrack()
const handleClick = () => {
track('product_card_clicked', {
productType: 'database',
planTier: 'pro',
source: 'dashboard',
})
}
return <button onClick={handleClick}>Click me</button>
}
All events must be defined as TypeScript interfaces in packages/common/telemetry-constants.ts:
/**
* [Event description]
*
* @group Events
* @source [what triggers this event]
*/
export interface MyFeatureClickedEvent {
action: 'my_feature_clicked'
properties: {
/** Description of property */
featureType: string
}
groups: TelemetryGroups
}
Add the new interface to the TelemetryEvent union type so useTrack picks it up.
@group Events and @source must be accurate.
When reviewing a PR, flag these as required changes:
[object]_[verb] snake_case, or using an unapproved verbuseSendEventMutation instead of useTrack@page/@source descriptions that don't match the actual implementationWhen a PR adds user-facing interactions (buttons, forms, toggles, modals) without tracking, suggest:
[object]_[verb] conventionuseTrack() call with suggested propertiesWhen checking property consistency, search packages/common/telemetry-constants.ts for similar events and verify property names match.
From the actual codebase:
// User copies a connection string
track('connection_string_copied', {
connectionType: 'psql',
connectionMethod: 'transaction_pooler',
connectionTab: 'Connection String',
})
// User enables a feature preview
track('feature_preview_enabled', {
feature: 'realtime_inspector',
})
// User clicks a banner CTA
track('index_advisor_banner_dismiss_button_clicked')
// Experiment exposure (fires on render — valid exception)
track('home_new_experiment_exposed', {
variant: 'treatment',
})
To add tracking for a user action:
[object]_[verb] using approved verbs onlypackages/common/telemetry-constants.ts for similar events and match their property names and casing@group Events and @source JSDoc, add to the TelemetryEvent union typeimport { useTrack } from 'lib/telemetry/track', call track('event_name', { properties })[object]_[verb] with approved verb@page/@sourceuseTrack hook (not useSendEventMutation)Take supabase/telemetry-standards from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.