Which channel brings paying customers? Stripe, without a tracker
18 September 2026 · by Nordva, who make Nordva Launch
How do I see which marketing channel brings paying customers when payments are in Stripe?
Record where each person came from at the moment they sign up (the referring site and the UTM values, read once from the page), store it next to their email, then match that email to your Stripe customers. Group by source and you have signups, paying customers and revenue per channel, without cookies or a tracking script.
Your ad dashboard shows clicks. Your analytics show visits. Stripe shows money. None of them shows the thing you want to know: which of the things I did last month produced customers who pay.
You can answer that with two pieces of data you already control, and no tracker.
The idea
- When someone signs up (waitlist, trial, newsletter, account), record where they came from, once.
- Later, when money arrives in Stripe, match the payer’s email to that signup.
- Group by source.
That is first-touch attribution on real identities. It is less than a full tracking tool sees, and for a small product it is usually enough to decide where to spend next month.
Step 1: capture the source when the form loads
Read it from the page once. Reduce the referrer to a hostname before it leaves the browser: full referrer URLs can carry search terms and tokens, and a hostname is all a report needs.
function firstTouch() {
const src = {};
try {
if (document.referrer) {
const host = new URL(document.referrer).hostname.replace(/^www\./, "");
if (host !== location.hostname) src.referrer = host; // moving inside your own site is not a source
}
const q = new URLSearchParams(location.search);
for (const k of ["utm_source", "utm_medium", "utm_campaign"]) {
const v = q.get(k);
if (v) src[k] = v.slice(0, 255);
}
src.landing_path = location.pathname;
} catch {}
return src;
}
Send it with the signup and store it in columns next to the email: source_referrer, utm_source, utm_medium, utm_campaign, landing_path. Two rules matter:
- Never reject a signup because the source is odd. Normalise what you can and store null for the rest.
- Keep the first one. If the same email signs up again from somewhere else, do not overwrite.
Then tag your own links. ?utm_source=reddit&utm_campaign=launch-week on the link you post is what separates “reddit.com” from “the Reddit post I paid for”.
Step 2: get paying customers out of Stripe, read-only
You need three lists: customers (email), subscriptions (status, amount) and paid invoices (amount, date). Use a restricted key with read permissions only, never your secret key, for anything that reads your Stripe account on a schedule.
Normalise emails on both sides before matching: lowercase, and for Gmail remove dots and anything after a plus sign, so Jane.Doe+launch@gmail.com and janedoe@gmail.com are one person.
Step 3: the report
Per source: signups, how many have an active subscription, and what they have paid. In SQL, roughly:
SELECT COALESCE(s.utm_source, s.source_referrer, '(direct)') AS source,
COUNT(*) AS signups,
COUNT(DISTINCT sub.customer_id) AS paying,
SUM(inv.amount_paid) AS revenue
FROM signups s
LEFT JOIN stripe_customers c ON c.email_normalised = s.email_normalised
LEFT JOIN stripe_subscriptions sub ON sub.customer_id = c.id AND sub.status IN ('active', 'past_due')
LEFT JOIN stripe_invoices inv ON inv.customer_id = c.id AND inv.paid
GROUP BY 1
ORDER BY paying DESC, signups DESC;
Keep currencies apart. Never add USD to EUR.
Step 4: add what each channel cost
Signups and revenue per source tell you what worked. Add spend and you know what it was worth. For each source and period, record what you paid: the ad budget, the sponsorship, the tool. Then:
- cost per signup = spend ÷ signups
- cost per customer = spend ÷ paying customers
- return on spend = revenue from those signups ÷ spend
Two details save you from wrong conclusions. If a cost covers a month and your report covers a week, count the cost in proportion to the days that overlap. And list sources that cost money and brought nobody: that row is usually the most useful one on the page.
What this does not tell you
- People who paid without ever signing up through your form.
- People who signed up with one email and paid with another.
- Anything after the first touch. Someone who found you on Hacker News and came back through Google three weeks later counts for Hacker News.
- Visits. It starts at the signup. If you want the top of the funnel, count page views per source as a plain daily number, without identifying visitors.
Doing it with Nordva Launch
This is what Launch’s attribution does, so you do not have to build the three steps:
- The waitlist widget, hosted page and API record the first-touch source on every signup, on every plan including Free, with no cookies.
- You connect Stripe with a restricted, read-only key in the dashboard. Launch never writes to your Stripe account.
GET /v1/attributionreturns signups, paying customers, MRR and revenue per referring site, UTM source, campaign or referrer. Record channel costs and it adds cost per signup, cost per customer and return on spend.- With the MCP server connected, you can ask your coding agent: “which source produced paying customers last month, and what have those customers asked for?”
The same limits apply as above, and the report says so in its own output.
Questions
- Does Stripe know where my customers came from?
- No. Stripe records the payment and the customer's email. It has no idea which page, ad or post the person arrived from, unless you put that into the customer's or the checkout session's metadata yourself.
- Do I need cookies or a consent banner for this?
- The method here sets no cookie and stores nothing in the browser: the source is read from the page once, when the form loads, and sent with the signup. Whether your site needs a banner for other reasons is a separate question, and a legal one.
- What does this method miss?
- Anyone who pays without first signing up through your form, people who sign up with one email and pay with another, and every touch after the first. It tells you which channel first brought a customer, not everything that influenced them.
- How is this different from an attribution tool with a tracking script?
- A tracker follows a visitor across pages and visits and ties the visit to the payment, which sees more of the journey and needs a script, storage and usually consent. The signup-source method sees only the first touch of people who signed up, and needs none of those.
Try it in your project
npx nordva@latest init
Free plan, no card, no invite.