Docs
    GuidesAPI ReferenceBlog
    Sign inCreate account
    Overview

    Getting started

    Sign upAPI keysQuickstartLoad your catalog

    Integration

    Tracking EventsIdentity StitchingPersonalisation

    Production

    Errors & status codesRetries & rate limitsTypeScript SDKTroubleshooting

    Reference

    API ReferenceVersioningChangelog
    HomeDocumentationIdentity Stitching
    Previous
    Tracking Events
    Next
    Personalisation

    Skip the ML, Ship the Revenue

    Product

    • How It Works
    • Features
    • For Startups
    • For Developers

    Developers

    • Documentation

    Company

    • Blog
    • Contact

    © 2026 Lehnz, Inc. All rights reserved.

    Integration

    Identity Stitching

    Lehnz tracks events under a single user_id per shopper. When that shopper is anonymous, you assign them a stable random ID and use it consistently. When they sign in, you reconcile the anonymous identity with their real one by sending a single identify event. This page is the canonical contract — any deviation will silently drop attribution.

    The four-step contract

    1

    On first visit, mint an anonymous user ID

    Generate a UUID v4 in the browser, persist it to localStorage, and use it as user_id on every event you send while the shopper is anonymous.

    identity.js
    let userId = localStorage.getItem('lehnz_user_id');
    if (!userId) {
    userId = crypto.randomUUID();
    localStorage.setItem('lehnz_user_id', userId);
    }

    Lehnz never mints this ID for you. Owning it on the client guarantees stability across page loads, tabs, and reconnects.

    2

    On login or signup, send exactly one identify event

    The moment authentication completes, fire one event that links the anonymous ID to the real one.

    terminal
    curl -X POST https://ingestion.lehnz.com/api/v1/events/ingest \
    -H "X-API-KEY: lehnz_pk_..." \
    -H "X-Domain: commerce" \
    -H "Content-Type: application/json" \
    -d '{
    "event_family": "system",
    "event_name": "identify",
    "user_id": "<real_user_id>",
    "previous_user_id": "<anon_uuid>"
    }'

    event_family: "system" is required. previous_user_id is required for identify events specifically.

    Then update localStorage and continue tracking under the real ID:

    onSignIn.js
    localStorage.setItem('lehnz_user_id', realUserId);
    3

    On logout, mint a fresh anonymous ID

    onSignOut.js
    const newAnon = crypto.randomUUID();
    localStorage.setItem('lehnz_user_id', newAnon);

    The new anonymous session is unrelated to the previous user. Don't reuse the old anonymous ID — that would commingle two sessions.

    4

    On account merge (rare), send identify with the deprecated real ID

    If the same person signs in with a second account that you then merge into a primary, send another identify event:

    merge.json
    {
    "event_family": "system",
    "event_name": "identify",
    "user_id": "<primary_user_id>",
    "previous_user_id": "<deprecated_user_id>"
    }

    What happens server-side

    When an identify event lands, lehnz-backend writes a Redis hash entry: alias:{tenantId} {previous_user_id} -> {user_id}. The downstream consumer resolves aliases at read time in O(1). Past events are never rewritten — the alias map is the join table.

    If multiple identify events form a chain (anon_a → real_x, then real_x → real_y), resolution walks the chain.

    Common mistakes

    Don't fire identify repeatedly on every page after login

    Once is enough. The alias is durable.

    Don't omit event_family: "system" on identify events

    They will return 400 Bad Request.

    Don't reuse a real user_id as the next anonymous ID after logout

    Generate a fresh UUID.

    What's next

    Tracking Events

    All event types, batching, attribution, and code examples.

    Recommendations

    Fetch personalized and item-based recommendations.