Amplitude
Server-side event delivery to Amplitude for product analytics, using the official @amplitude/analytics-node SDK. Supports track, identify, revenue, setGroup, groupIdentify, and flush calls with per-event identity via EventOptions.
Amplitude is a server destination in the walkerOS flow:
Sends events server-side to Amplitude's HTTP API, providing reliable delivery with identity resolution, revenue tracking, and group analytics without browser-side SDK overhead.
Installation
npm install @walkeros/server-destination-amplitude- Integrated
- Bundled
import { startFlow } from '@walkeros/collector';
import { destinationAmplitude } from '@walkeros/server-destination-amplitude';
await startFlow({
destinations: {
amplitude: {
code: destinationAmplitude,
config: {
settings: {
apiKey: 'YOUR_AMPLITUDE_API_KEY',
},
},
},
},
});Add to your flow.json destinations:
"destinations": {
"amplitude": {
"package": "@walkeros/server-destination-amplitude",
"import": "destinationAmplitude",
"config": {
"settings": {
"apiKey": "YOUR_AMPLITUDE_API_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 Amplitude project API key. Find it in your Amplitude project settings under "General" -> "API Keys". | |
serverZone | 'US' | 'EU' | Amplitude data residency zone. Use EU for European data residency. Default: US. | |
flushIntervalMillis | integer | How often (in ms) to flush the event queue. Default: 10000. | |
flushQueueSize | integer | Max queued events before a flush. Default: 200. | |
flushMaxRetries | integer | Max retries on failed flush. Default: 12. | |
useBatch | boolean | Use the Amplitude batch endpoint for higher rate limits. Recommended for high-volume server flows. Default: false. | |
minIdLength | integer | Minimum length for user_id and device_id fields. | |
serverUrl | string | Custom server URL for proxies or self-hosted endpoints. | |
optOut | boolean | Initial opt-out state. When true, no events are sent. Default: false. | |
enableRequestBodyCompression | boolean | Enable gzip compression for request payloads. Default: false. | |
identify | any | walkerOS mapping value resolving to per-event identity. Keys: user_id, device_id, session_id, set, setOnce, add, append, prepend, preInsert, postInsert, remove, unset, clearAll. | |
eventOptions | any | walkerOS mapping value resolving to per-event EventOptions. Keys: time, insert_id, ip, city, country, region, language, platform, os_name, os_version, device_brand, device_model, app_version, user_agent. | |
include | Array<string> | walkerOS event sections to include as event_properties (like ['data', 'globals']). |
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: user_id, device_id, session_id, set, setOnce, add, append, prepend, preInsert, postInsert, remove, unset, clearAll. | |
revenue | any | Revenue mapping. Resolves to a single object or (via loop) an array, each with: productId, price, quantity, revenueType, currency, revenue, receipt, receiptSig, eventProperties. One amplitude.revenue() call fires per item. | |
group | any | Group assignment. Resolves to { type, name } -> amplitude.setGroup(type, name, eventOptions). | |
groupIdentify | any | Group properties. Resolves to { type, name, set?, setOnce?, ... } -> amplitude.groupIdentify(type, name, identify, eventOptions). | |
eventOptions | any | Per-rule EventOptions override. Resolves to { time?, insert_id?, ip?, ... }. Overrides destination-level eventOptions for this rule. | |
include | Array<string> | Per-rule include override. Replaces destination-level include for this rule. |
Examples
Consent granted
A walker consent command with analytics granted opts back into Amplitude tracking via setOptOut(false).
{
"analytics": true
}amplitude.setOptOut(false)Consent revoked
After analytics consent is granted (Amplitude loads), revoking it opts out of tracking via setOptOut(true).
{
"analytics": false
}amplitude.setOptOut(false);
amplitude.setOptOut(true)Default event
A walkerOS event forwarded as an Amplitude 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": "ffef5cd62587c616",
"trigger": "load",
"entity": "product",
"action": "view",
"timestamp": 1700000100,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}amplitude.track("product view", {})Identify per event
Destination-level identify resolves user_id, device_id, and session_id into the Amplitude EventOptions on every call.
{
"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": "c82508451912bc88",
"trigger": "load",
"entity": "page",
"action": "view",
"timestamp": 1700000104,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}amplitude.track("page view", {}, {
"user_id": "us3r",
"device_id": "c00k13",
"session_id": 394324160
})Include data section
Destination-level include flattens the event data section into prefixed event_properties on every track call.
{
"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": "ae9817f1e4abf6e8",
"trigger": "load",
"entity": "product",
"action": "view",
"timestamp": 1700000102,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}amplitude.track("product view", {
"data_id": "ers",
"data_name": "Everyday Ruck Snack",
"data_color": "black",
"data_size": "l",
"data_price": 420
})Event options
Destination-level eventOptions map walker fields into Amplitude per-event metadata such as time and insert_id.
{
"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": "1700000110abcdef",
"trigger": "load",
"entity": "page",
"action": "view",
"timestamp": 1700000110,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}amplitude.track("page view", {}, {
"time": 1700000110,
"insert_id": "1700000110abcdef"
})Group assignment
A company update assigns the user to a group and sets group properties via setGroup plus groupIdentify.
{
"name": "company update",
"data": {
"company": "Acme",
"industry": "tech",
"employee_count": 50,
"founded_year": 2020
},
"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": "dd9eab8a6d1ada48",
"trigger": "test",
"entity": "company",
"action": "update",
"timestamp": 1700000109,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"group": {
"map": {
"type": {
"value": "company"
},
"name": "data.company"
}
},
"groupIdentify": {
"map": {
"type": {
"value": "company"
},
"name": "data.company",
"set": {
"map": {
"industry": "data.industry",
"size": "data.employee_count"
}
},
"setOnce": {
"map": {
"founded": "data.founded_year"
}
}
}
}
}
}amplitude.setGroup("company", "Acme");
amplitude.groupIdentify("company", "Acme", {
"set": {
"industry": "tech",
"size": 50
},
"setOnce": {
"founded": 2020
}
})Multi-product order
An order with multiple nested products fires one amplitude.revenue per product plus a single track for the order.
{
"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": "8200e58a6aae777e",
"trigger": "load",
"entity": "order",
"action": "complete",
"timestamp": 1700000108,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"include": [
"data",
"globals"
],
"settings": {
"revenue": {
"loop": [
"nested",
{
"condition": {
"$code": "e=>{const t=e;return\"number\"==typeof t?.data?.price}"
},
"map": {
"productId": "data.id",
"price": "data.price",
"quantity": {
"key": "data.quantity",
"value": 1
},
"revenueType": {
"value": "purchase"
},
"currency": {
"key": "data.currency",
"value": "EUR"
}
}
}
]
}
}
}amplitude.revenue({
"productId": "ers",
"price": 420,
"quantity": 1,
"revenueType": "purchase",
"currency": "EUR"
});
amplitude.revenue({
"productId": "cc",
"price": 42,
"quantity": 1,
"revenueType": "purchase",
"currency": "EUR"
});
amplitude.track("order complete", {
"data_id": "0rd3r1d",
"data_currency": "EUR",
"data_shipping": 5.22,
"data_taxes": 73.76,
"data_total": 555,
"globals_pagegroup": "shop"
})Subscription revenue
A subscription renewal fires a single amplitude.revenue call with productId, price, and a currency fallback.
{
"name": "subscription renew",
"data": {
"plan_id": "plan-pro",
"amount": 9.99
},
"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": "ac43e59e68035c13",
"trigger": "test",
"entity": "subscription",
"action": "renew",
"timestamp": 1700000107,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"revenue": {
"map": {
"productId": "data.plan_id",
"price": "data.amount",
"revenueType": {
"value": "renewal"
},
"currency": {
"key": "data.currency",
"value": "EUR"
}
}
}
}
}amplitude.revenue({
"productId": "plan-pro",
"price": 9.99,
"revenueType": "renewal",
"currency": "EUR"
})User login identify
A user login maps to amplitude.identify with set, setOnce, and add operations while the default track call is skipped.
{
"name": "user login",
"data": {
"user_id": "new-user-123",
"plan": "premium",
"company": "Acme",
"email": "user@acme.com"
},
"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": "68a7584eeec7c6ae",
"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": {
"user_id": "data.user_id",
"set": {
"map": {
"plan": "data.plan",
"company": "data.company",
"email": "data.email"
}
},
"setOnce": {
"map": {
"first_login": "timestamp"
}
},
"add": {
"map": {
"login_count": {
"value": 1
}
}
}
}
}
}
}amplitude.identify({
"set": {
"plan": "premium",
"company": "Acme",
"email": "user@acme.com"
},
"setOnce": {
"first_login": 1700000105
},
"add": {
"login_count": 1
}
}, {
"user_id": "new-user-123"
})