Интеграция Segment CDP на сайт
Segment — Customer Data Platform: единая точка сбора событий, которая маршрутизирует их в десятки инструментов одновременно. Вместо того чтобы ставить Mixpanel, Amplitude, Intercom и Braze по отдельности, подключаете один SDK и через UI настраиваете destinations. Ключевые концепции — Sources (откуда), Destinations (куда), Protocols (контракт данных).
Архитектура
Браузер / 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) │
└───────────────────────────────────────────────┘
Установка 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, // кастомный proxy опционально
}, {
integrations: {
'All': true,
'Segment.io': {
deliveryStrategy: {
strategy: 'batching',
config: {
size: 10,
timeout: 5000,
},
},
},
},
});
export default analytics;
CDN без бандлера:
<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>
Основные методы
Page
// Автоматически — уже называем явно для SPA
analytics.page('Product', 'Listing', {
url: window.location.href,
path: window.location.pathname,
title: document.title,
referrer: document.referrer,
search: window.location.search,
// кастомные свойства
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 следует ecommerce spec — если называть события по спецификации, они автоматически маппятся в Destinations без дополнительной настройки.
Identify
analytics.identify('usr_12345', {
email: '[email protected]',
name: 'Иван Петров',
plan: 'pro',
company: {
id: 'company_abc',
name: 'ООО Пример',
},
createdAt: '2024-01-15T10:00:00Z',
// Trait-ы, специфичные для вашего продукта
projects_count: 5,
last_login: new Date().toISOString(),
});
Group
// Привязать пользователя к организации (B2B)
analytics.group('company_abc', {
name: 'ООО Пример',
industry: 'Technology',
employees: 25,
plan: 'enterprise',
website: 'https://example.com',
});
Middleware для обогащения событий
// Добавляем контекст ко всем событиям
analytics.addSourceMiddleware(({ payload, next }) => {
// Добавить версию приложения
payload.obj.context = {
...payload.obj.context,
app: {
version: APP_VERSION,
},
locale: navigator.language,
};
// Добавить AB-вариант
const abVariant = localStorage.getItem('ab_variant');
if (abVariant && payload.obj.properties) {
payload.obj.properties.ab_variant = abVariant;
}
next(payload);
});
Server-side источник (Node.js / PHP)
Для событий, которые нельзя трекать с фронта (webhook-оплата, активация подписки):
// Node.js
import { Analytics } from '@segment/analytics-node';
const analytics = new Analytics({
writeKey: process.env.SEGMENT_SERVER_WRITE_KEY,
flushAt: 20,
flushInterval: 10000,
});
// Событие оплаты от платёжного шлюза
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,
},
});
// Обязательно вызвать flush перед завершением процесса
process.on('SIGTERM', async () => {
await analytics.closeAndFlush({ timeout: 5000 });
process.exit(0);
});
// PHP через 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: контракт данных
Segment Protocols позволяет задать JSON Schema для каждого события — нарушения схемы логируются и блокируются:
{
"name": "Order Completed",
"description": "Пользователь завершил оформление заказа",
"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" }
}
}
}
}
}
}
Это особенно ценно в командах: разработчик не может случайно отправить total: "14500" (строку вместо числа) — Protocols отклонит событие и оповестит.
Функции (Destination Functions)
Когда нужного Destination нет в каталоге — пишем Function на JS прямо в UI:
// Segment Function — отправка в кастомный 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}`);
}
}
Сроки
Базовая установка Analytics.js с page/track/identify — 1 день. Настройка Destinations (Mixpanel + BigQuery + CRM) — 2–3 дня. Настройка Protocols и валидации схем — 1 день. Server-side источник + функции — ещё 1–2 дня.







