On this page
Revenue attribution means tying each payment to the visit that first brought the customer, so you can see revenue, customers and revenue per visitor for every traffic source instead of only visitors and pageviews. It takes three pieces: a visitor id that your tracker keeps in the browser, that id passed into the checkout, and a webhook from your payment provider that reports each payment back with the id attached. Once those three are in place, the question "which source brings people who pay" has a number next to it.
The short version. Read the visitor id from the tracker's cookie, put it in the checkout's metadata under one agreed key, and point the provider's webhook at your analytics. Then sort sources by revenue per visitor, not by visitors.
Why visitors are the wrong number
A source that sends many visitors is not the same as a source that sends customers. Search traffic is wide: people comparing, students, your own team. A launch on a community site sends a burst of curious people who rarely buy. Meanwhile a smaller source, a newsletter mention or an AI assistant answer, can send a few hundred people of whom a surprising number pay. Ranked by visitors the small source is at the bottom; ranked by revenue per visitor it is at the top. You cannot see that from pageviews, and a goal like "visited the pricing page" only tells you about intent, not money.
The three pieces
1. A visitor id that survives until the payment
The tracker creates a random id the first time a browser visits your site and keeps it in local storage and in a first-party cookie. It is random, so it says nothing about the person, and it is per site, so nobody is followed across the web. With Glai the cookie is called glai_vid; the first visit's source, campaign and landing page are stored against that id, which is what "first touch" attribution reads later.
2. The id passed into the checkout
When your server creates a checkout session, read the cookie and add the id to the checkout under the key glai_visitor_id. Stripe takes it in metadata (or client_reference_id), Polar in metadata, Paddle in custom_data and Lemon Squeezy in the checkout's custom data. The install guide has the exact lines for each provider.
3. A webhook back to the analytics
Each provider can call an address of yours when a payment succeeds or is refunded. The analytics side verifies the call with the signing secret, reads the amount, currency, customer email and the visitor id, finds the visitor and stores the payment with a snapshot of that visitor's first source. A refund later reduces the amount; renewals of a subscription count as new payments against the same visitor.
Setting it up, in order
- Install the tracker and confirm a visit shows up. Attribution needs the first visit recorded before the payment, so do this well before you launch a campaign.
- Add the id to your checkout code. One line on the server, usually where you already set the success address. Test it with a real checkout in the provider's test mode and look at the session's metadata.
- Add the webhook in the provider's dashboard, with the events for successful payments and refunds, and paste the signing secret into your analytics.
- Make a test payment and check it appears next to the visit. If the visitor id did not make it through, the payment is still stored, with the customer's email, and it is matched to a visitor who later identifies with that email.
The three numbers to watch
| Number | What it tells you | Watch out for |
|---|---|---|
| Revenue per visitor | How much a source is worth per person it sends, the number to rank sources by | Small sources swing wildly; wait for a few hundred visitors |
| Conversion rate | Customers divided by visitors, the quality of the source | A free plan signup is not a customer; count payments |
| Days to payment | How long from first visit to first payment, the length of the decision | Long cycles need a long retention window to be seen at all |
Read them together. A source with high revenue per visitor and a short time to payment is where to spend next week. A source with many visitors and a long time to payment may still be your best, but it needs patience and a retention window that covers the whole cycle, which is why Glai keeps payments with their attribution for as long as the site exists, whatever the plan's retention of raw events.
The mistakes
- Creating the checkout on a different domain. The cookie belongs to your site's domain; a checkout page on another domain cannot read it. Read the id on your own page and pass it along.
- Last touch by accident. If you overwrite the stored source on every visit, the payment is credited to the visit right before it, often "direct". First touch answers "what brought this person"; keep both if you can.
- Counting signups as revenue. A signup is a goal. Revenue is a payment reported by the provider, after refunds. Mixing them flatters sources that bring free users.
- Forgetting refunds. A source that brings customers who refund is worse than it looks. The webhook should carry refunds, and the dashboard should subtract them.
What Glai does
Every site gets a webhook address per provider and a field for the signing secret. The payment is stored once with the visitor's first source, campaign, country and device, so every breakdown of the dashboard can show revenue and customers beside visitors, and the AI can answer "which source brings the customers who pay" from the same table. The sources that matter most for this, including AI assistants, are named rather than hidden as referrals. See what it costs on the pricing page, or start free and connect Stripe this afternoon.
Questions people ask
Does revenue attribution need cookies?
It needs a first-party id kept in the visitor's own browser, which is a cookie or local storage on your own domain. It is not a third-party cookie and nobody is tracked across sites. In a tracker's strict daily mode, which stores nothing, attribution by visitor id is off and payments are matched by email instead.
What if the customer pays on a different device?
The visitor id lives in one browser, so a payment from another device arrives without it. It is then matched to a visitor who identified with the same email address, if your app calls identify after sign-in. Otherwise the payment is recorded with no source.
Which provider events should the webhook send?
Successful payments and refunds. For Stripe that is checkout.session.completed, invoice.paid and charge.refunded. Polar, Paddle and Lemon Squeezy each have an order paid and an order refunded event. Anything else is ignored and answered with a 200 so the provider stops retrying.
Is first touch or last touch better?
First touch answers what brought the person to you in the first place, which is the question a marketing budget needs. Last touch tends to credit "direct" and your own emails. Store the first visit with the payment, and keep the full journey for the cases where you want to see the path.