Skip to content

Cross-device attribution

What Retidal's identity resolution actually guarantees — and what it doesn't — across sessions, visitors, and devices.

Retidal attributes an event to an ad click by resolving through three IDs — visitorId, sessionId, userId — in a fixed priority order. This page is about being precise on what that resolution does and does not promise. Getting this wrong in either direction creates real support load: under-promising means customers don’t trust the numbers; over-promising means they escalate when a conversion doesn’t get credited the way marketing expected.

ID Scope Lifetime Who generates it
visitorId Device / browser Permanent for that device, until storage is cleared You — persist it in localStorage or a long-lived cookie
sessionId A single visit Session-scoped — gone when the session ends You — a fresh session cookie with no max-age
userId Your logged-in user Exists once the user has logged in Your own auth system

When an event arrives, Retidal looks for an attribution source in this order:

Priority Tier Condition What happens
Highest Tier 0 — Explicit The event itself carries a Click ID, shortLinkId, or UTM params Used directly, no lookup needed.
High Tier 1 — Session The event’s sessionId matches an existing attribution record The event inherits whatever ad click first attributed that session.
Medium Tier 2 — Visitor The event’s visitorId has an attribution record from the last 24 hours Fuzzy cross-session match on the same device.
Low Tier 3 — UTM only Only UTM parameters are present, no Click ID Recorded, but there’s nothing to callback to an ad platform with.

sessionId is what makes Tier 1 possible: every event in the same session automatically inherits the ad attribution from that session’s first hit. Omit sessionId and you fall back to Tier 2 — a 24-hour fuzzy visitorId match, which is both lower priority and less accurate.

Calling POST /api/v1/identify links a visitorId to a userId and, as a side effect, backfills that userId onto every prior event and visit for that same visitorId. This is how a user who clicked an ad before logging in still gets correctly attributed once they log in — their pre-login activity on that device gets stamped with their userId retroactively.

No cross-device stitching beyond a shared userId

Identity resolution joins activity by userId, sessionId, and visitorId — nothing in the sources for this integration describes probabilistic or fingerprint-based device linking (matching by IP, device model, or similar signals shared across two different visitorIds). If the same person clicks an ad on their phone and converts on their desktop, Retidal only connects those two events if both devices eventually call identify with the same userId. Until that happens, they are two independent visitors with two independent attribution histories — there is no automatic bridge.

Concretely:

  • A visitor who clicks an ad on Device A, never logs in there, then converts on Device B after logging in: the conversion on Device B is attributed to whatever ad clicked on Device B (or nothing, if there wasn’t one) — the Device A click is not connected, because Device A was never identified.
  • A visitor who clicks an ad on Device A, logs in on Device A, then converts on Device B while logged in as the same user: both devices now share the same userId, so both histories exist under that userId, but the attribution record itself (the click → session/visitor link) still lives per-device — Retidal doesn’t retroactively promote Device A’s ad click to be “the” cause of a Device B conversion unless your reporting explicitly reasons over the shared userId’s full event history.
  • visitorId fuzzy matching (Tier 2) is scoped to 24 hours and to a single visitorId — it is not a cross-visitor or cross-device mechanism at all.

Set expectations accordingly: cross-device reporting (seeing all of one user’s activity once they’re identified everywhere) works well because everything is keyed on userId. Cross-device ad-click attribution (crediting a specific platform click for a conversion that happened on a different device) only works to the extent your users identify themselves promptly on every device they use.

Understanding attribution priority unlocks correctly explaining to stakeholders why a conversion was (or wasn’t) credited to a specific ad click, and correctly setting expectations for Ad platforms reporting, which depends entirely on a click having won attribution priority in the first place.

  1. Enable Debug view

    Console → Projects → Debug, or, from a browser session already logged into the console (so the trackly_session cookie is sent automatically):

    bash
    curl -s -X POST https://retidal.com/api/projects/{projectId}/debug-mode \
    -H "Cookie: trackly_session=$SESSION_COOKIE" -H "Content-Type: application/json" \
    -d '{"action":"enable"}'
    # expect: 200 — debug mode now captures incoming events for 30 minutes

    This is a Management API call — host https://retidal.com, session-cookie authenticated (see Debug view).

  2. Send an event with predictable attribution inputs

    Send a test event via Sending events carrying the sessionId/visitorId (or Click ID) combination you expect to win a specific tier, tagged _debug: 1 for instant capture.

  3. Check the attribution tier in Debug view

    bash
    curl -s "https://retidal.com/api/projects/{projectId}/debug-events?limit=1" \
    -H "Cookie: trackly_session=$SESSION_COOKIE"
    # expect: 200 with the captured event's attributionTier matching what you'd
    # predict from the priority order above (Tier 0 explicit > Tier 1 session >
    # Tier 2 visitor > Tier 3 UTM-only)

    Console → Projects → Debug shows the same attributionTier for the event — the per-visitor conversion detail page (Console → Projects → Visitors) shows postback status and platform, but not the attribution tier itself.

If the wrong tier (or the wrong click within a tier) appears to have won, work through Attribution looks wrong.