Segment
Segment is a customer data platform that routes your
event data to downstream destinations (analytics, marketing, warehouses, ...).
This destination forwards walkerOS events to Segment via the official
@segment/analytics-next
(Analytics.js 2.0) SDK, calling the Segment Spec methods track, identify,
group, page, and reset. With settings.consent, it also stamps consent
context on every call.
Segment is a web destination in the walkerOS flow:
Installation
npm install @walkeros/web-destination-segment- Integrated
- Bundled
import { startFlow } from '@walkeros/collector';
import { destinationSegment } from '@walkeros/web-destination-segment';
await startFlow({
destinations: {
segment: {
code: destinationSegment,
config: {
settings: {
apiKey: 'YOUR_SEGMENT_WRITE_KEY',
},
},
},
},
});Add to your flow.json destinations:
"destinations": {
"segment": {
"package": "@walkeros/web-destination-segment",
"config": {
"settings": {
"apiKey": "YOUR_SEGMENT_WRITE_KEY"
}
}
}
}Configuration
This destination uses the standard destination config wrapper (consent, data, env, id, ...). For the shared fields see destination configuration. Package-specific fields live under config.settings and are listed below.
Settings
| Property | Type | Description | More |
|---|---|---|---|
apiKey | string | Your Segment source write key. Find it in your Segment workspace under Connections, Sources, Settings, API Keys. Maps to `writeKey` in the Analytics.js `load()` call (like a1B2c3D4e5F6a1B2c3D4e5F6a1B2c3D4). | |
cdnURL | string | Not applied: the destination passes it in the load() options, where Analytics.js does not read it, so settings are always fetched from https://cdn.segment.com. | |
initialPageview | boolean | When true, the SDK fires an automatic initial page() call on load. Default: false (walkerOS sources handle page tracking, so this is disabled to avoid duplicate page views). | |
disableClientPersistence | boolean | When true, prevents any cookie or localStorage writes. Useful for privacy-conscious setups. Default: false. | |
disableAutoISOConversion | boolean | Disable automatic ISO string → Date conversion. Default: false. | |
retryQueue | boolean | Retry failed events. Default: true. | |
obfuscate | boolean | Obfuscate event payloads. Default: false. | |
integrations | Record<string, any> | Enable/disable downstream Segment destinations. Example: { "All": true, "Mixpanel": false }. | |
identify | any | Destination-level identity mapping. Resolves to an object with any of: userId, traits, anonymousId. Resolved on every push: analytics.identify fires on the first push and when userId or traits change, and on every push while anonymousId is set. | |
group | any | Destination-level group mapping. Resolves to an object with: groupId, traits. Fires on the first push and re-fires on change. | |
consent | Record<string, string> | Mapping from walkerOS consent keys → Segment `categoryPreferences` keys. Example: { "marketing": "Advertising", "analytics": "Analytics" }. Only mapped keys are forwarded; when omitted, no consent context is sent. |
Mapping
Per-event rules under config.mapping. For the standard rule fields (consent, condition, data, batch, name, policy) see mapping.
| Property | Type | Description | More |
|---|---|---|---|
identify | any | Per-event identity mapping. Resolves to an object with any of: userId, traits, anonymousId. Use with rule-level `silent: true` on login/identify events. | |
group | any | Per-event group assignment. Resolves to { groupId, traits }. Use with rule-level `silent: true` on company/team events. | |
page | any | Per-event page call configuration. Resolves to { category?, name?, properties? } for analytics.page(), or `true` for an empty analytics.page() that relies on SDK auto-collection. Use with rule-level `silent: true` on page view events. | |
reset | any | Logout trigger. Resolves to a truthy value → analytics.reset() (clears userId, anonymousId, traits). Typically used with silent: true on a user logout rule. |
Examples
Group company
A company update fires Segment analytics.group with a groupId and traits for account-level tracking.
{
"name": "company update",
"data": {
"company_id": "comp-456",
"company_name": "Acme",
"industry": "tech",
"employees": 50,
"plan": "enterprise"
},
"context": {
"dev": [
"test",
1
]
},
"globals": {
"lang": "elb"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "child",
"data": {
"is": "subordinated"
}
}
],
"consent": {
"functional": true
},
"id": "5be7db50a6ea6322",
"trigger": "test",
"entity": "company",
"action": "update",
"timestamp": 1700000108,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"group": {
"map": {
"groupId": "data.company_id",
"traits": {
"map": {
"name": "data.company_name",
"industry": "data.industry",
"employees": "data.employees",
"plan": "data.plan"
}
}
}
}
}
}analytics.group("comp-456", {
"name": "Acme",
"industry": "tech",
"employees": 50,
"plan": "enterprise"
})Consent context
With settings.consent mapping analytics to Analytics and marketing to Advertising, the event consent is stamped on every Segment call via context.consent.categoryPreferences for downstream filtering.
{
"name": "product view",
"data": {
"id": "ers",
"name": "Everyday Ruck Snack",
"color": "black",
"size": "l",
"price": 420
},
"context": {
"shopping": [
"detail",
0
]
},
"globals": {
"pagegroup": "shop"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [],
"consent": {
"analytics": true,
"marketing": true
},
"id": "a5df0682a86f1caa",
"trigger": "load",
"entity": "product",
"action": "view",
"timestamp": 1700000112,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}analytics.track("product view", {}, {
"context": {
"consent": {
"categoryPreferences": {
"Analytics": true,
"Advertising": true
}
}
}
})Consent deferred load
With consent: { analytics: true } in the destination config, a walker consent grant triggers the deferred Segment analytics.load with the configured writeKey.
{
"analytics": true
}analytics.load({
"writeKey": "test-project"
}, {
"initialPageview": false
})Default track
A walker event becomes a Segment analytics.track call with the event name and empty properties.
{
"name": "product view",
"data": {
"id": "ers",
"name": "Everyday Ruck Snack",
"color": "black",
"size": "l",
"price": 420
},
"context": {
"shopping": [
"detail",
0
]
},
"globals": {
"pagegroup": "shop"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [],
"consent": {
"functional": true
},
"id": "7f7bc382d01e4cd3",
"trigger": "load",
"entity": "product",
"action": "view",
"timestamp": 1700000100,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}analytics.track("product view", {})Destination identify
With settings.identify mapping userId to 'user.id', the destination calls analytics.identify before the default track.
{
"name": "page view",
"data": {
"domain": "www.example.com",
"title": "walkerOS documentation",
"referrer": "https://www.walkeros.io/",
"search": "?foo=bar",
"hash": "#hash",
"id": "/docs/"
},
"context": {
"dev": [
"test",
1
]
},
"globals": {
"pagegroup": "docs"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "child",
"data": {
"is": "subordinated"
}
}
],
"consent": {
"functional": true
},
"id": "dacd71cd25fb871a",
"trigger": "load",
"entity": "page",
"action": "view",
"timestamp": 1700000104,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}analytics.identify("us3r", {});
analytics.track("page view", {})Include data
With include: ['data'] in the destination config, the event data section is flattened into prefixed Segment track properties.
{
"name": "product view",
"data": {
"id": "ers",
"name": "Everyday Ruck Snack",
"color": "black",
"size": "l",
"price": 420
},
"context": {
"shopping": [
"detail",
0
]
},
"globals": {
"pagegroup": "shop"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [],
"consent": {
"functional": true
},
"id": "c644f8ebdb794af4",
"trigger": "load",
"entity": "product",
"action": "view",
"timestamp": 1700000102,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}analytics.track("product view", {
"data_id": "ers",
"data_name": "Everyday Ruck Snack",
"data_color": "black",
"data_size": "l",
"data_price": 420
})Initialization
Destination bootstrap calls analytics.load with the Segment writeKey and walker default options.
{
"settings": {
"apiKey": "test-project"
}
}analytics.load({
"writeKey": "test-project"
}, {
"initialPageview": false
})Order completed
A completed order is mapped to the Segment Spec Order Completed event with a nested products array.
{
"name": "order complete",
"data": {
"id": "0rd3r1d",
"currency": "EUR",
"shipping": 5.22,
"taxes": 73.76,
"total": 555
},
"context": {
"shopping": [
"complete",
0
]
},
"globals": {
"pagegroup": "shop"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "product",
"data": {
"id": "ers",
"name": "Everyday Ruck Snack",
"color": "black",
"size": "l",
"price": 420
},
"context": {
"shopping": [
"complete",
0
]
},
"nested": []
},
{
"entity": "product",
"data": {
"id": "cc",
"name": "Cool Cap",
"size": "one size",
"price": 42
},
"context": {
"shopping": [
"complete",
0
]
},
"nested": []
},
{
"entity": "gift",
"data": {
"name": "Surprise"
},
"context": {
"shopping": [
"complete",
0
]
},
"nested": []
}
],
"consent": {
"functional": true
},
"id": "0f99e95e2ec76641",
"trigger": "load",
"entity": "order",
"action": "complete",
"timestamp": 1700000111,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"name": "Order Completed",
"data": {
"map": {
"order_id": "data.id",
"currency": {
"key": "data.currency",
"value": "EUR"
},
"shipping": "data.shipping",
"tax": "data.taxes",
"total": "data.total",
"products": {
"loop": [
"nested",
{
"condition": {
"$code": "e=>{var t;return\"number\"==typeof(null==(t=null==e?void 0:e.data)?void 0:t.price)}"
},
"map": {
"product_id": "data.id",
"name": "data.name",
"price": "data.price",
"quantity": {
"key": "data.quantity",
"value": 1
},
"currency": {
"key": "data.currency",
"value": "EUR"
}
}
}
]
}
}
}
}analytics.track("Order Completed", {
"order_id": "0rd3r1d",
"currency": "EUR",
"shipping": 5.22,
"tax": 73.76,
"total": 555,
"products": [
{
"product_id": "ers",
"name": "Everyday Ruck Snack",
"price": 420,
"quantity": 1,
"currency": "EUR"
},
{
"product_id": "cc",
"name": "Cool Cap",
"price": 42,
"quantity": 1,
"currency": "EUR"
}
]
})Page view
A page view fires Segment analytics.page with category, name, and properties instead of a generic track.
{
"name": "page view",
"data": {
"category": "docs",
"title": "Getting Started",
"section": "tutorials"
},
"context": {
"dev": [
"test",
1
]
},
"globals": {
"pagegroup": "docs"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "child",
"data": {
"is": "subordinated"
}
}
],
"consent": {
"functional": true
},
"id": "5c63c8febd5adc5a",
"trigger": "load",
"entity": "page",
"action": "view",
"timestamp": 1700000109,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"page": {
"map": {
"category": "data.category",
"name": "data.title",
"properties": {
"map": {
"section": "data.section"
}
}
}
}
}
}analytics.page("docs", "Getting Started", {
"section": "tutorials"
})Page view minimal
A mapping with page: true fires an empty analytics.page call relying on Segment's auto-collection.
{
"name": "page view",
"data": {
"domain": "www.example.com",
"title": "walkerOS documentation",
"referrer": "https://www.walkeros.io/",
"search": "?foo=bar",
"hash": "#hash",
"id": "/docs/"
},
"context": {
"dev": [
"test",
1
]
},
"globals": {
"pagegroup": "docs"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "child",
"data": {
"is": "subordinated"
}
}
],
"consent": {
"functional": true
},
"id": "c41a6e9e6f611114",
"trigger": "load",
"entity": "page",
"action": "view",
"timestamp": 1700000110,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"page": true
}
}analytics.page()Profile update
A profile update calls Segment analytics.identify with traits and no userId to merge traits into the current profile.
{
"name": "profile update",
"data": {
"name": "Jane Q. Doe",
"avatar_url": "https://example.com/avatar.png",
"phone": "+1234567890"
},
"context": {
"dev": [
"test",
1
]
},
"globals": {
"lang": "elb"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "child",
"data": {
"is": "subordinated"
}
}
],
"consent": {
"functional": true
},
"id": "b8a9b1df1973e8c7",
"trigger": "test",
"entity": "profile",
"action": "update",
"timestamp": 1700000106,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"identify": {
"map": {
"traits": {
"map": {
"name": "data.name",
"avatar": "data.avatar_url",
"phone": "data.phone"
}
}
}
}
}
}analytics.identify(null, {
"name": "Jane Q. Doe",
"avatar": "https://example.com/avatar.png",
"phone": "+1234567890"
})Rule include overrides
With include: ['data'] in the destination config, the rule's include: ['globals'] replaces it, so this event forwards only globals.
{
"name": "order complete",
"data": {
"id": "0rd3r1d",
"currency": "EUR",
"shipping": 5.22,
"taxes": 73.76,
"total": 555
},
"context": {
"shopping": [
"complete",
0
]
},
"globals": {
"pagegroup": "shop"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "product",
"data": {
"id": "ers",
"name": "Everyday Ruck Snack",
"color": "black",
"size": "l",
"price": 420
},
"context": {
"shopping": [
"complete",
0
]
},
"nested": []
},
{
"entity": "product",
"data": {
"id": "cc",
"name": "Cool Cap",
"size": "one size",
"price": 42
},
"context": {
"shopping": [
"complete",
0
]
},
"nested": []
},
{
"entity": "gift",
"data": {
"name": "Surprise"
},
"context": {
"shopping": [
"complete",
0
]
},
"nested": []
}
],
"consent": {
"functional": true
},
"id": "66b0548b99be2a75",
"trigger": "load",
"entity": "order",
"action": "complete",
"timestamp": 1700000103,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"include": [
"globals"
]
}analytics.track("order complete", {
"globals_pagegroup": "shop"
})User login identify
A user login fires Segment analytics.identify with userId and reserved traits such as email, name, and plan.
{
"name": "user login",
"data": {
"user_id": "new-user-123",
"email": "user@acme.com",
"name": "Jane Doe",
"plan": "premium",
"company_name": "Acme",
"company_id": "comp-456"
},
"context": {
"dev": [
"test",
1
]
},
"globals": {
"lang": "elb"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "child",
"data": {
"is": "subordinated"
}
}
],
"consent": {
"functional": true
},
"id": "98c4aa19829b2546",
"trigger": "test",
"entity": "user",
"action": "login",
"timestamp": 1700000105,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"identify": {
"map": {
"userId": "data.user_id",
"traits": {
"map": {
"email": "data.email",
"name": "data.name",
"plan": "data.plan",
"company": {
"map": {
"name": "data.company_name",
"id": "data.company_id"
}
}
}
}
}
}
}
}analytics.identify("new-user-123", {
"email": "user@acme.com",
"name": "Jane Doe",
"plan": "premium",
"company": {
"name": "Acme",
"id": "comp-456"
}
})User logout reset
A user logout calls analytics.reset to clear userId, anonymousId, and traits then generate a new anonymous id.
{
"name": "user logout",
"data": {
"string": "foo",
"number": 1,
"boolean": true,
"array": [
0,
"text",
false
]
},
"context": {
"dev": [
"test",
1
]
},
"globals": {
"lang": "elb"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "child",
"data": {
"is": "subordinated"
}
}
],
"consent": {
"functional": true
},
"id": "6dce83812f36320c",
"trigger": "test",
"entity": "user",
"action": "logout",
"timestamp": 1700000107,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"reset": true
}
}analytics.reset()Consent
The destination supports two complementary consent mechanisms.
Automatic context forwarding. When settings.consent is configured,
every track, identify, group, and page call is stamped with
context.consent.categoryPreferences. walkerOS consent keys are remapped
to Segment category names:
settings: {
apiKey: 'WRITE_KEY',
consent: {
analytics: 'Analytics',
marketing: 'Advertising',
},
}Deferred-load consent pattern. When config.consent is declared (see
consent management), AnalyticsBrowser.load() is held until the first walker consent command
that grants all required keys. Analytics.js has no optOut() method, so the
destination enforces consent by not loading the SDK before it is granted. A
later revocation stops further events at the walkerOS consent gate; the
loaded SDK stays on the page.
destinations: {
segment: {
code: destinationSegment,
config: {
consent: { analytics: true },
settings: { apiKey: 'WRITE_KEY' },
},
},
}Scope notes
alias()andscreen()have no setting in this destination.screen()is for mobile apps.- Plugins, source middleware, and destination middleware cannot be added
through this destination: it creates the
AnalyticsBrowserinstance internally and does not expose it.