Segment CDP Integration
Segment is a Customer Data Platform: a single point for event collection that routes them to dozens of tools simultaneously. Instead of installing Mixpanel, Amplitude, Intercom, and Braze separately, you connect one SDK and configure destinations via UI. Key concepts — Sources (where from), Destinations (where to), Protocols (data contract).
Architecture
Browser / Server / Mobile
│
Segment Analytics.js / Node SDK
│
┌────┴─────────────────────────┐
│ Segment │
│ Sources → Protocols → ... │
└────┬─────────────────────────┘
│
┌────┴──────────────────────────────────────────┐
│ Destinations │
│ ├── Mixpanel (event analytics) │
│ ├── Amplitude (product analytics) │
│ ├── BigQuery (data warehouse) │
│ ├── Intercom (customer messaging) │
│ ├── Braze (marketing automation) │
│ ├── HubSpot (CRM) │
│ └── Webhook (custom) │
└───────────────────────────────────────────────┘
Installation of Analytics.js 2.0
npm install @segment/analytics-next
// src/analytics/segment.ts
import { AnalyticsBrowser } from '@segment/analytics-next';
export const analytics = AnalyticsBrowser.load({
writeKey: import.meta.env.VITE_SEGMENT_WRITE_KEY,
cdnURL: undefined, // custom proxy optional
}, {
integrations: {
'All': true,
'Segment.io': {
deliveryStrategy: {
strategy: 'batching',
config: {
size: 10,
timeout: 5000,
},
},
},
},
});
export default analytics;
CDN without bundler:
<script>
!function(){var i="analytics",analytics=window[i]=window[i]||[];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","register"];analytics.factory=function(e){return function(){if(window[i].initialized)return window[i][e].apply(window[i],arguments);var n=Array.prototype.slice.call(arguments);if(["track","screen","alias","group","page","identify"].indexOf(e)>-1){var c=document.querySelector("link[rel='canonical']");n.push({__t:"bpc",c:c&&c.getAttribute("href")||void 0,p:location.pathname,u:location.href,s:location.search,t:document.title,r:document.referrer})}n.unshift(e);analytics.push(n);return analytics}};for(var n=0;n<analytics.methods.length;n++){var key=analytics.methods[n];analytics[key]=analytics.factory(key)}analytics.load=function(key,n){var t=document.createElement("script");t.type="text/javascript";t.async=!0;t.setAttribute("data-global-segment-analytics-key",i);t.src="https://cdn.segment.com/analytics.js/v1/"+key+"/analytics.min.js";var r=document.getElementsByTagName("script")[0];r.parentNode.insertBefore(t,r);analytics._writeKey=key;analytics._loadOptions=n};analytics.SNIPPET_VERSION="5.2.1";
analytics.load("YOUR_WRITE_KEY");
analytics.page();
}}();
</script>
Core Methods
Page
// Automatically — explicitly name for SPA
analytics.page('Product', 'Listing', {
url: window.location.href,
path: window.location.pathname,
title: document.title,
referrer: document.referrer,
search: window.location.search,
// custom properties
category: 'electronics',
locale: 'ru-RU',
});
Track
analytics.track('Order Completed', {
order_id: 'ORDER-789',
affiliation: 'Web Store',
total: 14500,
subtotal: 13500,
revenue: 14500,
shipping: 500,
tax: 500,
discount: 0,
currency: 'RUB',
products: [
{
product_id: 'SKU-001',
sku: 'SKU-001',
name: 'Professional Plan',
price: 13500,
quantity: 1,
category: 'subscription',
},
],
});
Segment follows ecommerce spec — naming events per spec auto-maps them to Destinations without extra setup.
Identify
analytics.identify('usr_12345', {
email: '[email protected]',
name: 'Ivan Petrov',
plan: 'pro',
company: {
id: 'company_abc',
name: 'Example Inc',
},
createdAt: '2024-01-15T10:00:00Z',
// Product-specific traits
projects_count: 5,
last_login: new Date().toISOString(),
});
Group
// Attach user to organization (B2B)
analytics.group('company_abc', {
name: 'Example Inc',
industry: 'Technology',
employees: 25,
plan: 'enterprise',
website: 'https://example.com',
});
Middleware for Event Enrichment
// Add context to all events
analytics.addSourceMiddleware(({ payload, next }) => {
// Add app version
payload.obj.context = {
...payload.obj.context,
app: {
version: APP_VERSION,
},
locale: navigator.language,
};
// Add AB variant
const abVariant = localStorage.getItem('ab_variant');
if (abVariant && payload.obj.properties) {
payload.obj.properties.ab_variant = abVariant;
}
next(payload);
});
Server-side Source (Node.js / PHP)
For events that can't be tracked from frontend (webhook payment, subscription activation):
// Node.js
import { Analytics } from '@segment/analytics-node';
const analytics = new Analytics({
writeKey: process.env.SEGMENT_SERVER_WRITE_KEY,
flushAt: 20,
flushInterval: 10000,
});
// Payment event from gateway
analytics.track({
userId: 'usr_12345',
event: 'Subscription Started',
properties: {
plan: 'pro',
revenue: 2990,
currency: 'RUB',
billing_cycle: 'monthly',
payment_method: 'card',
mrr: 2990,
},
context: {
ip: clientIp,
},
});
// Must flush before process exit
process.on('SIGTERM', async () => {
await analytics.closeAndFlush({ timeout: 5000 });
process.exit(0);
});
// PHP via HTTP API
class SegmentService
{
private string $writeKey;
private string $endpoint = 'https://api.segment.io/v1/track';
public function track(string $userId, string $event, array $properties = []): void
{
Http::withBasicAuth($this->writeKey, '')
->timeout(3)
->post($this->endpoint, [
'userId' => $userId,
'event' => $event,
'properties' => $properties,
'timestamp' => now()->toIso8601String(),
'messageId' => uniqid('php_', true),
'context' => ['library' => ['name' => 'analytics-php']],
]);
}
}
Protocols: Data Contract
Segment Protocols lets you define JSON Schema for each event — schema violations are logged and blocked:
{
"name": "Order Completed",
"description": "User completed checkout",
"rules": {
"required": ["order_id", "total", "currency"],
"properties": {
"order_id": { "type": "string" },
"total": { "type": "number", "minimum": 0 },
"currency": { "type": "string", "enum": ["RUB", "USD", "EUR"] },
"products": {
"type": "array",
"items": {
"required": ["product_id", "price"],
"properties": {
"product_id": { "type": "string" },
"price": { "type": "number" }
}
}
}
}
}
}
Invaluable for teams: developer can't accidentally send total: "14500" (string vs number) — Protocols rejects it and alerts.
Functions (Destination Functions)
When the needed Destination isn't in the catalog — write a Function in JS directly in UI:
// Segment Function — send to custom webhook
async function onTrack(event, settings) {
if (event.event !== 'Order Completed') return;
const response = await fetch(settings.webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': settings.apiKey },
body: JSON.stringify({
orderId: event.properties.order_id,
userId: event.userId,
revenue: event.properties.total,
timestamp: event.timestamp,
}),
});
if (!response.ok) {
throw new Error(`Webhook failed: ${response.status}`);
}
}
Timeline
Basic Analytics.js setup with page/track/identify — 1 day. Destination configuration (Mixpanel + BigQuery + CRM) — 2–3 days. Protocols and schema validation — 1 day. Server-side source + functions — 1–2 more days.







