# How to Connect Supabase to Segment

- Tool: Supabase
- Difficulty: Beginner
- Time required: 15-20 min
- Compatibility: Supabase (all plans), Segment (all plans), @supabase/supabase-js v2+
- Last updated: March 2026

## TL;DR

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.

## Before you start

- 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

### 1. 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.

```
// Install via npm
// npm install @segment/analytics-next

import { AnalyticsBrowser } from '@segment/analytics-next'

export const analytics = AnalyticsBrowser.load({
  writeKey: process.env.NEXT_PUBLIC_SEGMENT_WRITE_KEY!
})
```

**Expected result:** The Segment SDK is initialized and ready to send events from the browser to your Segment source.

### 2. 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.

```
import { createClient } from '@supabase/supabase-js'
import { analytics } from './segment'

const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)

supabase.auth.onAuthStateChange(async (event, session) => {
  if (event === 'SIGNED_IN' && session?.user) {
    // Link Supabase user ID to Segment profile
    analytics.identify(session.user.id, {
      email: session.user.email,
      provider: session.user.app_metadata?.provider,
      created_at: session.user.created_at
    })

    analytics.track('User Signed In', {
      method: session.user.app_metadata?.provider ?? 'email',
      user_id: session.user.id
    })
  }

  if (event === 'SIGNED_OUT') {
    analytics.track('User Signed Out')
    analytics.reset() // Clear Segment identity
  }
})
```

**Expected result:** Every sign-in creates an identify call and a track call in Segment. Sign-outs are tracked and the identity is reset.

### 3. 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.

```
// supabase/functions/segment-track/index.ts
import { corsHeaders } from '../_shared/cors.ts'

Deno.serve(async (req) => {
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders })
  }

  const SEGMENT_WRITE_KEY = Deno.env.get('SEGMENT_WRITE_KEY')!
  const payload = await req.json()

  const segmentEvent = {
    userId: payload.user_id || payload.record?.user_id,
    event: payload.event_name || 'Database Event',
    properties: {
      table: payload.table,
      type: payload.type,
      ...payload.record
    },
    timestamp: new Date().toISOString()
  }

  const response = await fetch('https://api.segment.io/v1/track', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Basic ${btoa(SEGMENT_WRITE_KEY + ':')}`
    },
    body: JSON.stringify(segmentEvent)
  })

  return new Response(
    JSON.stringify({ success: response.ok }),
    { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
  )
})
```

**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.

### 4. 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.

```
-- Alternatively, create the webhook via SQL
select
  supabase_functions.http_request(
    'https://<project-ref>.supabase.co/functions/v1/segment-track',
    'POST',
    '{"Content-Type": "application/json"}',
    '{}',
    '5000'
  );
```

**Expected result:** Every new INSERT on the configured table automatically triggers the Edge Function, which sends the event to Segment.

### 5. 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.

```
import { analytics } from './segment'
import { createClient } from '@supabase/supabase-js'

const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)

async function handleCreateProject(projectName: string) {
  const { data: { user } } = await supabase.auth.getUser()

  // Insert into Supabase
  const { data, error } = await supabase
    .from('projects')
    .insert({ name: projectName, user_id: user?.id })
    .select()
    .single()

  if (!error && data) {
    // Track in Segment
    analytics.track('Project Created', {
      project_id: data.id,
      project_name: projectName,
      user_id: user?.id
    })
  }
}
```

**Expected result:** Custom events appear in the Segment debugger with the properties you specified, and are routed to all connected analytics destinations.

## Complete code example

File: `segment-integration.ts`

```typescript
import { AnalyticsBrowser } from '@segment/analytics-next'
import { createClient } from '@supabase/supabase-js'

// Initialize Segment
export const analytics = AnalyticsBrowser.load({
  writeKey: process.env.NEXT_PUBLIC_SEGMENT_WRITE_KEY!
})

// Initialize Supabase
const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)

// Track auth events automatically
export function initAuthTracking() {
  supabase.auth.onAuthStateChange(async (event, session) => {
    switch (event) {
      case 'SIGNED_IN':
        if (session?.user) {
          analytics.identify(session.user.id, {
            email: session.user.email,
            provider: session.user.app_metadata?.provider,
            created_at: session.user.created_at
          })
          analytics.track('User Signed In', {
            method: session.user.app_metadata?.provider ?? 'email'
          })
        }
        break
      case 'SIGNED_OUT':
        analytics.track('User Signed Out')
        analytics.reset()
        break
      case 'USER_UPDATED':
        if (session?.user) {
          analytics.identify(session.user.id, {
            email: session.user.email
          })
          analytics.track('User Profile Updated')
        }
        break
    }
  })
}

// Track a custom event
export function trackEvent(name: string, properties?: Record<string, unknown>) {
  analytics.track(name, properties)
}

// Track a page view
export function trackPage(name: string, properties?: Record<string, unknown>) {
  analytics.page(name, properties)
}
```

## Common mistakes

- **Hardcoding the Segment Write Key in Edge Function code instead of using Supabase secrets** — undefined Fix: 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').
- **Not calling analytics.reset() on sign-out, causing the next user's events to be attributed to the previous user** — undefined Fix: Always call analytics.reset() when the SIGNED_OUT event fires to clear the Segment anonymous ID and user identity.
- **Sending identify calls without the Supabase user ID, making it impossible to link events across sessions** — undefined Fix: Always pass session.user.id as the first argument to analytics.identify(). This links the Segment profile to the Supabase user.
- **Deploying the Edge Function without handling CORS, causing browser-based webhook tests to fail** — undefined Fix: 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

## 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.

---

Source: https://www.rapidevelopers.com/supabase-tutorial/how-to-connect-supabase-to-segment
© RapidDev — https://www.rapidevelopers.com/supabase-tutorial/how-to-connect-supabase-to-segment
