How attribution is computed
The math, step by step. Useful for analysts who want to reproduce numbers or reconcile against other tools.
This page is for the technically-minded reader who wants to understand exactly what FTS does to turn raw events into attributed revenue. If you just want to use Pulse and trust the numbers, How attribution works is the lighter read.
The pipeline
For every conversion (Shopify order linked to a visitor journey), attribution runs through these steps:
- Identify the visitor. Match the order's customer ID to the visitor cookie. If matched: proceed. If unmatched: order is recorded but flagged with no attributable journey.
- Pull the journey. Get every session for this visitor, ordered by session start time, ascending.
- Apply the lookback filter. Drop any session older than 30 days before the conversion timestamp.
- Apply the model. Distribute conversion revenue across the remaining sessions according to the active model.
- Aggregate by channel. For each session that received credit, increment the corresponding channel's revenue total by its credit amount.
That's the full pipeline. Five deterministic steps. The same inputs always produce the same outputs.
Step 1 — Identify the visitor
Two paths from order to visitor:
Path A: Pixel-driven (the common case). When the visitor reaches the thank-you page, our pixel fires a conversion event with both the order ID (read from the page) and the visitor cookie. The two are linked.
Path B: Webhook-only (the express-checkout case). Buy It Now / Shop Pay buyers never see the thank-you page. The order webhook arrives with a customer ID, and we look up whether that customer has any prior identification on a visitor cookie. If yes, we link to that visitor. If no, the order is unattributed (shows as direct).
See Why Buy It Now / Shop Pay shows as direct for the full v1.0 limitation.
Step 2 — Pull the journey
The journey is all sessions belonging to this visitor, sorted by session start time ascending. This includes:
- Sessions that converted in the past
- Sessions that bounced
- Sessions before identification (anonymous), if they were on the same cookie
- Sessions across multiple days
It does not include:
- Sessions on a different cookie (e.g. different browser, different device — unless merged via customer login)
- Sessions before our pixel was installed on your store
Step 3 — Apply the lookback filter
We compare each session's start time to the conversion timestamp:
keep_session = (conversion_time - session_start_time) <= 30 daysSessions older than 30 days are dropped from the journey for attribution purposes. They remain visible in the Visitor Journey UI (so you can see the full history) but are not credited.
This is a per-conversion lookback, not a per-visitor one. If a visitor has two conversions, each conversion's attribution is computed against its own 30-day window.
Step 4 — Apply the model
Three deterministic rules.
First-touch
credit[first_session] = order_revenue
credit[other_sessions] = 0The earliest session in the lookback-filtered journey gets 100% of the credit. All other sessions get zero.
Last-touch
credit[last_session] = order_revenue
credit[other_sessions] = 0The latest session before the conversion gets 100%. The "last" session is usually the converting session itself.
Linear
credit[each_session] = order_revenue / NWhere N is the number of sessions in the lookback-filtered journey. Equal split, no weighting.
Step 5 — Aggregate by channel
For each session that received credit, add its credit to the running total for that session's channel:
channel_revenue[meta_paid_social] += credit[session_1]
channel_revenue[email] += credit[session_2]
channel_revenue[direct] += credit[session_3]
...Repeat across every conversion in the active date range. The resulting per-channel totals are what populate the channel performance table in Pulse.
Worked example
A visitor with this journey converts at $120:
Day 1, 14:32 — Meta paid social (4 min, no order)
Day 3, 09:15 — Klaviyo email (1 min, no order)
Day 5, 21:08 — Direct → ORDER ($120)All three sessions are within the 30-day lookback (relative to day 5). The journey passes through unfiltered.
| Model | Meta paid social | Direct | |
|---|---|---|---|
| First-touch | $120 | $0 | $0 |
| Last-touch | $0 | $0 | $120 |
| Linear | $40 | $40 | $40 |
These numbers are exactly what Pulse will show under each model toggle for this conversion's contribution.
What changes when models switch
Nothing in the data. The journey, the sessions, the order, the channel classifications — all stay the same. Only the credit allocation changes. This is why Pulse can switch models with zero recalculation lag.
It also means you can sanity-check by adding up attributed revenue across all channels. Under all three models, the total should equal total conversion revenue (within rounding).
Edge cases
A few worth knowing:
- Single-session journey. All three models give 100% credit to the single session. First/last/linear produce identical results.
- Two sessions on the same channel. Linear splits evenly between the two; first/last credits one of them. Channel-level total is the same.
- Refunded order. When a refund webhook arrives, we reduce the original order's revenue by the refund amount. Attribution is recomputed using the (smaller) revenue figure. If fully refunded, attribution credit goes to zero across all sessions.
- Cancelled order. Excluded from attribution entirely (never enters the pipeline).
Where to go next
- Lookback windows — the 30-day default, in detail
- Channel taxonomy — how channels are classified
- Picking the right attribution model — decision-oriented