Skip to main content

Mixpanel

Web Source code Package

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.

Where this fits

Mixpanel is a web destination in the walkerOS flow:

Installation

npm install @walkeros/web-destination-mixpanel
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',
      },
    },
  },
},
});

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

PropertyTypeDescriptionMore
apiKey*stringYour 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_hoststringMixpanel 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_cookiebooleanShare cookie across subdomains. Default: true.
cookie_expirationintegerCookie expiration in days. Default: 365.
secure_cookiebooleanOnly send cookie over HTTPS. Default: false.
ipbooleanEnable server-side IP geolocation. Default: true.
batch_requestsbooleanUse the /batch endpoint instead of individual requests. Default: true.
batch_sizeintegerMax events per batch. Default: 50.
batch_flush_interval_msintegerBatch flush interval in ms. Default: 5000.
debugbooleanEnable verbose SDK logging. Default: false.
opt_out_tracking_by_defaultbooleanStart in opted-out state until opt_in_tracking() is called. Default: false.
track_pageviewboolean | stringEnable Mixpanel auto-pageview tracking. walkerOS default: false — walkerOS sources handle page views.
autocaptureanyEnable Mixpanel web autocapture. walkerOS default: false — walkerOS sources handle event capture.
record_sessions_percentnumberSession replay sampling rate (0-100). Default: 0 (disabled). Session replay is bundled in the npm build.
record_mask_all_inputsbooleanMask all input values in session replay. Default: true.
identifyanywalkerOS mapping value resolving to an identity object. Keys: distinctId.
groupanywalkerOS mapping value resolving to { key, id } → mixpanel.set_group(key, id). Runs on destination init or per-event.
* Required fields

Mapping

Per-event rules under config.mapping. For the standard rule fields (consent, condition, data, batch, name, policy) see mapping.

PropertyTypeDescriptionMore
identifyanyPer-event identity mapping. Resolves to { distinctId } → mixpanel.identify(distinctId).
peopleanyPer-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.
groupanyPer-event group assignment. Resolves to { key, id } → mixpanel.set_group(key, id).
groupProfileanyPer-event group profile operations. Resolves to { key, id, set?, set_once?, unset?, union?, remove?, delete? } → mixpanel.get_group(key, id).set/... calls.
resetanyLogout 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.

Event
{
  "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"
  }
}
Mapping
{
  "silent": true,
  "settings": {
    "people": {
      "map": {
        "delete_user": {
          "value": true
        }
      }
    }
  }
}
Out
mixpanel.people.delete_user()

Group profile

A company update sets Mixpanel group profile properties via get_group.set and get_group.set_once.

Event
{
  "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"
  }
}
Mapping
{
  "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"
          }
        }
      }
    }
  }
}
Out
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.

Event
{
  "analytics": true
}
Out
mixpanel.opt_in_tracking()

Consent revoked

A walker consent command with analytics denied calls mixpanel.opt_out_tracking to stop event capture.

Event
{
  "analytics": false
}
Out
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.

Event
{
  "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"
  }
}
Out
mixpanel.track("product view", {})

Destination identify

Destination-level identify calls mixpanel.identify with a resolved distinctId before firing the default track.

Event
{
  "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"
  }
}
Out
mixpanel.identify("us3r");

mixpanel.track("page view", {})

Include data

Destination-level include flattens the event data section into prefixed Mixpanel track properties.

Event
{
  "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"
  }
}
Out
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.

Event
{
  "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"
  }
}
Mapping
{
  "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"
          ]
        }
      }
    }
  }
}
Out
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.

Event
{
  "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"
  }
}
Mapping
{
  "include": [
    "globals"
  ]
}
Out
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.

Event
{
  "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"
  }
}
Mapping
{
  "settings": {
    "group": {
      "map": {
        "key": {
          "value": "company_id"
        },
        "id": "data.company_id"
      }
    }
  }
}
Out
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.

Event
{
  "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"
  }
}
Mapping
{
  "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
            }
          }
        }
      }
    }
  }
}
Out
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.

Event
{
  "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"
  }
}
Mapping
{
  "silent": true,
  "settings": {
    "reset": true
  }
}
Out
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-level settings.include to 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 regular track() calls with a revenue property.
  • 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.).

💡 Need implementation support?
elbwalker offers hands-on support: setup review, measurement planning, destination mapping, and live troubleshooting. Book a 2-hour session (€399)