Skip to content

Features

Attribution at every stage of the funnel

Ad platforms report the conversion they touched last. Attruly measures every channel, campaign, ad group, keyword, landing page, country, device and OS version against every milestone you define — signed up, activated, added a card, subscribed.

Funnel-stage attribution

Every milestone, measured against every segment

Put your goals in order once and every channel, campaign, device model and OS version is measured against all of them at the same time. The ranking changes as you move down the stages, and that change is the whole report.

Illustrative example — not real customer data
ChannelSigned upActivatedAdded paymentSubscribedRevenue
Paid Social4189623.0%122.9%30.7%$1,497
Paid Search30117257.1%8829.2%4113.6%$20.5K
Organic Search22415870.5%9743.3%6227.7%$30.9K
Email14812181.8%8456.8%5839.2%$28.9K
AI Assistants634469.8%2742.9%1625.4%$7,980
Direct19011862.1%6132.1%3417.9%$17K

Paid Social brings 418 signups here, more than any other channel. Ninety-six activate, twelve add a payment method, three subscribe. Email brings 148 signups and ends with 58 subscriptions.

Ranked on signups, Paid Social leads the account by almost three to one. Ranked on subscriptions it finishes last, and the platform optimising it has no way to say so.

Progression funnel

Every stage in order, with the people lost at each step and the share of the previous stage that carried through.

Stage matrix

One row per segment, one column per stage. Each cell carries a count and that segment’s own entry-to-stage rate, tinted against the cohort’s rate at the same stage — good at a signup step and good at a checkout step are orders of magnitude apart.

Highest and lowest yield

The segments beating or missing the cohort’s own rate at the stages that pay, ranked by how much traffic the gap covers. Missing the average by twelve points on nine hundred people outranks missing it by forty on eleven.

Best performer at each stage

The top segment for every milestone with its share of everyone who reached it, and the runner-up behind it.

Tracking health

Unexpanded {campaign} placeholders, one value spelled two ways, a utm_source with no utm_medium, and the share of entrants carrying no campaign data at all — counted in people affected.

How the cohort is counted

The rules, written where you can check them

A funnel report is worth acting on only if you know what it counted. These are the rules Attruly applies, and the screen repeats them next to the numbers they produced.

Entry is the first time, ever

A person enters the funnel the first time they ever convert on step one, and they belong to the period that entry falls in. Converting on step one again next month does not move them.

Later stages are counted as of today

A cohort from this week has had less time to reach the bottom than one from three months ago, so a recent window always reads less converted. The report says that under the chart rather than letting anyone mistake a young cohort for a bad one.

Stages are ordered, not nested

Someone can reach stage four without ever matching stage three. That shows up as a gain on the stage, with the count named, because a drop-off of minus eighteen rendered as a drop-off is a lie.

Under 10 people it says nothing

A segment with fewer than 10 entrants is never called good or bad. A rate built on four signups is not a finding, and one lucky conversion in a segment of two should not arrive at the top of the page as the best thing in the account.

The window is yours

Leave a funnel open when the journey legitimately runs for months, or give it a fixed window when the question is whether somebody finished checkout — a purchase six weeks later is a different visit and a different intent.

First touch or last

The entry can be credited to the touch that started the person or the one that closed them, and the whole report recomputes either way.

Dimensions

Sixteen ways to cut the same funnel

Switch the breakdown and the same cohort is regrouped against the same milestones. Start at channel to see the shape, then go down to the ad group, the keyword, the device model or the OS version — the level an ad platform lets you act on.

Android 10 signs up 187 people this month, more than any other OS version in the account. Four of them reach the payment step. None subscribe.

That is an exclusion you can paste into Google Ads this afternoon. Grouped by channel, those 187 people disappear into a row that looks healthy. Counted only at the last step, they never appear at all.

Acquisition

  • Channel
  • Source
  • Medium
  • Source / Medium
  • Campaign
  • Ad group / Content
  • Keyword / Term
  • Referrer

Content

  • Landing page

Audience

  • Country
  • Region
  • City

Technology

  • Device type
  • Device model
  • Operating system
  • Browser

Media spend attaches to channel, source, medium and campaign. Nobody can upload a cost per browser version, so on the other dimensions the cost metrics stay blank instead of showing you a zero you might believe.

Identity

One person, however many devices

