Overview
Segment is a Customer Data Platform (CDP) that collects, transforms, and routes event data to hundreds of downstream tools and warehouses. Instead of implementing individual analytics SDKs, you implement Segment once and manage destinations through the Segment UI.
Key Architecture:
- Sources: Where data originates (web, mobile, server, cloud apps)
- Connections: Segment's data routing engine
- Destinations: Where data flows (analytics, marketing, warehouses)
- Protocols: Data validation and quality controls
- Functions: Custom transformation logic
Benefits:
- Single SDK replaces dozens of vendor scripts
- Centralized destination management
- Retroactive integration (send historical data to new tools)
- Built-in data governance and privacy controls
- Device-mode and cloud-mode flexibility
Prerequisites
1. Segment Workspace Setup
Before installation, ensure you have:
- Active Segment workspace with appropriate pricing plan
- Write Key for your source (found in Source Settings)
- Workspace ID if using newer Connections SDK
- Separate sources for staging, development, and production environments
2. Access & Permissions
Required access:
- Workspace Member or Admin role in Segment
- Ability to modify application code or website
<head> - For mobile: Developer access to iOS/Android codebase
- For server-side: Backend infrastructure access
3. Data Governance Planning
Document before implementation:
- Tracking Plan: Event names, properties, and data types
- User Identity Strategy: How userId and anonymousId will be managed
- Consent Management: GDPR/CCPA requirements per region
- Data Residency: EU/US endpoint requirements
- Destination Strategy: Which destinations need device-mode vs cloud-mode
4. Environment Configuration
Plan separate Segment sources for:
- Production: Live customer data
- Staging: Pre-production testing
- Development: Local development and QA
- CI/CD: Automated testing environments
Never share write keys across environments.
Web SDK Installation Methods
Segment offers multiple web SDK options:
Method 1: Analytics.js 2.0 (Standard Web SDK)
The classic Segment web SDK, suitable for most websites and SPAs.
Direct Snippet Installation
Add to your website's <head> section:
<!DOCTYPE html>
<html>
<head>
<script>
!function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware"];analytics.factory=function(e){return function(){var t=Array.prototype.slice.call(arguments);t.unshift(e);analytics.push(t);return analytics}};for(var e=0;e<analytics.methods.length;e++){var key=analytics.methods[e];analytics[key]=analytics.factory(key)}analytics.load=function(key,e){var t=document.createElement("script");t.type="text/javascript";t.async=!0;t.src="https://cdn.segment.com/analytics.js/v1/" + key + "/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(t,n);analytics._loadOptions=e};analytics._writeKey="YOUR_WRITE_KEY";analytics.SNIPPET_VERSION="4.15.3";
analytics.load("YOUR_WRITE_KEY");
analytics.page();
}}();
</script>
</head>
<body>
<!-- Your content -->
</body>
</html>
Replace YOUR_WRITE_KEY with your actual write key from Segment.
Environment-Specific Configuration
Use server-side rendering to inject write keys:
<script>
analytics.load("<%= process.env.SEGMENT_WRITE_KEY %>");
analytics.page();
</script>
// React/Next.js example
const SEGMENT_WRITE_KEY = process.env.NEXT_PUBLIC_SEGMENT_WRITE_KEY;
analytics.load(SEGMENT_WRITE_KEY);
analytics.page();
Regional Data Residency (EU Endpoint)
For GDPR compliance, use the EU endpoint:
analytics.load("YOUR_WRITE_KEY", {
integrations: {
"Segment.io": {
apiHost: "api.segment.io/v1",
protocol: "https"
}
}
});
Or for EU workspace:
analytics.load("YOUR_WRITE_KEY", {
integrations: {
"Segment.io": {
apiHost: "events.eu1.segmentapis.com",
protocol: "https"
}
}
});
Method 2: Analytics.js NPM Package
For modern JavaScript applications using build tools.
Installation
npm install @segment/analytics-next
# or
yarn add @segment/analytics-next
# or
pnpm add @segment/analytics-next
Basic Usage
import { AnalyticsBrowser } from '@segment/analytics-next'
export const analytics = AnalyticsBrowser.load({
writeKey: 'YOUR_WRITE_KEY'
})
// Track pageview
analytics.page()
// Identify user
analytics.identify('user-123', {
name: 'Jane Doe',
email: 'jane@example.com',
plan: 'premium'
})
// Track event
analytics.track('Button Clicked', {
buttonId: 'signup-cta',
location: 'header'
})
Advanced Configuration
import { AnalyticsBrowser } from '@segment/analytics-next'
export const analytics = AnalyticsBrowser.load({
writeKey: process.env.REACT_APP_SEGMENT_WRITE_KEY,
// Regional settings
cdnURL: 'https://cdn.segment.com',
// Privacy controls
integrations: {
All: false, // Disable all by default
'Segment.io': true, // Enable Segment
'Google Analytics 4': true,
'Mixpanel': true
},
// Custom context
context: {
app: {
name: 'MyApp',
version: '2.1.0',
build: '512'
}
}
})
Error Handling
analytics.track('Purchase Completed', {
orderId: '12345',
total: 99.99
})
.then(() => {
console.log('Event sent successfully')
})
.catch((error) => {
console.error('Failed to send event:', error)
// Implement fallback or retry logic
})
Method 3: Google Tag Manager Integration
Deploy Segment through GTM for centralized tag management.
Step 1: Create Custom HTML Tag
- In GTM, navigate to Tags → New
- Select Custom HTML tag type
- Add Segment snippet:
<script>
!function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware"];analytics.factory=function(e){return function(){var t=Array.prototype.slice.call(arguments);t.unshift(e);analytics.push(t);return analytics}};for(var e=0;e<analytics.methods.length;e++){var key=analytics.methods[e];analytics[key]=analytics.factory(key)}analytics.load=function(key,e){var t=document.createElement("script");t.type="text/javascript";t.async=!0;t.src="https://cdn.segment.com/analytics.js/v1/" + key + "/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(t,n);analytics._loadOptions=e};analytics._writeKey="{{Segment Write Key}}";analytics.SNIPPET_VERSION="4.15.3";
analytics.load("{{Segment Write Key}}");
}}();
</script>
Step 2: Create GTM Variable for Write Key
- Navigate to Variables → New → User-Defined Variables
- Variable Type: Lookup Table or Custom JavaScript
- Configure environment mapping:
function() {
var hostname = {{Page Hostname}};
if (hostname.indexOf('localhost') !== -1) {
return 'DEV_WRITE_KEY';
} else if (hostname.indexOf('staging') !== -1) {
return 'STAGING_WRITE_KEY';
} else if (hostname === 'yourdomain.com') {
return 'PRODUCTION_WRITE_KEY';
}
return 'DEFAULT_WRITE_KEY';
}
Step 3: Configure Trigger
- Trigger Type: Page View - Window Loaded
- Fires On: All Pages
- Priority: High (e.g., 999) to load before other tags
Step 4: Track Page Views Automatically
Create a second tag for automatic page tracking:
<script>
if (window.analytics && window.analytics.page) {
analytics.page();
}
</script>
Trigger: All Pages - DOM Ready
Step 5: Track Events via Data Layer
Create event tags that fire on GTM events:
<script>
if (window.analytics && window.analytics.track) {
analytics.track('{{Event Name}}', {
category: '{{Event Category}}',
label: '{{Event Label}}',
value: {{Event Value}}
});
}
</script>
Trigger: Custom Event matching your data layer pushes
Framework-Specific Integrations
React Integration
Using Analytics Hook
// analytics.js
import { AnalyticsBrowser } from '@segment/analytics-next'
export const analytics = AnalyticsBrowser.load({
writeKey: process.env.REACT_APP_SEGMENT_WRITE_KEY
})
// useAnalytics.js
import { useEffect, useCallback } from 'react'
import { analytics } from './analytics'
export function useAnalytics() {
const track = useCallback((eventName, properties) => {
analytics.track(eventName, properties)
}, [])
const page = useCallback((name, properties) => {
analytics.page(name, properties)
}, [])
const identify = useCallback((userId, traits) => {
analytics.identify(userId, traits)
}, [])
return { track, page, identify }
}
// Component usage
function SignupButton() {
const { track } = useAnalytics()
const handleClick = () => {
track('Signup Button Clicked', {
location: 'header',
plan: 'premium'
})
}
return <button Up</button>
}
React Router Integration
// App.js
import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'
import { analytics } from './analytics'
function App() {
const location = useLocation()
useEffect(() => {
analytics.page()
}, [location])
return <YourAppComponents />
}
Context Provider Pattern
// AnalyticsContext.js
import React, { createContext, useContext } from 'react'
import { analytics } from './analytics'
const AnalyticsContext = createContext()
export function AnalyticsProvider({ children }) {
return (
<AnalyticsContext.Provider value={analytics}>
{children}
</AnalyticsContext.Provider>
)
}
export function useSegment() {
return useContext(AnalyticsContext)
}
// App.js
import { AnalyticsProvider } from './AnalyticsContext'
function App() {
return (
<AnalyticsProvider>
<YourApp />
</AnalyticsProvider>
)
}
// Component
import { useSegment } from './AnalyticsContext'
function Component() {
const analytics = useSegment()
const handleEvent = () => {
analytics.track('Event Name', { prop: 'value' })
}
}
Next.js Integration
App Router (Next.js 13+)
// app/providers.js
'use client'
import { AnalyticsBrowser } from '@segment/analytics-next'
import { usePathname, useSearchParams } from 'next/navigation'
import { useEffect } from 'react'
const analytics = AnalyticsBrowser.load({
writeKey: process.env.NEXT_PUBLIC_SEGMENT_WRITE_KEY
})
export function AnalyticsProvider({ children }) {
const pathname = usePathname()
const searchParams = useSearchParams()
useEffect(() => {
analytics.page()
}, [pathname, searchParams])
return <>{children}</>
}
// app/layout.js
import { AnalyticsProvider } from './providers'
export default function RootLayout({ children }) {
return (
<html>
<body>
<AnalyticsProvider>
{children}
</AnalyticsProvider>
</body>
</html>
)
}
Pages Router
// pages/_app.js
import { useEffect } from 'react'
import { useRouter } from 'next/router'
import { AnalyticsBrowser } from '@segment/analytics-next'
const analytics = AnalyticsBrowser.load({
writeKey: process.env.NEXT_PUBLIC_SEGMENT_WRITE_KEY
})
function MyApp({ Component, pageProps }) {
const router = useRouter()
useEffect(() => {
const handleRouteChange = () => {
analytics.page()
}
router.events.on('routeChangeComplete', handleRouteChange)
return () => router.events.off('routeChangeComplete', handleRouteChange)
}, [router.events])
// Track initial page
useEffect(() => {
analytics.page()
}, [])
return <Component {...pageProps} />
}
export default MyApp
Server-Side Identification
// pages/api/identify.js
export default async function handler(req, res) {
const { userId, traits } = req.body
// Server-side Segment call
await fetch('https://api.segment.io/v1/identify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic ' + Buffer.from(process.env.SEGMENT_WRITE_KEY + ':').toString('base64')
},
body: JSON.stringify({
userId: userId,
traits: traits,
timestamp: new Date().toISOString()
})
})
res.status(200).json({ success: true })
}
Vue.js Integration
Vue 3 Composition API
// plugins/segment.js
import { AnalyticsBrowser } from '@segment/analytics-next'
export const analytics = AnalyticsBrowser.load({
writeKey: import.meta.env.VITE_SEGMENT_WRITE_KEY
})
export default {
install: (app) => {
app.config.globalProperties.$analytics = analytics
app.provide('analytics', analytics)
}
}
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import segmentPlugin from './plugins/segment'
const app = createApp(App)
app.use(segmentPlugin)
app.mount('#app')
// Component.vue
<script setup>
import { inject } from 'vue'
const analytics = inject('analytics')
function trackEvent() {
analytics.track('Button Clicked', {
component: 'hero',
action: 'signup'
})
}
</script>
Vue Router Integration
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import { analytics } from '../plugins/segment'
const router = createRouter({
history: createWebHistory(),
routes: [/* your routes */]
})
router.afterEach((to, from) => {
analytics.page(to.name, {
path: to.path,
url: window.location.href
})
})
export default router
Angular Integration
Create Analytics Service
// services/analytics.service.ts
import { Injectable } from '@angular/core'
import { AnalyticsBrowser } from '@segment/analytics-next'
import { environment } from '../environments/environment'
@Injectable({
providedIn: 'root'
})
export class AnalyticsService {
private analytics: any
constructor() {
this.analytics = AnalyticsBrowser.load({
writeKey: environment.segmentWriteKey
})
}
identify(userId: string, traits?: Record<string, any>) {
return this.analytics.identify(userId, traits)
}
track(eventName: string, properties?: Record<string, any>) {
return this.analytics.track(eventName, properties)
}
page(name?: string, properties?: Record<string, any>) {
return this.analytics.page(name, properties)
}
group(groupId: string, traits?: Record<string, any>) {
return this.analytics.group(groupId, traits)
}
reset() {
return this.analytics.reset()
}
}
Router Integration
// app.component.ts
import { Component } from '@angular/core'
import { Router, NavigationEnd } from '@angular/router'
import { filter } from 'rxjs/operators'
import { AnalyticsService } from './services/analytics.service'
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
constructor(
private router: Router,
private analytics: AnalyticsService
) {
this.router.events
.pipe(filter(event => event instanceof NavigationEnd))
.subscribe((event: NavigationEnd) => {
this.analytics.page(event.urlAfterRedirects)
})
}
}
Mobile SDK Installation
iOS (Swift/Objective-C)
Installation via CocoaPods
# Podfile
platform :ios, '13.0'
target 'YourApp' do
use_frameworks!
pod 'Segment', '~> 4.0'
# Optional: Device-mode destinations
pod 'Segment-Mixpanel'
pod 'Segment-Firebase'
pod 'Segment-Amplitude'
end
pod install
Installation via Swift Package Manager
- In Xcode: File → Add Packages
- Enter:
https://github.com/segmentio/analytics-swift - Select version and add to target
Basic Configuration (Swift)
// AppDelegate.swift
import Segment
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let configuration = AnalyticsConfiguration(writeKey: "YOUR_IOS_WRITE_KEY")
// Optional: Enable debug logging
configuration.trackApplicationLifecycleEvents = true
configuration.flushInterval = 30
Analytics.setup(with: configuration)
return true
}
}
Tracking Events
// Track screen view
Analytics.shared().screen("Home Screen", properties: [
"category": "navigation",
"referrer": "app-launch"
])
// Identify user
Analytics.shared().identify("user-123", traits: [
"name": "Jane Doe",
"email": "jane@example.com",
"plan": "premium"
])
// Track event
Analytics.shared().track("Product Viewed", properties: [
"product_id": "SKU-123",
"name": "Premium Subscription",
"price": 99.99,
"currency": "USD"
])
// Track purchase
Analytics.shared().track("Order Completed", properties: [
"order_id": "ORDER-456",
"total": 149.99,
"revenue": 149.99,
"products": [
[
"product_id": "SKU-123",
"name": "Premium Subscription",
"price": 99.99,
"quantity": 1
]
]
])
Android (Kotlin/Java)
Installation via Gradle
// build.gradle (app level)
dependencies {
implementation 'com.segment.analytics.android:analytics:4.+'
// Optional: Device-mode destinations
implementation 'com.segment.analytics.android.integrations:mixpanel:+'
implementation 'com.segment.analytics.android.integrations:firebase:+'
implementation 'com.segment.analytics.android.integrations:amplitude:+'
}
Permissions
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Basic Configuration (Kotlin)
// Application.kt
import android.app.Application
import com.segment.analytics.Analytics
import com.segment.analytics.android.integrations.mixpanel.MixpanelIntegration
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
val analytics = Analytics.Builder(this, "YOUR_ANDROID_WRITE_KEY")
.trackApplicationLifecycleEvents()
.recordScreenViews()
.flushQueueSize(20)
.flushInterval(30, TimeUnit.SECONDS)
.use(MixpanelIntegration.FACTORY) // Device-mode destinations
.build()
Analytics.setSingletonInstance(analytics)
// Enable debug logging
Analytics.setLogLevel(Analytics.LogLevel.VERBOSE)
}
}
Tracking Events
// Track screen view
Analytics.with(context).screen("Home Screen", Properties()
.putValue("category", "navigation")
.putValue("referrer", "app-launch")
)
// Identify user
Analytics.with(context).identify("user-123", Traits()
.putName("Jane Doe")
.putEmail("jane@example.com")
.putValue("plan", "premium")
, null)
// Track event
Analytics.with(context).track("Product Viewed", Properties()
.putValue("product_id", "SKU-123")
.putValue("name", "Premium Subscription")
.putValue("price", 99.99)
.putValue("currency", "USD")
)
// Track purchase
Analytics.with(context).track("Order Completed", Properties()
.putValue("order_id", "ORDER-456")
.putValue("total", 149.99)
.putRevenue(149.99)
)
React Native
Installation
npm install @segment/analytics-react-native
# or
yarn add @segment/analytics-react-native
# iOS specific
cd ios && pod install
Configuration
// App.js
import { createClient } from '@segment/analytics-react-native'
const segmentClient = createClient({
writeKey: 'YOUR_WRITE_KEY',
trackAppLifecycleEvents: true,
trackDeepLinks: true
})
// Track screen
segmentClient.screen('Home Screen', {
category: 'navigation'
})
// Identify user
segmentClient.identify('user-123', {
name: 'Jane Doe',
email: 'jane@example.com'
})
// Track event
segmentClient.track('Button Pressed', {
buttonId: 'signup-cta'
})
Server-Side Implementation
Node.js
Installation
npm install @segment/analytics-node
Basic Usage
const { Analytics } = require('@segment/analytics-node')
const analytics = new Analytics({
writeKey: process.env.SEGMENT_WRITE_KEY,
flushAt: 20, // Flush after 20 events
flushInterval: 10000 // Flush after 10 seconds
})
// Identify user
analytics.identify({
userId: 'user-123',
traits: {
name: 'Jane Doe',
email: 'jane@example.com',
plan: 'premium'
}
})
// Track event
analytics.track({
userId: 'user-123',
event: 'Order Completed',
properties: {
orderId: 'ORDER-456',
total: 149.99,
revenue: 149.99,
currency: 'USD'
}
})
// Graceful shutdown
process.on('SIGTERM', async () => {
await analytics.closeAndFlush()
process.exit(0)
})
Express.js Middleware
const express = require('express')
const { Analytics } = require('@segment/analytics-node')
const app = express()
const analytics = new Analytics({
writeKey: process.env.SEGMENT_WRITE_KEY
})
// Middleware to attach analytics
app.use((req, res, next) => {
req.analytics = analytics
next()
})
// Track API requests
app.post('/api/signup', async (req, res) => {
const { email, name } = req.body
// Create user...
const userId = createUser(email, name)
// Track signup
req.analytics.track({
userId: userId,
event: 'Signed Up',
properties: {
method: 'email',
source: 'website'
}
})
res.json({ success: true, userId })
})
Python
Installation
pip install segment-analytics-python
Basic Usage
from segment import analytics
analytics.write_key = 'YOUR_WRITE_KEY'
# Identify user
analytics.identify('user-123', {
'email': 'jane@example.com',
'name': 'Jane Doe',
'plan': 'premium'
})
# Track event
analytics.track('user-123', 'Order Completed', {
'order_id': 'ORDER-456',
'total': 149.99,
'revenue': 149.99,
'currency': 'USD'
})
# Flush on shutdown
analytics.flush()
Django Integration
# settings.py
SEGMENT_WRITE_KEY = os.environ.get('SEGMENT_WRITE_KEY')
# middleware.py
from segment import analytics
class SegmentMiddleware:
def __init__(self, get_response):
self.get_response = get_response
analytics.write_key = settings.SEGMENT_WRITE_KEY
def __call__(self, request):
request.analytics = analytics
response = self.get_response(request)
return response
# views.py
def signup_view(request):
if request.method == 'POST':
# Create user...
user = create_user(request.POST)
# Track signup
request.analytics.identify(str(user.id), {
'email': user.email,
'name': user.get_full_name()
})
request.analytics.track(str(user.id), 'Signed Up', {
'method': 'email',
'source': 'website'
})
Ruby
Installation
# Gemfile
gem 'analytics-ruby'
Basic Usage
require 'segment/analytics'
analytics = Segment::Analytics.new({
write_key: ENV['SEGMENT_WRITE_KEY'],
on_error: Proc.new { |status, msg| print msg }
})
# Identify user
analytics.identify(
user_id: 'user-123',
traits: {
name: 'Jane Doe',
email: 'jane@example.com',
plan: 'premium'
}
)
# Track event
analytics.track(
user_id: 'user-123',
event: 'Order Completed',
properties: {
order_id: 'ORDER-456',
total: 149.99,
revenue: 149.99
}
)
# Flush on shutdown
analytics.flush
Go
Installation
go get github.com/segmentio/analytics-go/v3
Basic Usage
package main
import (
"os"
"github.com/segmentio/analytics-go/v3"
)
func main() {
client := analytics.New(os.Getenv("SEGMENT_WRITE_KEY"))
defer client.Close()
// Identify user
client.Enqueue(analytics.Identify{
UserId: "user-123",
Traits: analytics.NewTraits().
SetName("Jane Doe").
SetEmail("jane@example.com").
Set("plan", "premium"),
})
// Track event
client.Enqueue(analytics.Track{
UserId: "user-123",
Event: "Order Completed",
Properties: analytics.NewProperties().
Set("order_id", "ORDER-456").
Set("total", 149.99).
Set("revenue", 149.99),
})
}
Configuration & Advanced Features
Device-Mode vs Cloud-Mode
Device-Mode:
- SDK loads destination library directly in client
- Data sent from client to destination
- Required for features like session recording, heatmaps
- Increases bundle size
- Can be blocked by ad blockers
Cloud-Mode:
- Data sent to Segment, then to destination
- Smaller bundle size
- Better for privacy/ad blocker resilience
- Some destination features unavailable
Configure per destination in Segment UI under Connections → Destinations → Settings.
Identity Management
AnonymousId vs UserId
// Track anonymous user
analytics.track('Page Viewed', {
page: 'homepage'
})
// Automatically generates anonymousId
// Identify when user logs in
analytics.identify('user-123', {
email: 'jane@example.com',
name: 'Jane Doe'
})
// Links anonymousId to userId
// Alias to merge pre-signup and post-signup identities
analytics.alias('user-123')
Cross-Domain Tracking
// Persist anonymousId across domains
const anonymousId = analytics.user().anonymousId()
// Pass in URL or form
window.location.href = `https://checkout.yourdomain.com?ajs_aid=${anonymousId}`
// On destination domain, set before loading
analytics.setAnonymousId(anonymousId)
analytics.load(WRITE_KEY)
Consent Management
GDPR Integration
// Don't load until consent granted
let analytics
function grantConsent() {
analytics = AnalyticsBrowser.load({
writeKey: WRITE_KEY,
integrations: {
All: true,
'Segment.io': {
apiHost: 'events.eu1.segmentapis.com'
}
}
})
}
// User grants consent
grantConsent()
Conditional Destination Loading
analytics.load(WRITE_KEY, {
integrations: {
All: false,
'Segment.io': true,
'Google Analytics 4': hasAnalyticsConsent,
'Facebook Pixel': hasMarketingConsent,
'Mixpanel': hasAnalyticsConsent
}
})
Middleware & Transformations
Source Middleware (Client-Side)
analytics.addSourceMiddleware(({ payload, next }) => {
// Add custom context to all events
payload.obj.context = {
...payload.obj.context,
customField: 'custom value',
userAgent: navigator.userAgent
}
// Continue processing
next(payload)
})
Destination Middleware
analytics.addDestinationMiddleware('Google Analytics 4', ({ payload, next }) => {
// Transform data for specific destination
if (payload.obj.type === 'track') {
payload.obj.properties.ga4_custom_field = 'value'
}
next(payload)
})
Verification & Testing
1. Debugger
Use Segment's web debugger:
- Open Segment dashboard
- Navigate to Sources → Your Source → Debugger
- Trigger events on your site/app
- Verify events appear in real-time with correct properties
2. Browser Console
// Check if analytics loaded
typeof analytics !== 'undefined'
// Get current user
analytics.user()
// View user traits
analytics.user().traits()
// Get anonymous ID
analytics.user().anonymousId()
// Get user ID
analytics.user().id()
// Test event
analytics.track('Test Event', { test: true })
3. Network Inspector
Monitor network requests:
- Script:
https://cdn.segment.com/analytics.js/v1/*/analytics.min.js - Events:
https://api.segment.io/v1/torhttps://api.segment.io/v1/batch
4. Event Delivery
Check Event Delivery in Segment:
- Sources → Your Source → Event Delivery
- Review success/failure rates per destination
- Click on failed events to see error details
- Use Event Tester to test specific payloads
Troubleshooting
Events Not Appearing
Problem: Events not showing in debugger or destinations
Solutions:
- Verify write key is correct for environment
- Check network tab for failed requests
- Ensure
analytics.load()called before tracking - Check browser console for errors
- Verify destination is enabled and configured
Identity Resolution Issues
Problem: Users not properly identified across sessions
Solutions:
- Call
analytics.identify()on login/signup - Ensure userId consistent across platforms
- Use
analytics.alias()when changing userId - Check anonymousId persistence (localStorage)
Destination Not Receiving Data
Problem: Segment debugger shows events but destination doesn't
Solutions:
- Check destination settings and connection status
- Verify destination mapping configuration
- Review Event Delivery for specific errors
- Check if destination requires device-mode
- Ensure required properties are included
High Bundle Size
Problem: Segment SDK increases page load time
Solutions:
- Use cloud-mode instead of device-mode where possible
- Load analytics asynchronously
- Implement lazy loading for non-critical destinations
- Use NPM package with tree-shaking
- Consider loading SDK after initial page render
Security Best Practices
1. Write Key Protection
// Good - Use environment variables
const WRITE_KEY = process.env.REACT_APP_SEGMENT_WRITE_KEY
// Bad - Never hardcode in client code
const WRITE_KEY = 'abc123...' // Don't do this!
2. Server-Side for Sensitive Events
// Client-side: Don't send payment details
analytics.track('Checkout Started')
// Server-side: Send after payment processed
analytics.track({
userId: 'user-123',
event: 'Order Completed',
properties: {
orderId: 'ORDER-456',
total: 149.99
}
})
3. PII Handling
// Bad - Sending PII in clear text
analytics.identify('user-123', {
ssn: '123-45-6789',
creditCard: '4111...'
})
// Good - Hash or omit PII
analytics.identify('user-123', {
email_hash: sha256(email),
plan: 'premium'
})
4. Rate Limiting
Implement client-side throttling:
let eventCount = 0
const MAX_EVENTS_PER_MINUTE = 100
function trackWithLimit(event, properties) {
if (eventCount >= MAX_EVENTS_PER_MINUTE) {
console.warn('Event rate limit exceeded')
return
}
eventCount++
setTimeout(() => eventCount--, 60000)
analytics.track(event, properties)
}
Validation Checklist
Before production deployment:
- Correct write key configured per environment
- Events appearing in Segment debugger
- All required destinations receiving data
- Event properties match tracking plan schema
- User identification working (userId/anonymousId)
- Cross-domain tracking functional if needed
- Consent management implemented if required
- Regional endpoints configured (EU/US)
- No PII sent to client-side destinations
- Error handling implemented
- Server-side fallback for critical events
- Bundle size acceptable
- Page load performance not degraded
- Mobile SDK initialized correctly
- Graceful degradation if Segment unavailable
Configuration Recommendations
Destination Mode: Use cloud-mode (server-side) for all destinations that support it — this reduces client-side JavaScript and improves page performance. Only use device-mode when the destination requires it (e.g., Hotjar for session replay, Intercom for live chat widget). Check each destination's docs for mode support.
Identity Resolution: Call analytics.identify(userId, traits) at login and signup. Before authentication, Segment auto-assigns an anonymousId. On identify, Segment merges the anonymous profile with the known user. Never call analytics.alias() unless migrating from a system that used different user IDs — modern Segment handles merging automatically.
Protocols (Tracking Plan): Enable Segment Protocols to enforce your tracking plan schema. Set violations to "block" in production to prevent bad data from reaching destinations. Start with "allow" during development to see violations without blocking events, then switch to "block" before launch.
Data Residency: Choose your Segment region (US or EU) at workspace creation — it cannot be changed later. EU workspaces store data in Dublin (AWS eu-west-1). For destinations, verify each destination's data residency independently since Segment forwards data to destinations in their respective regions.
Performance: The Segment analytics.js bundle is ~36KB gzipped. With device-mode destinations, each adds 10-50KB. If bundle size is a concern, use the Segment CDN with tree-shaking (@segment/analytics-next) and move high-volume events to server-side tracking via Segment's HTTP API.