Open AnalyticsdocsDashboard
Documentation menu

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.

wherever you record the visitor's choice
oa.consent("granted"); // or "denied", which stops collection entirely

We 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:

success page
oa.conversion("purchase", { order_id: "cs_live_a1B2c3" });
  • order_id is 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:

browser
oa.identify("user_8f21c4");
server, creating the checkout
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.

Privacy

Card numbers never touch our servers, provider payloads are never persisted, and the customer reference is stored only as a non-joinable pseudonym. Revenue aggregates are readable over the API by the site owner; individual transactions never leave the dashboard.