Stripe revenue by traffic source: a practical guide for SaaS founders
September 25, 2026 · 7 min read
Most founders can tell you how many visitors they had last week. Far fewer can tell you which of those channels produced revenue. That gap is expensive: you end up doubling down on the channel with the most traffic, which is often not the one with the most customers.
The core idea: carry an ID from visit to payment
Attribution is a join between two systems that don't know about each other: your analytics (which knows where a visitor came from) and your payment provider (which knows who paid). To join them you need one shared key. The simplest one is an anonymous visitor ID that your analytics assigns, which you pass into the checkout as metadata.
- Analytics assigns an anonymous ID to the visit and remembers its source.
- When the visitor starts checkout, your code adds that ID to the Checkout Session's metadata.
- When Stripe sends the payment webhook, the ID comes back, and the payment can be credited to the original source.
Step 1: send the ID with checkout
// Browser: include the visitor id with your checkout request
await fetch("/api/checkout", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ vid: window.cleverpilot?.vid }),
});Step 2: put it in Stripe metadata
// Server (Node): create the Checkout Session
const session = await stripe.checkout.sessions.create({
mode: "subscription",
line_items: [{ price: "price_123", quantity: 1 }],
success_url: "https://example.com/thanks",
metadata: { cleverpilot_vid: body.vid },
// Copy it onto the subscription so renewals are attributed too:
subscription_data: { metadata: { cleverpilot_vid: body.vid } },
});Putting the ID on subscription_data matters for SaaS: it means every renewal invoice carries it, so a customer from a blog post keeps counting toward that post month after month.
Step 3: listen to the right webhooks
For one-off payments, checkout.session.completed is enough. For subscriptions, use invoice.paid, which fires for the first payment and every renewal. Always verify the webhook signature, and de-duplicate by the Stripe object ID, because Stripe retries deliveries.
First touch or last touch?
If a visitor first came from Google, left, and came back a week later by typing your URL, who gets the credit? There's no universally right answer. For early-stage SaaS, crediting the source of the visit that led to checkout is simple and actionable. Privacy-first tools that don't use cookies (including Cleverpilot) can't follow one person across many days, which keeps the model honest and simple rather than stitching together a surveillance profile.
Reading the results
- Revenue per visitor by channel is the number to watch. It normalizes for traffic volume.
- Look at pages, not just sources. Which landing pages do paying customers enter on? Write more like those.
- Give it a few weeks. With a handful of customers, one big deal can skew everything.
Cleverpilot does all of this out of the box for Stripe, Paddle and Polar. See the revenue docs, or look at the live demo's Revenue tab.
Ask your site a question. Get the answer.
Cleverpilot plans and sets up your tracking from a plain-English goal. Cookieless, free forever for small sites.