A funnel counts people, not sessions. Stage four is only comparable to stage one if the product knows that the anonymous browser from March and the signed contract from May are the same person.

An alias graph, not a cookie

Every identifier we have ever seen for a person — browser ids and your own user ids — points at one profile. Resolving a visitor is a single indexed lookup.

Merging, done carefully

When two profiles turn out to be one person, they merge: the identified profile survives, the earlier first-touch is kept, and every conversion is re-credited.

Cross-device by default

Someone who researched on their phone and bought on a laptop is one customer with one path — as long as they identified on both.

Attribution models

Six models, and the funnel entry takes one too

Every report is computed under a model you pick, and switching it recomputes the page. It is the fastest way to see how much of your reporting is a modelling choice rather than a fact.

Attribution models available on every plan
ModelTypeWhat it is for
First touchSingle touchAnswers "what creates demand". Favours awareness channels and will make your brand campaigns look better than your retargeting. Use it when you are deciding where to spend to reach new people.
Last touchSingle touchThe default in most ad platforms, which is why they all claim the same conversion. Favours closing channels — branded search, retargeting, email. Simple, and consistently overstates the bottom of the funnel.
Last non-directSingle touchLast touch, but it skips past "direct" — someone typing your URL or arriving with a stripped referrer is not a marketing channel. This is what GA4 does by default and it is usually the fairest single-touch view.
LinearMulti touchTreats every touch as equally responsible. Honest about the fact that a journey has many steps, deliberately naive about which mattered. A good sanity check against the single-touch models.
Position basedMulti touchThe U-shaped model. Rewards the channel that found the person and the channel that closed them, while still acknowledging the middle. The pragmatic default for most teams running both awareness and performance.
Time decayMulti touchCredit halves for every half-life period further from the conversion. Right for short consideration cycles, where a touch from six weeks ago genuinely mattered less than one from yesterday.

A funnel entry takes first or last touch, so you can ask whether the campaign that started these people was the same one that closed them.

AI analysis

An analyst that has to show its working

Sixteen dimensions across five stages is more cells than anyone reads on a Monday. Point the analysis at a window and it returns the segments carrying people to the money, the ones consuming budget and stopping early, ordered recommendations, and the caveats that would make the read unreliable. Every number in the output is copied from the evidence pack rather than estimated.

  • Reads six traffic breakdowns — channel, source / medium, campaign, landing page, device type and operating system — against the window before it.
  • Reads your primary funnel as well: the same segments scored at every stage, so it can tell you where a campaign stops rather than only that it converts badly.
  • Will not build a traffic recommendation on a segment under thirty visits, or a funnel recommendation on one with fewer than ten people in it. It can raise either as something to watch, and has to say that is what it is doing.
  • Refuses to run at all on a window with fewer than fifty visits, and tells you to widen the range instead of inventing a conclusion.
  • Never recommends spending more or less on Direct, because nobody can buy Direct. A high direct share is raised as a tracking-coverage caveat instead.
  • Says nothing about ROAS or CPA when the project has no cost data. It knows conversion rates and revenue, not what anything cost, and it names that as the gap.
  • Returns fewer items and low confidence when the evidence does not support more. An empty list is an acceptable answer.
  • Knows that funnel stages are not strictly nested, so it does not report a later stage overtaking an earlier one as an error.
  • Reads aggregates only. No email address, name, IP address or individual profile reaches a model provider.

Reporting

Group by anything, measure anything

Any dimension against any of twenty-one metrics, filtered, sorted, compared with the previous period and exported to CSV. The overview is the same data read at a glance.

Overview · Last 30 days
Illustrative example — not real customer data

Visitors

17.4K

+18.4%vs previous period

Conversions

814

+24.1%vs previous period

Attributed revenue

$121.3K

+31.7%vs previous period

Blended ROAS

4.0x

−4.2%vs previous period

Visits over time

05001,0001,500May 1May 6May 11May 16May 21May 26May 30

Revenue by channel

  • Organic Search212 conversions · 4.3% rate$31.8K
  • Paid Search184 conversions · 3.0% rate$27.6K
  • Email148 conversions · 6.7% rate$22.2K
  • Direct96 conversions · 4.0% rate$14.4K
  • AI Assistants51 conversions · 5.4% rate$9,180
  • 3 more rows not shown

Traffic mix

  • Paid Search27%
  • Organic Search22%
  • Paid Social18%
  • Direct11%
  • Email10%
  • Referral5%
  • AI Assistants4%
  • Organic Social4%

