Revenue attribution
Connect Stripe and see which pages, channels and campaigns actually earn.
Connecting Stripe
Under your site's Settings, Integrations, connect Stripe with a restricted, read-only key: a couple of minutes, no code changes. From then on payments, refunds, disputes and fees flow into the Revenue tab, joined to the visits that produced them where a signal exists. Disconnecting stops the flow immediately.
Attribution is opt-in, and it asks something of you
Revenue totals need nothing from your visitors. Tying a payment back to the visit that produced it is different on both counts: you turn Attributed revenue on when connecting Stripe — until you do, the script sends no order_id at all and the conversion is just a count — and the linking itself carries a consent obligation you meet as the controller of your site.
The switch decides whether the link happens at all, not just what the script sends. An order_id that reaches us while it is off, from a cached copy of the script or a request you wrote yourself, is dropped before the event is stored; and the matcher skips your site entirely, so a payment is not linked through your own Stripe integration either (a client_reference_id, an id on the customer). Conversions are still counted and revenue totals are unaffected — what stops is the journey.
Switching it off leaves the journeys you already have; it stops new ones. Switching it back on picks up roughly the last month of payments on the next pass — that is how far back the matcher re-reads — and older ones stay as they are.
oa.consent("granted"); // or "denied", which stops collection entirelyWe do not hold the hint back on a consent state we cannot see, so wiring this is yours to do. The best place to ask is your own checkout page: consent collected inside Stripe Checkout is consent for taking payment, and the analytics link is a different purpose with a different controller — you.
Recipe 1: the order_id conversion (the strong one)
Fire a conversion on your success page carrying the order:
oa.conversion("purchase", { order_id: "cs_live_a1B2c3" });order_idis the Stripe Checkout Session (cs_…), PaymentIntent (pi_…) or charge id (ch_…), whichever your page has.- The join is exact: the transaction and its journey get confidence “exact”, the strongest the system issues.
- A conversion is a billable custom event, one unit; nothing about the recipe bills twice.
Recipe 2: identify plus client_reference_id
When your success page cannot know the order, pass the same stable user reference to both sides:
oa.identify("user_8f21c4");stripe.checkout.sessions.create({
client_reference_id: "user_8f21c4",
// ...
});Both sides are hashed with the same site-scoped derivation and joined without either value ever being stored raw. This yields confidence "linked": it identifies the person rather than the order, which is exactly what makes it the fallback. See identify for the rules.
What the reports show
- Net revenue with its parts printed: gross, refunds, disputes, fees. A flat month of quiet trading and a flat month of heavy refunds look different here, on purpose.
- Gross and net share one chart; the gap between the lines is the cost of doing business.
- Payments the join could not attribute still count in every total; they simply have no journey. There is no IP matching and no time-proximity guessing, by policy.
- Currencies that could not be converted are listed beside the totals rather than silently dropped.