Playbook: Segment and Mixpanel Identity Resolution via Edge User ID
Version: 0.1
Last updated: 2026-04-27
Audience: LLM agents and humans implementing identity stitching between Edge-to-Activation, Segment, and Mixpanel.
Purpose
This playbook details how to resolve anonymous and known user identities across three systems: Edge (CDN/Edge layer), Segment (CDP/identity graph), and Mixpanel (product analytics). Specifically, it covers how to make Segment and Mixpanel recognize that an edge_user_id created at the Edge layer belongs to the same person who later logs in or registers, so that pre-login events (clicks, intake, purchases) and post-login traits (email, phone) are stitched into a single unified profile.
This exists because Edge-to-Activation recovers attribution signals that client-side pixels miss, but those signals are only valuable if they can be tied back to the real person in downstream tools.
When to use
Use this playbook when:
- Edge-to-Activation is already capturing traffic and you need to activate that data in Segment and Mixpanel
- A client’s Segment to Mixpanel pipeline shows broken identity stitching (e.g. anonymous events never merge into known profiles)
- You are wiring
edge_user_idinto websiteanalytics.identify()calls on login or registration - You need to reconcile Edge-derived events with Segment’s identity graph and Mixpanel’s user profiles
Do not use this playbook when:
- The client does not use Segment or Mixpanel (use the generic Edge-to-Activation Implementation Playbook instead)
- You are only doing a gap analysis or discrepancy report without fixing identity resolution (use the SOP: Edge-to-Activation Phase 0 instead)
- The identity stitching problem is purely within Mixpanel (no Segment in the path)
Service line / subservice
| Field | Value |
|---|---|
| Service line | Data Platform & Analytics → data-infrastructure |
| Primary subservice | Activation & Attribution → activation-attribution |
| Notes | This playbook is a Phase 1–2 add-on to the core Edge-to-Activation engagement. Requires Edge layer already deployed. |
Approval-before-execution pipeline
| Gate | When to stop for approval |
|---|---|
| 1. Segment destination audit | Before enabling any new or existing Mixpanel destinations in Segment. Verify there is exactly one active destination per Mixpanel project to avoid duplicate identify calls. |
| 2. Traits and PII mapping | Before sending email, phone, or other PII traits through Segment. Confirm with the client which traits are allowed and whether consent has been captured. |
| 3. Production identity sync | Before enabling Segment’s Profile Sync (Unify) or warehouse-to-Segment reverse ETL in production. Validate in Segment’s debugger that edge_user_id appears on events and that the identity graph resolves correctly. |
Scope
In scope
- Instrumenting
edge_user_idinto website interactions (clicks, intake, login/register, purchase, abandonment) - Sending
analytics.identify()withedge_user_id, email, and phone on login/register - Configuring Segment to bridge
edge_user_idwith Segmentanonymous_idanduser_id - Mapping Segment identity resolution to Mixpanel user profiles
- Validating that pre-login Edge events stitch to post-login known profiles in Mixpanel
- Troubleshooting duplicate profiles, disabled destinations, and staging table misrouting
Out of scope
- Deploying or configuring the Edge layer itself (see Edge-to-Activation Implementation Playbook)
- Configuring the warehouse schema or BigQuery/Snowflake ingestion (see SOP)
- Building custom Mixpanel reports or dashboards
- GDPR/consent platform configuration (see SOP Compliance Controls add-on)
Prerequisites
| Requirement | Notes |
|---|---|
| Edge layer deployed and streaming events to warehouse | Usually Cloudflare Workers → BigQuery/Snowflake |
edge_user_id available in browser context | Typically set as a first-party cookie or returned from an Edge session-start API |
| Segment source configured for the website | JavaScript source or GTM-managed source with analytics.js loaded |
| Mixpanel destination configured in Segment | At least one Mixpanel destination exists in the Segment workspace |
| Access to Segment workspace | Debugger, Sources, Destinations, and Unify/Profiles access |
| Access to Mixpanel project | User profiles, event stream, and identity merge tooling |
Inputs
| Input | Example | Notes |
|---|---|---|
edge_user_id | edge_abc123def456 | UUID or stable string created at Edge Session Start; persisted in cookie/localStorage |
segment_anonymous_id | anon_xyz789 | Auto-generated by analytics.js on first page load |
user_id | u_987654321 | Client’s internal user ID, created on login/registration |
transaction_id | txn_555444333 | Order/transaction identifier from Edge ‘thank you’ visit or backend |
| Customer traits | { email: "user@example.com", phone: "+1-555-0100", first_name: "Jane" } | Sent in analytics.identify() at login/register |
Workflow
Step 1 — Verify Edge ID collection and propagation
Confirm that edge_user_id is created at Edge Session Start and is accessible to the website JavaScript.
- Check the Edge Worker response sets a first-party cookie (e.g.
__edge_uid) or returnsedge_user_idin a JSON payload. - Confirm the website reads this cookie and makes it available to the tracking layer.
- Test: In browser dev tools, verify
document.cookiecontains__edge_uidon the first request.
Step 2 — Decorate website interactions with edge_user_id (inline approach)
Ensure every analytics.track() call on the website includes edge_user_id in the event properties.
- Add
edge_user_idas a super-property or include it explicitly on every track call:analytics.track('Button Clicked', { button_id: 'cta-pricing', edge_user_id: getEdgeUserId(), // from cookie or localStorage }); - Cover all event types: click events, intake events, login/register events, purchase events, abandonment events.
- Test: Use Segment Debugger to confirm
edge_user_idappears on every event payload.
Step 2a — Decorate website interactions via Google Tag Manager (GTM variant)
If the client manages Segment through GTM rather than inline analytics.js, push edge_user_id through the data layer and wire it into the Segment tag.
- On page load, push
edge_user_idto the data layer:window.dataLayer = window.dataLayer || []; window.dataLayer.push({ edge_user_id: getEdgeUserId(), event: 'edge_id_ready' }); - In GTM, create a Data Layer Variable named
dlv - edge_user_idthat readsedge_user_idfrom the data layer. - In the Segment tag configuration, add a custom field or event parameter that maps
dlv - edge_user_idto theedge_user_idproperty on every track call. - For identify calls, map the same variable into the traits object.
- Test: Use GTM Preview mode to confirm the variable populates, then check Segment Debugger for the property.
Step 3 — Configure Segment identity resolution
Tell Segment how to treat edge_user_id as an identifier.
- In Segment, go to Unify → Identity Resolution (or legacy Profiles settings).
- Add
edge_user_idas an external ID type if it is not already present. - Ensure the identity priority order makes sense for the client. Typical order:
user_id(most authoritative)edge_user_id(stable cross-session)anonymous_id(least authoritative, session-scoped)
- Caution: Do not treat
edge_user_idas equivalent todevice_idunless you have confirmed with the client that the Edge cookie is device-scoped. In many Edge deployments,edge_user_idis a stable browser cookie, so it behaves like a device identifier.
Step 4 — Send analytics.identify() on login and registration
This is the critical stitching moment. When the user logs in or registers, send an identify call that links the anonymous edge_user_id to the known user.
- On successful login or registration:
analytics.identify(userId, { email: user.email, phone: user.phone, first_name: user.firstName, last_name: user.lastName, edge_user_id: getEdgeUserId(), // propagate the same Edge ID }); - If the client uses a custom login flow (e.g. OAuth redirect), ensure the identify call fires after the session is established and the
edge_user_idcookie is still readable. - Include
edge_user_idin the identify traits so Segment can bridge it explicitly. Segment will merge the anonymous profile (with pre-login events) into the known profile.
Step 5 — Map Edge ‘thank you’ and transaction events
Edge captures conversions (e.g. ‘thank you’ page visits) that may not fire client-side pixels due to ad blockers. Ensure these reach Segment.
- Option A (recommended): Stream Edge events from the warehouse to Segment via a warehouse source or reverse ETL. Include
edge_user_idandtransaction_idin the mapped payload. - Option B: If the website’s purchase confirmation page is reachable, fire a client-side
analytics.track('Order Completed', { ... })with the sametransaction_idandedge_user_id. - Whichever option you choose, the
transaction_idmust match between Edge and Segment so that downstream attribution models do not double-count.
Step 6 — Configure Mixpanel destination in Segment
Route the unified profiles to Mixpanel with correct ID mapping.
- In Segment, open the Mixpanel destination settings.
- Under Identify, ensure:
- “Use user_id” is enabled (or the client’s chosen ID)
- “Map Segment anonymous_id to Mixpanel device_id” is enabled if you want pre-login events to appear as anonymous in Mixpanel
- “Send identify events” is enabled
- Under Group User Profile by, select the primary identifier that matches the client’s data model (typically
user_id). - Critical: Verify there is only one active Mixpanel destination per Mixpanel project. Multiple destinations with identify calls enabled will create duplicate profiles and event streams. If you find multiple destinations, disable or consolidate them.
Step 7 — Validate identity stitching end-to-end
Use a test user to walk through the full journey and confirm stitching.
- Open an incognito browser. Clear cookies.
- Visit the site. Confirm Edge sets
edge_user_id. - Trigger a few tracked events (click, scroll). Confirm they appear in Segment Debugger with
anonymous_idandedge_user_id. - Log in or register. Confirm
analytics.identify()fires withuser_id, email, phone, andedge_user_id. - In Segment’s Profile Explorer (or Unify), verify the anonymous profile now links to the known profile.
- In Mixpanel, verify:
- The user profile shows pre-login events
- The profile contains email, phone, and
edge_user_idtraits - There are not two profiles for the same person
Visual reference — Segment Debugger:
The debugger shows a live event stream in a chronological list. Clicking any event expands a JSON payload panel on the right. Look for properties.edge_user_id and context.traits.edge_user_id in the expanded JSON. A green checkmark next to the event means Segment received it; a red X means it was rejected by a destination or filter.
Visual reference — Event Delivery tab: Open the Mixpanel destination and click the Event Delivery tab. A bar chart appears at the top showing successful vs. dropped events over the selected time range. Below the chart, a Mapping Errors panel lists specific field-level failures (for example, “user_id: invalid format” or “traits.phone: type mismatch”). Green bars = events delivered; red bars = events dropped. Hover over a red bar to see the error count and category.
Step 8 — Reconcile and monitor
Set up ongoing checks to catch identity drift.
- Weekly check: In Mixpanel, query for profiles where
edge_user_idexists butemaildoes not. These are anonymous users who have not yet converted. A sudden spike means the identify call is failing. - Weekly check: In Segment, check the Event Delivery tab for the Mixpanel destination. Look for dropped
identifyevents or mapping errors. - Monthly check: Compare Edge transaction volume in the warehouse against Mixpanel
Order Completedevents bytransaction_id. Flag discrepancies >5%. - Escalation: If identity merge fails for a specific user segment (e.g. OAuth users, mobile app users), open a Linear blocker ticket and tag the engagement lead.
Failure modes / gotchas
- Duplicate Mixpanel destinations in Segment. Multiple destinations receiving from different sources with identify calls enabled will fork profiles and inflate event counts. Audit destinations before enabling anything.
- Segment Profile Sync to the wrong warehouse table. If Segment’s Unify/Profile Sync is configured to sync to a staging table rather than the production table that feeds Mixpanel, profiles will look correct in Segment but never reach Mixpanel. Verify the connection table name in Segment → Destinations → Mixpanel → Connection.
- Disabled Segment to Mixpanel sync. In the Segment destination settings, the toggle or specific event filters may be off. Check the Event Delivery tab and confirm “Enabled” is active. Historical gaps cannot be backfilled automatically.
edge_user_idcookie lost on login. If the login flow redirects across domains or clears cookies, theedge_user_idmay not be available for the identify call. Ensure the cookie isSameSite=None; Secureif cross-domain, or read it before the redirect and pass it through.- Phone number formatting. If phone is sent as a trait, standardize format (E.164) before sending to Segment, or Mixpanel may treat
+1-555-0100and5550100as different values. - Segment
anonymous_idregeneration. Ifanalytics.jsis re-initialized or cookies are cleared, a newanonymous_idis created. Theedge_user_idis the stable bridge that allows Segment to merge these sessions anyway, but only ifedge_user_idis configured as an external ID in Segment. - GTM data layer race condition. If the Segment tag fires before the
edge_id_readyevent pushes todataLayer, theedge_user_idvariable will be undefined. Use a trigger that waits for theedge_id_readyevent before firing the Segment tag. - Mixpanel
device_idconfusion. Mixpanel usesdevice_idfor anonymous users. If Segment mapsanonymous_idtodevice_idand the client also sends a native mobile appdevice_id, Mixpanel may merge unrelated users. Confirm ID sources before enabling the mapping.
Example implementation
Below is a condensed client-agnostic implementation pattern. Client-specific code belongs in the client repo.
Edge Session Start (Cloudflare Worker snippet)
// In the Edge Worker, on first visit
const edgeUserId = crypto.randomUUID();
// Set first-party cookie
response.headers.append('Set-Cookie', `__edge_uid=${edgeUserId}; Path=/; Max-Age=31536000; SameSite=Lax`);
// Stream to warehouse
await streamToWarehouse({ edge_user_id: edgeUserId, session_id: crypto.randomUUID(), timestamp: Date.now() });Website tracking layer (inline)
function getEdgeUserId() {
// Read from cookie set by Edge Worker
const match = document.cookie.match(/__edge_uid=([^;]+)/);
return match ? match[1] : null;
}
// On every track call
analytics.track('Intake Form Submitted', {
form_id: 'contact-us',
edge_user_id: getEdgeUserId(),
});
// On login success
analytics.identify(user.id, {
email: user.email,
phone: user.phone, // E.164 recommended
first_name: user.firstName,
last_name: user.lastName,
edge_user_id: getEdgeUserId(),
});Website tracking layer (GTM variant)
// Push edge_user_id to data layer on page load
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
edge_user_id: getEdgeUserId(),
event: 'edge_id_ready'
});
// GTM Configuration Summary:
// 1. Variable: Data Layer Variable "dlv - edge_user_id" → Data Layer Key: edge_user_id
// 2. Trigger: Custom Event "edge_id_ready"
// 3. Tag: Segment - Track Event → Map "dlv - edge_user_id" into event properties
// 4. Tag: Segment - Identify → Map "dlv - edge_user_id" into traits on login/registerSegment destination audit checklist
- [ ] Exactly one Mixpanel destination per Mixpanel project
- [ ] Identify calls enabled and not filtered out
- [ ] `user_id` mapped correctly in destination settings
- [ ] Event Delivery tab shows green for the last 7 days
- [ ] No staging or non-production source accidentally connected to production MixpanelRelated
- Edge-to-Activation Implementation Playbook — Core technical deployment and testing phases
- SOP: Edge-to-Activation — Delivery phases, governance, and SOW copy
- Implementation plan (offering) — Week-by-week timeline
- Linear template (offering) — Ticket scaffolding
- PLAYBOOK_INDEX.md — Registry of all playbooks
- Transcript reference:
knowledge/clients/unassigned/transcripts/2026-04-21_chat_segment-mixpanel_id_stitching_a208fa45.md— Real-world debugging of disabled Segment to Mixpanel syncs and staging table misrouting
Changelog
| Date | Change | Author |
|---|---|---|
| 2026-04-27 | Initial draft | OpenCode |