Connect Supabase to Segment by sending analytics events from your application using the Segment Analytics.js SDK on the client side, and by forwarding server-side events from Supabase Edge Functions using the Segment HTTP Tracking API. Track auth events by listening to onAuthStateChange and sending identify and track calls to Segment. For database-level events, use a database webhook that triggers an Edge Function to forward the event payload to Segment.
Sending Supabase Auth and Database Events to Segment for Analytics
Segment is a customer data platform that collects events from your application and routes them to analytics tools like Mixpanel, Amplitude, Google Analytics, and data warehouses. This tutorial shows you how to connect Supabase to Segment using two approaches: client-side tracking with Analytics.js for auth events, and server-side tracking with Edge Functions for database events. By combining both, you get complete visibility into user behavior.
Prerequisites
- A Supabase project with authentication configured
- A Segment workspace with a source created (get your Write Key)
- @supabase/supabase-js v2 installed in your project
- Basic understanding of Segment's track and identify calls
Step-by-step guide
Install the Segment Analytics.js SDK in your frontend
Install the Segment Analytics.js SDK in your frontend
Add the Segment Analytics.js snippet or npm package to your frontend application. The Analytics.js SDK provides track, identify, and page methods for sending events to Segment. Use the npm package for framework-based apps (React, Next.js, Vue) and the snippet for plain HTML sites. Your Segment Write Key is found in the Segment Dashboard under Sources.
1// Install via npm2// npm install @segment/analytics-next34import { AnalyticsBrowser } from '@segment/analytics-next'56export const analytics = AnalyticsBrowser.load({7 writeKey: process.env.NEXT_PUBLIC_SEGMENT_WRITE_KEY!8})Expected result: The Segment SDK is initialized and ready to send events from the browser to your Segment source.
Track Supabase auth events with onAuthStateChange
Track Supabase auth events with onAuthStateChange
Listen to Supabase auth state changes and send corresponding Segment events. When a user signs in, call analytics.identify to associate their Supabase user ID with their Segment profile, then call analytics.track to record the sign-in event. When they sign out, track the sign-out event. This creates a complete auth funnel in Segment.
1import { createClient } from '@supabase/supabase-js'2import { analytics } from './segment'34const supabase = createClient(5 process.env.NEXT_PUBLIC_SUPABASE_URL!,6 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!7)89supabase.auth.onAuthStateChange(async (event, session) => {10 if (event === 'SIGNED_IN' && session?.user) {11 // Link Supabase user ID to Segment profile12 analytics.identify(session.user.id, {13 email: session.user.email,14 provider: session.user.app_metadata?.provider,15 created_at: session.user.created_at16 })1718 analytics.track('User Signed In', {19 method: session.user.app_metadata?.provider ?? 'email',20 user_id: session.user.id21 })22 }2324 if (event === 'SIGNED_OUT') {25 analytics.track('User Signed Out')26 analytics.reset() // Clear Segment identity27 }28})Expected result: Every sign-in creates an identify call and a track call in Segment. Sign-outs are tracked and the identity is reset.
Create an Edge Function to forward server-side events to Segment
Create an Edge Function to forward server-side events to Segment
For events that happen at the database level (new orders, profile updates, etc.), use a Supabase Edge Function that sends events to Segment's HTTP Tracking API. This function receives a webhook payload from Supabase and forwards it to Segment as a track call. Store your Segment Write Key as a Supabase secret so it is not exposed in code.
1// supabase/functions/segment-track/index.ts2import { corsHeaders } from '../_shared/cors.ts'34Deno.serve(async (req) => {5 if (req.method === 'OPTIONS') {6 return new Response('ok', { headers: corsHeaders })7 }89 const SEGMENT_WRITE_KEY = Deno.env.get('SEGMENT_WRITE_KEY')!10 const payload = await req.json()1112 const segmentEvent = {13 userId: payload.user_id || payload.record?.user_id,14 event: payload.event_name || 'Database Event',15 properties: {16 table: payload.table,17 type: payload.type,18 ...payload.record19 },20 timestamp: new Date().toISOString()21 }2223 const response = await fetch('https://api.segment.io/v1/track', {24 method: 'POST',25 headers: {26 'Content-Type': 'application/json',27 'Authorization': `Basic ${btoa(SEGMENT_WRITE_KEY + ':')}`28 },29 body: JSON.stringify(segmentEvent)30 })3132 return new Response(33 JSON.stringify({ success: response.ok }),34 { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }35 )36})Expected result: The Edge Function receives webhook payloads and forwards them to Segment's HTTP API. Each database event appears as a track call in your Segment debugger.
Set up a database webhook to trigger the Edge Function
Set up a database webhook to trigger the Edge Function
In the Supabase Dashboard, go to Database > Webhooks and create a new webhook. Configure it to fire on INSERT events for the tables you want to track (for example, orders or subscriptions). Set the webhook URL to your Edge Function's URL. The webhook automatically sends the new row data as the request body, which the Edge Function then forwards to Segment.
1-- Alternatively, create the webhook via SQL2select3 supabase_functions.http_request(4 'https://<project-ref>.supabase.co/functions/v1/segment-track',5 'POST',6 '{"Content-Type": "application/json"}',7 '{}',8 '5000'9 );Expected result: Every new INSERT on the configured table automatically triggers the Edge Function, which sends the event to Segment.
Track custom events from your application code
Track custom events from your application code
Beyond automated auth and database events, track custom user actions like button clicks, feature usage, and page views. Call analytics.track from your React components or event handlers. Include relevant properties like the Supabase user ID, the feature name, and any contextual data. This gives you a complete picture of user behavior in Segment.
1import { analytics } from './segment'2import { createClient } from '@supabase/supabase-js'34const supabase = createClient(5 process.env.NEXT_PUBLIC_SUPABASE_URL!,6 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!7)89async function handleCreateProject(projectName: string) {10 const { data: { user } } = await supabase.auth.getUser()1112 // Insert into Supabase13 const { data, error } = await supabase14 .from('projects')15 .insert({ name: projectName, user_id: user?.id })16 .select()17 .single()1819 if (!error && data) {20 // Track in Segment21 analytics.track('Project Created', {22 project_id: data.id,23 project_name: projectName,24 user_id: user?.id25 })26 }27}Expected result: Custom events appear in the Segment debugger with the properties you specified, and are routed to all connected analytics destinations.
Complete working example
1import { AnalyticsBrowser } from '@segment/analytics-next'2import { createClient } from '@supabase/supabase-js'34// Initialize Segment5export const analytics = AnalyticsBrowser.load({6 writeKey: process.env.NEXT_PUBLIC_SEGMENT_WRITE_KEY!7})89// Initialize Supabase10const supabase = createClient(11 process.env.NEXT_PUBLIC_SUPABASE_URL!,12 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!13)1415// Track auth events automatically16export function initAuthTracking() {17 supabase.auth.onAuthStateChange(async (event, session) => {18 switch (event) {19 case 'SIGNED_IN':20 if (session?.user) {21 analytics.identify(session.user.id, {22 email: session.user.email,23 provider: session.user.app_metadata?.provider,24 created_at: session.user.created_at25 })26 analytics.track('User Signed In', {27 method: session.user.app_metadata?.provider ?? 'email'28 })29 }30 break31 case 'SIGNED_OUT':32 analytics.track('User Signed Out')33 analytics.reset()34 break35 case 'USER_UPDATED':36 if (session?.user) {37 analytics.identify(session.user.id, {38 email: session.user.email39 })40 analytics.track('User Profile Updated')41 }42 break43 }44 })45}4647// Track a custom event48export function trackEvent(name: string, properties?: Record<string, unknown>) {49 analytics.track(name, properties)50}5152// Track a page view53export function trackPage(name: string, properties?: Record<string, unknown>) {54 analytics.page(name, properties)55}Common mistakes when connecting Supabase to Segment
Why it's a problem: Hardcoding the Segment Write Key in Edge Function code instead of using Supabase secrets
How to avoid: Store the Write Key as a Supabase secret: supabase secrets set SEGMENT_WRITE_KEY=your_key. Access it with Deno.env.get('SEGMENT_WRITE_KEY').
Why it's a problem: Not calling analytics.reset() on sign-out, causing the next user's events to be attributed to the previous user
How to avoid: Always call analytics.reset() when the SIGNED_OUT event fires to clear the Segment anonymous ID and user identity.
Why it's a problem: Sending identify calls without the Supabase user ID, making it impossible to link events across sessions
How to avoid: Always pass session.user.id as the first argument to analytics.identify(). This links the Segment profile to the Supabase user.
Why it's a problem: Deploying the Edge Function without handling CORS, causing browser-based webhook tests to fail
How to avoid: Import and apply corsHeaders in your Edge Function. Handle OPTIONS preflight requests explicitly.
Best practices
- Use analytics.identify with the Supabase user ID to create a consistent identity across all analytics tools
- Track auth events automatically with onAuthStateChange instead of scattering track calls throughout your codebase
- Store the Segment Write Key as a Supabase secret for Edge Functions — never hardcode it
- Call analytics.reset() on sign-out to prevent cross-user event attribution
- Use consistent event naming conventions like 'Object Action' (e.g., 'Project Created', 'File Uploaded')
- Test events in the Segment debugger before connecting downstream destinations
- Use database webhooks for server-side events that should be tracked regardless of which client initiated them
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to send Supabase auth events and database events to Segment for analytics. Show me how to use Analytics.js on the client to track sign-in and sign-out events, and how to create a Supabase Edge Function that forwards database webhook events to Segment's HTTP Tracking API.
Set up a Supabase-to-Segment integration that tracks auth events with onAuthStateChange and analytics.identify/track on the client, and forwards database INSERT events from a webhook to Segment via an Edge Function using the HTTP Tracking API.
Frequently asked questions
Is the Segment Write Key safe to use in browser code?
Yes. The Segment Write Key is designed for client-side use, similar to the Supabase anon key. It can only send events to Segment, not read data. Use it in your frontend without concern.
Can I track Supabase Realtime events in Segment?
Yes. Subscribe to Realtime postgres_changes events and call analytics.track when events are received. This lets you track when other users' actions trigger updates visible to the current user.
How do I test that events are reaching Segment?
Use the Segment Debugger in the Segment Dashboard. It shows real-time incoming events with their properties, making it easy to verify your integration before connecting downstream destinations.
Can I send events to Segment from Supabase without an Edge Function?
For client-side events, use Analytics.js directly. For server-side database events, an Edge Function or external service is required because database triggers cannot make HTTP requests directly. The pg_net extension is an alternative for simple HTTP calls.
What happens if the Segment API is down when my Edge Function fires?
The Edge Function will receive an error from the Segment API. Implement retry logic or store failed events in a Supabase table for later processing. Segment also provides a batch API that can handle retries.
Can RapidDev help set up a complete analytics pipeline from Supabase to Segment?
Yes. RapidDev can design and implement your Segment integration including client-side tracking, Edge Function webhooks, event naming conventions, and downstream destination configuration.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation