Segment is the leading Customer Data Platform (CDP) — analytics.load(writeKey) initializes the browser SDK. analytics.identify(userId, { email, name, plan }) associates all subsequent events with the user. analytics.track("Order Completed", { orderId, revenue, currency, products }) fires a structured event. analytics.page("Home", { url, title, referrer }) logs page views. analytics.group(groupId, { name, plan, employees }) associates the user with an account. Segment routes events to 400+ destinations (Mixpanel, Amplitude, Braze, Salesforce, BigQuery, Snowflake) without code changes. Server-side Node.js: new Analytics({ writeKey }), analytics.track({ userId, event, properties }), analytics.flush(). TypeScript typed analytics with analytics-next: import { AnalyticsBrowser } from "@segment/analytics-next", const analytics = AnalyticsBrowser.load({ writeKey }), then analytics.track(...) — fully typed. Protocols: define a JSON Schema tracking plan, Segment validates events against it and flags violations. Source Functions: JavaScript functions that transform incoming webhooks into Segment events. Destination Functions: custom destinations in JavaScript that run per-event. Claude Code generates Segment tracking plans, typed analytics wrappers, and server-side enrichment pipelines.
CLAUDE.md for Segment
## Segment Stack
- Browser version: @segment/analytics-next >= 1.x (replaces classic Analytics.js)
- Node version: @segment/analytics-node >= 1.x
- Browser init: const analytics = AnalyticsBrowser.load({ writeKey: WRITE_KEY })
- Identify: analytics.identify(userId, { email, name, plan, createdAt })
- Track: analytics.track("Event Name", { prop1: value1, prop2: value2 })
- Page: analytics.page() — or analytics.page("Page Name", { url, path }) in SPA
- Server: const analytics = new Analytics({ writeKey }); analytics.track({ userId, event, properties }); await analytics.closeAndFlush()
- Segment routes events to all connected destinations without extra code
Typed Analytics Client
// lib/segment/analytics.ts — typed Segment analytics client
import { AnalyticsBrowser } from "@segment/analytics-next"
// Singleton — reuse across app
export const analytics = AnalyticsBrowser.load({
writeKey: process.env.NEXT_PUBLIC_SEGMENT_WRITE_KEY!,
cdnURL: process.env.NEXT_PUBLIC_SEGMENT_CDN_URL, // optional proxy
})
// ── Type definitions ───────────────────────────────────────────────────────
export type UserTraits = {
email?: string
name?: string
firstName?: string
lastName?: string
plan?: "free" | "pro" | "enterprise"
createdAt?: string // ISO 8601
company?: string
role?: string
}
export type GroupTraits = {
name: string
plan?: string
employees?: number
industry?: string
website?: string
}
// ── Typed event catalog ────────────────────────────────────────────────────
type Events = {
"Signed Up": { method: "email" | "google" | "github" }
"Signed In": { method: string }
"Signed Out": Record<string, never>
"Plan Upgraded": { fromPlan: string; toPlan: string; revenue: number }
"Feature Used": { featureName: string; context?: string }
"Checkout Started": { cartValue: number; itemCount: number; currency: string }
"Order Completed": { orderId: string; revenue: number; currency: string; products: unknown[] }
"Form Submitted": { formName: string }
"Search Performed": { query: string; resultCount: number }
"Error Encountered": { errorCode: string; errorMessage: string; route: string }
}
type EventNames = keyof Events
/** Typed track — narrow to known events */
export function track<E extends EventNames>(event: E, properties: Events[E]): void {
analytics.track(event, properties as Record<string, unknown>)
}
/** Identify user — stored and forwarded to all destinations */
export function identify(userId: string, traits: UserTraits = {}): void {
analytics.identify(userId, traits as Record<string, unknown>)
}
/** Group / account call */
export function group(groupId: string, traits: GroupTraits): void {
analytics.group(groupId, traits as Record<string, unknown>)
}
/** Page call — use in layout or router hooks */
export function page(name?: string, properties?: Record<string, unknown>): void {
if (name) {
analytics.page(name, properties)
} else {
analytics.page()
}
}
/** Reset identity on sign-out */
export function reset(): void {
analytics.reset()
}
React Analytics Provider
// components/AnalyticsProvider.tsx — auto-page-view + session init
"use client"
import { useEffect, useRef } from "react"
import { usePathname } from "next/navigation"
import { identify, page } from "@/lib/segment/analytics"
type Props = {
userId?: string
userTraits?: Record<string, string>
children: React.ReactNode
}
export default function AnalyticsProvider({ userId, userTraits, children }: Props) {
const pathname = usePathname()
const initialized = useRef(false)
// Identify user once on mount (or when userId changes)
useEffect(() => {
if (userId && !initialized.current) {
identify(userId, userTraits)
initialized.current = true
}
}, [userId, userTraits])
// Track page views on route change
useEffect(() => {
page(undefined, { url: window.location.href, path: pathname })
}, [pathname])
return <>{children}</>
}
// Usage in app/layout.tsx:
// import { auth } from "@/lib/auth"
// const session = await auth()
// return (
// <html><body>
// <AnalyticsProvider userId={session?.user.id} userTraits={{ email: session?.user.email }}>
// {children}
// </AnalyticsProvider>
// </body></html>
// )
Server-Side Node.js Tracking
// lib/segment/server.ts — server-side Segment for backend events
import { Analytics } from "@segment/analytics-node"
const serverAnalytics = new Analytics({
writeKey: process.env.SEGMENT_WRITE_KEY!, // server-side write key (different from browser)
maxEventsInBatch: 100,
httpRequestTimeout: 10000,
})
export type ServerTrackOptions = {
userId: string
event: string
properties?: Record<string, unknown>
context?: { ip?: string; userAgent?: string; locale?: string }
timestamp?: Date
}
/** Track a server-side event (payment processing, webhooks, etc.) */
export async function serverTrack(options: ServerTrackOptions): Promise<void> {
serverAnalytics.track({
userId: options.userId,
event: options.event,
properties: options.properties ?? {},
context: {
...(options.context ?? {}),
library: { name: "segment-node", version: "1.x" },
},
...(options.timestamp ? { timestamp: options.timestamp } : {}),
})
}
/** Server identify (e.g. after backend user update) */
export async function serverIdentify(
userId: string,
traits: Record<string, unknown>,
): Promise<void> {
serverAnalytics.identify({ userId, traits })
}
/** Flush events and close (call at process end or in Vercel edge functions) */
export async function flushAnalytics(): Promise<void> {
await serverAnalytics.closeAndFlush({ timeout: 5000 })
}
// Next.js API route usage:
// export async function POST(req: Request) {
// const { userId, amount } = await req.json()
// await serverTrack({ userId, event: "Order Completed", properties: { revenue: amount, currency: "USD" } })
// return NextResponse.json({ ok: true })
// }
For the PostHog alternative when needing an open-source, self-hostable product analytics platform with feature flags, A/B testing, session recording, and funnel analysis all in one tool without a per-event pricing model — PostHog is a powerful all-in-one self-hosted product analytics suite while Segment is the gold standard for a vendor-neutral event router that connects data to any downstream destination, see the PostHog guide. For the RudderStack alternative when wanting an open-source, self-hostable Segment alternative with the same Connections model, warehouse-native transformations, and lower per-event cost — RudderStack is the open-source CDP that replicates Segment’s architecture while Segment has the largest destination ecosystem and most reliable delivery guarantees, see the RudderStack guide. The Claude Skills 360 bundle includes Segment skill sets covering typed event tracking, identify/group calls, and server-side pipelines. Start with the free tier to try customer data platform generation.