PostHog event tracking standards for Supabase Studio. Use when reviewing PRs for telemetry compliance or implementing new event tracking. Covers event naming, property conventions, approved patterns, and implementation guide.
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)