Mixpanel
Mixpanel is a product analytics platform with people
profiles, group analytics, and cohort-based reporting. This destination forwards
walkerOS events to Mixpanel via the official
mixpanel-browser SDK,
translating events into mixpanel.track(...) calls and resolving identity,
people properties, group assignments, and consent opt-in/opt-out.
Mixpanel is a web destination in the walkerOS flow:
Installation
npm install @walkeros/web-destination-mixpanel- Integrated
- Bundled
import { startFlow } from '@walkeros/collector';
import { destinationMixpanel } from '@walkeros/web-destination-mixpanel';
await startFlow({
destinations: {
mixpanel: {
code: destinationMixpanel,
config: {
settings: {
apiKey: 'YOUR_PROJECT_TOKEN',
api_host: 'https://api-eu.mixpanel.com',
},
},
},
},
});Add to your flow.json destinations:
"destinations": {
"mixpanel": {
"package": "@walkeros/web-destination-mixpanel",
"config": {
"settings": {
"apiKey": "YOUR_PROJECT_TOKEN",
"api_host": "https://api-eu.mixpanel.com"
}
}
}
}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 Mixpanel project token. Find it in your Mixpanel project settings under "Project Settings" and "Access Keys". Passed to mixpanel.init() as the first argument (like a1b2c3d4e5f6789012345678abcdef12). | |
api_host | string | Mixpanel ingestion host. Default: https://api-js.mixpanel.com. Use https://api-eu.mixpanel.com for EU residency. | |
persistence | 'cookie' | 'localStorage' | Client-side persistence backend. Default: cookie. | |
cross_subdomain_cookie | boolean | Share cookie across subdomains. Default: true. | |
cookie_expiration | integer | Cookie expiration in days. Default: 365. | |
secure_cookie | boolean | Only send cookie over HTTPS. Default: false. | |
ip | boolean | Enable server-side IP geolocation. Default: true. | |
batch_requests | boolean | Use the /batch endpoint instead of individual requests. Default: true. | |
batch_size | integer | Max events per batch. Default: 50. | |
batch_flush_interval_ms | integer | Batch flush interval in ms. Default: 5000. | |
debug | boolean | Enable verbose SDK logging. Default: false. | |
opt_out_tracking_by_default | boolean | Start in opted-out state until opt_in_tracking() is called. Default: false. | |
track_pageview | boolean | string | Enable Mixpanel auto-pageview tracking. walkerOS default: false — walkerOS sources handle page views. | |
autocapture | any | Enable Mixpanel web autocapture. walkerOS default: false — walkerOS sources handle event capture. | |
record_sessions_percent | number | Session replay sampling rate (0-100). Default: 0 (disabled). Session replay is bundled in the npm build. | |
record_mask_all_inputs | boolean | Mask all input values in session replay. Default: true. | |
identify | any | walkerOS mapping value resolving to an identity object. Keys: distinctId. | |
group | any | walkerOS mapping value resolving to { key, id } → mixpanel.set_group(key, id). Runs on destination init or per-event. |
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 { distinctId } → mixpanel.identify(distinctId). | |
people | any | Per-event people operations. Resolves to an object with any of: set, set_once, increment, append, union, remove, unset, delete_user. Each key fires a separate mixpanel.people.* call. | |
group | any | Per-event group assignment. Resolves to { key, id } → mixpanel.set_group(key, id). | |
groupProfile | any | Per-event group profile operations. Resolves to { key, id, set?, set_once?, unset?, union?, remove?, delete? } → mixpanel.get_group(key, id).set/... calls. | |
reset | any | Logout trigger. Resolves to a truthy value → mixpanel.reset(). Typically used with silent: true on a user logout rule. |
Examples
Delete user
An account delete fires Mixpanel people.delete_user to remove the user profile from the project.
{
"name": "account delete",
"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": "14bad20e37252b25",
"trigger": "test",
"entity": "account",
"action": "delete",
"timestamp": 1700000107,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"people": {
"map": {
"delete_user": {
"value": true
}
}
}
}
}mixpanel.people.delete_user()Group profile
A company update sets Mixpanel group profile properties via get_group.set and get_group.set_once.
{
"name": "company update",
"data": {
"company_id": "acme-inc",
"company_name": "Acme, Inc.",
"plan": "enterprise",
"employee_count": 250,
"founded_year": 2010
},
"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": "6a8106b29a6d22c1",
"trigger": "test",
"entity": "company",
"action": "update",
"timestamp": 1700000110,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"groupProfile": {
"map": {
"key": {
"value": "company_id"
},
"id": "data.company_id",
"set": {
"map": {
"name": "data.company_name",
"plan": "data.plan",
"employee_count": "data.employee_count"
}
},
"set_once": {
"map": {
"founded": "data.founded_year"
}
}
}
}
}
}mixpanel.get_group.set("company_id", "acme-inc", {
"name": "Acme, Inc.",
"plan": "enterprise",
"employee_count": 250
});
mixpanel.get_group.set_once("company_id", "acme-inc", {
"founded": 2010
})Consent granted
A walker consent command with analytics granted calls mixpanel.opt_in_tracking to resume event capture.
{
"analytics": true
}mixpanel.opt_in_tracking()Consent revoked
A walker consent command with analytics denied calls mixpanel.opt_out_tracking to stop event capture.
{
"analytics": false
}mixpanel.opt_in_tracking();
mixpanel.opt_out_tracking()Default track
A walker event becomes a Mixpanel 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": "1f7cb3875d3f6233",
"trigger": "load",
"entity": "product",
"action": "view",
"timestamp": 1700000100,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}mixpanel.track("product view", {})Destination identify
Destination-level identify calls mixpanel.identify with a resolved distinctId before firing 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": "adb1c39fd4d27754",
"trigger": "load",
"entity": "page",
"action": "view",
"timestamp": 1700000104,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}mixpanel.identify("us3r");
mixpanel.track("page view", {})Include data
Destination-level include flattens the event data section into prefixed Mixpanel 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": "4d7bd5a178ca1109",
"trigger": "load",
"entity": "product",
"action": "view",
"timestamp": 1700000102,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}mixpanel.track("product view", {
"data_id": "ers",
"data_name": "Everyday Ruck Snack",
"data_color": "black",
"data_size": "l",
"data_price": 420
})All people operations
A profile update exercises the full Mixpanel people vocabulary including set, increment, append, union, and remove.
{
"name": "profile update",
"data": {
"name": "Jane Doe",
"email": "jane@acme.com",
"page": "/docs/getting-started",
"removed_tag": "trial",
"source": "referral"
},
"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": "88e593bca048ca75",
"trigger": "test",
"entity": "profile",
"action": "update",
"timestamp": 1700000106,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"people": {
"map": {
"set": {
"map": {
"name": "data.name",
"email": "data.email"
}
},
"set_once": {
"map": {
"signup_source": "data.source"
}
},
"increment": {
"map": {
"page_views": {
"value": 1
}
}
},
"append": {
"map": {
"visited_pages": "data.page"
}
},
"union": {
"map": {
"unique_tags": {
"value": [
"active"
]
}
}
},
"remove": {
"map": {
"tags": "data.removed_tag"
}
},
"unset": {
"value": [
"old_plan"
]
}
}
}
}
}mixpanel.people.set({
"name": "Jane Doe",
"email": "jane@acme.com"
});
mixpanel.people.set_once({
"signup_source": "referral"
});
mixpanel.people.increment({
"page_views": 1
});
mixpanel.people.append({
"visited_pages": "/docs/getting-started"
});
mixpanel.people.union({
"unique_tags": [
"active"
]
});
mixpanel.people.remove({
"tags": "trial"
});
mixpanel.people.unset([
"old_plan"
])Rule include overrides
A per-rule include replaces the destination-level include for this event, forwarding only globals here.
{
"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": "56c0111aba4cd068",
"trigger": "load",
"entity": "order",
"action": "complete",
"timestamp": 1700000103,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"include": [
"globals"
]
}mixpanel.track("order complete", {
"globals_pagegroup": "shop"
})Group association
A user login associates the user to a company group via mixpanel.set_group and fires the default track.
{
"name": "user login",
"data": {
"user_id": "user-456",
"company_id": "acme-inc"
},
"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": "4b63f371c3d150ae",
"trigger": "test",
"entity": "user",
"action": "login",
"timestamp": 1700000109,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"settings": {
"group": {
"map": {
"key": {
"value": "company_id"
},
"id": "data.company_id"
}
}
}
}mixpanel.set_group("company_id", "acme-inc");
mixpanel.track("user login", {})User login identify
A user login identifies the user and fires Mixpanel people set, set_once, and increment operations.
{
"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": "84319763e6b971fe",
"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": {
"distinctId": "data.user_id"
}
},
"people": {
"map": {
"set": {
"map": {
"plan": "data.plan",
"company": "data.company",
"email": "data.email"
}
},
"set_once": {
"map": {
"first_login": "timestamp"
}
},
"increment": {
"map": {
"login_count": {
"value": 1
}
}
}
}
}
}
}mixpanel.identify("new-user-123");
mixpanel.people.set({
"plan": "premium",
"company": "Acme",
"email": "user@acme.com"
});
mixpanel.people.set_once({
"first_login": 1700000105
});
mixpanel.people.increment({
"login_count": 1
})User logout reset
A user logout calls mixpanel.reset to clear persistence and generate a new anonymous distinct 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": "32fe32c38937879e",
"trigger": "test",
"entity": "user",
"action": "logout",
"timestamp": 1700000108,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"reset": true
}
}mixpanel.reset()Intentionally not supported
Mixpanel features that are deferred or not in scope for v1:
alias(): anonymous-to-identified merging is handled by walkerOS identity (the source resolves the user before pushing).register()/ super properties: use destination-levelsettings.includeto attach properties on every event instead. Mixpanel's super-property pattern overlaps with walkerOS's mapping model.people.track_charge: deprecated by Mixpanel since v2.78. Send revenue events as regulartrack()calls with arevenueproperty.time_event/ page view auto-tracking: walkerOS sources handle event capture and timing.
All other built-in mixpanel-browser config options pass through settings
directly (e.g. api_host, persistence, cross_subdomain_cookie,
secure_cookie, ip, property_blacklist, loaded callback, etc.).