Metrics

  • Visitors
  • New visitors
  • Visits
  • Pageviews
  • Bounces
  • Time on site
  • Conversions
  • Revenue
  • Spendneeds spend
  • Impressionsneeds spend
  • Ad clicksneeds spend
  • Bounce rate
  • Avg. visit
  • Pages / visit
  • Conv. rate
  • Rev. / visitor
  • Avg. value
  • CPAneeds spend
  • ROASneeds spend
  • CPCneeds spend
  • CTRneeds spend

Tracking

Two SDKs, one dataset

The browser SDK captures the top of the funnel: the click, the campaign, the landing page. The server SDK captures the stages that pay — the webhook, the CRM stage change, the refund — which a browser never sees. Both write to the same person.

  • Under 4KBGzipped, no dependencies, loaded with defer so it never blocks a paint.
  • First-partyServed from your Attruly domain, so ad blockers and ITP treat it as yours.
  • Automatic capturePageviews, SPA route changes, UTM parameters, click ids and referrers.
  • Offline safeEvents queue when the network is gone and flush on reconnect, deduplicated by message id.
index.html
<script defer
  src="https://www.attruly.com/a.js"
  data-key="pk_live_YOUR_KEY"></script>
app.js
attruly.identify('user_8412', {
  email: 'sam@acme.com',
  plan: 'growth',
})

attruly.track('Demo Booked', {
  source: 'pricing_page',
  seats: 12,
})
webhooks/stripe.ts
import { Attruly } from '@attruly/node'

const attruly = new Attruly({ apiKey: process.env.ATTRULY_SECRET_KEY })

// A Stripe webhook the browser never sees — still attributed to the
// campaign that brought this person in, months earlier.
await attruly.track({
  userId: invoice.customer,
  event: 'Subscription Paid',
  revenue: invoice.amount_paid / 100,
  currency: invoice.currency.toUpperCase(),
})

Classification

Your utm_source is a mess. That is fine.

Google / Paid, google / cpc and an untagged gclid all mean the same thing. Attruly folds them into one row so a campaign enters the funnel once, with the spelling your traffic actually used.

Paid Search

Paid

Search ads — Google Ads, Microsoft Ads. Matched on a cpc/ppc/paid medium or a gclid.

Paid Social

Paid

Paid placements on social platforms, including clicks carrying an fbclid or ttclid.

Display

Paid

Banner, programmatic and retargeting placements.

Video

Paid

Video placements — YouTube campaigns and in-stream advertising.

Organic Search

Unpaid search traffic, matched on an organic medium or a search-engine referrer.

Organic Social

Unpaid posts, profile links and shares on social platforms.

AI Assistants

Referrals from ChatGPT, Claude, Gemini, Perplexity and peers.

Email

Newsletters, lifecycle and drip campaigns, plus links opened from webmail.

Affiliate & Partner

Paid

Affiliate links, partner co-marketing and referral programmes.

SMS & Messaging

SMS, WhatsApp, push notifications and in-app messaging.

Referral

Links from third-party sites that are not search, social or AI.

Internal

Traffic tagged from the project’s own properties — not an acquisition source.

Other Campaign

Tagged traffic whose medium does not map to a known channel.

Direct

No campaign tag and no referrer. Typed URLs, bookmarks, and traffic that lost its referrer in transit.

The rest of it

What running this every week needs

The tracking, the identity graph, the models and the reporting are one system, because attribution breaks at the seams between tools.

One project per site

Every site gets its own keys, goals, funnels, timezone and currency, and they never share data. That separation is what makes this workable for an agency.

Raw events, kept

Not a sampled aggregate. Every event stays queryable and exportable for as long as your plan retains it, so a number you disagree with can be traced back to its rows.

Real-time

An event lands and the dashboard reflects it. Nothing waits four hours to tell you whether a launch worked.

Person-level paths

Open a profile and read the whole path in order — every touch, every session, every event, with the credit each one received.

Spend, CPA and ROAS

Import your media spend and every channel, source, medium and campaign row carries its own cost per acquisition and return, next to the conversions it earned.

First-party by design

Your domain, your data, your database. Self-host the whole thing on your own infrastructure if that is what compliance needs.

See it against your own funnel

Install the snippet, put your milestones in order, and compare what Attruly says to what your ad platforms claim.