How to attribute Stripe revenue to marketing channels

Stripe attribution writes a visitor's source onto the payment in 6 steps. See where Stripe stores it, what to count as revenue and which tools do the join.

Muzahid Maruf — Founder of TrackRev.io

Muzahid MarufUpdated

Revenue attribution · 9 min read
On this page
  1. 01What does Stripe store about a sale?
  2. 02Which 4 ways join a payment to a source?
  3. 03How does Stripe attribution work, step by step?
  4. 04What do the numbers look like after the join?
  5. 05How do you choose a window and a credit rule?
  6. 06How do Stripe attribution tools compare?
  7. 07Where does the chain break?
  8. 08What does TrackRev do with a Stripe charge?

Explore with AI

Opens this article inside the chosen assistant with a ready-made prompt.

Stripe attribution means attaching the marketing source of a visit to the Stripe payment it produced, so revenue can be totaled by channel.

A Checkout Session has no UTM field, and the Payment Links tracking guide describes UTM codes coming back on the redirect URL. Your side has to carry the source from the browser to the charge.

The work takes a first-party cookie and a few server lines, then a report that groups paid invoices by what you stored.

This guide covers the 6 steps, the Stripe events that count as revenue and 4 ways to run the join in 2026.

In the illustrative numbers below, paid social brings 57.1% of the trials on a $39 plan and 19.1% of the net revenue, so ranking by signups would misplace budget.

For example, the newsletter sends 17.1% of the trials and earns 48.4% of the revenue, as the worked table later in this guide shows.

Key takeaways

  • Stripe records no campaign for a sale. The source rides in client_reference_id (200 characters) or metadata (50 keys) that your server writes.
  • Metadata copies between Stripe objects only in a few cases, so write the source onto the Subscription or PaymentIntent whose events you will read.
  • Count revenue from invoice.paid, subtract the amount on each charge.refunded event, and wait for checkout.session.async_payment_succeeded on delayed methods such as ACH debits.
  • In the worked example (illustrative figures), paid social brings 57.1% of the trials on a $39 plan and 19.1% of net revenue. Crediting only first payments would cut the newsletter's share from 48.4% to 39.0%.

What does Stripe store about a sale?

A Stripe sale is a chain of objects: a Customer, a Checkout Session, a PaymentIntent, a Charge and, for subscriptions, an Invoice each billing period.

Each object has a metadata field, and the metadata guide says metadata copies between objects only in the cases below. Only secret-key requests return metadata, so your server does the writing.

FieldLimitWhere the value ends up
client_reference_id on a Checkout Session200 charactersThe Session and its checkout.session.completed event
metadata on any object50 keys, 40-character keys, 500-character valuesThe object you set it on
payment_intent_data.metadata in CheckoutSame as metadataThe PaymentIntent, then a one-time copy on its Charge
subscription_data.metadata in CheckoutSame as metadataThe Subscription, then a copy on every later Invoice
Metadata on a Payment LinkSame as metadataA snapshot on each Checkout Session the link creates
UTM codes on a Payment Link URL5 codes, 150 characters eachYour redirect URL

From Stripe's metadata, Checkout and Payment Links documentation, October 2026.

Metadata set on a Customer does not copy to its Charges. Write the source onto the object whose events you will read, when you create it.

For example, a subscription written with subscription_data.metadata lets all 12 invoices of a year carry the source (October 2026).

Which 4 ways join a payment to a source?

Four routes join a payment to a source: a Payment Link per channel, a visitor ID in Stripe Checkout, the customer email and a GA4 purchase event.

The first and third routes need no checkout code, but the second is the one I would build, because only it stores a journey you own.

Google's Measurement Protocol guide asks for server events within 48 hours of the browser event, so renewals strain the fourth route. For instance, a renewal billed on day 30 arrives long after that window closes.

The Google Analytics guide has the build. In practice, the visitor ID route breaks only when payments skip your server, as a Payment Link does.

RouteCodeKeepsBreaks when
One Payment Link per channelNoneThe channel, as link metadataPlacements outnumber links
Visitor ID in Stripe CheckoutA few server linesThe stored journeyPayments skip your server
Customer emailNoneAny flow with matching emailsSignup and payment emails differ
GA4 purchase eventA webhookGoogle's channel reportsRenewals arrive late

How does Stripe attribution work, step by step?

Stripe attribution by visitor ID is a chain of 6 links, and a break in any one sends revenue to an unattributed row. Step 1 tags the link and saves the source. Step 2 ties the visitor to an account.

Step 3 writes the ID into Stripe Checkout. Step 4 reads the money from Stripe Billing webhooks. Step 5 groups paid invoices by source. Step 6 tests the chain in a Stripe sandbox, where no real card is charged.

Each step names the exact Stripe field or event, with limits taken from Stripe's documentation of October 2026.

A UTM tag is a lowercase label such as utm_source=newsletter, and each placement needs its own values, stored on arrival.

Google's Analytics Help page says parameter values are case sensitive, so Newsletter and newsletter count as 2 sources in Google Analytics. Have your server set the cookie.

According to WebKit's cookie rules, Safari Intelligent Tracking Prevention deletes JavaScript-created cookies after 7 days without interaction. The same rules cap cookies set in an HTTP response at 7 days only when WebKit detects third-party CNAME or IP address cloaking.

A cookie from your own server therefore stays outside the 7-day script rule in 2026.

Step 2: Why tie the visitor to an account at signup?

A visitor record is the row that holds the visitor ID, first-touch source and email, and the user record should store all 3 values at signup.

A buyer who clicks on a phone and pays on a laptop holds 2 cookies and 1 email, and the email links the 2 cookies.

The signup row also survives a cleared cookie, so a payment made weeks later still finds its source. Lowercase the email before saving, so Jane@Example.com and jane@example.com match.

In practice, save the row at signup and read the row at payment, because the 2 events can sit days apart in Stripe Billing.

Step 3: How do you write the visitor ID into Stripe?

A Checkout Session is the Stripe object that carries the visitor ID, and the Session should be created when the buyer clicks Buy.

A Session stays open for 30 minutes to 24 hours, so one built at page load carries whatever the cookie held then. Put the ID in client_reference_id and in metadata, using the subscription or PaymentIntent field that matches the mode.

A UUID takes 36 characters, so 164 of the 200 allowed characters stay free. The Checkout attribution guide has the route and the metadata setup guide has key names.

For example, a Stripe Checkout Session created at 10:00 can still be paid 24 hours later.

A Payment Link skips your server, so append client_reference_id to its URL. Stripe accepts letters, digits, dashes and the _ character up to 200 characters, which fits a 36-character UUID. The Payment Links attribution guide covers the rest.

LimitValueWhy it matters
Checkout Session lifetime30 minutes to 24 hoursA Session built early holds an old cookie
client_reference_id200 charactersA 36-character UUID fits
Metadata keys per object50A visitor ID plus 6 UTM fields uses 7
Live-mode webhook retriesUp to 3 daysDuplicate events need a unique index

Limits from Stripe's Checkout, metadata and webhook documentation, October 2026.

Step 4: Which Stripe events count as revenue?

Revenue events are the webhooks that fire when money moves, and 3 of them cover most flows. Stripe's subscription webhook guide says invoice.paid is sent when an invoice is successfully paid.

Each new invoice gets a copy of the subscription's metadata under parent.subscription_details.metadata, so payment 12 of a $39 plan carries the source written for payment 1.

Live mode retries a failed delivery for up to 3 days, so store each event ID under a unique index.

For example, a retried invoice.paid event must not book the same $39 twice, and a 12-month plan books exactly 12 events.

EventFires whenAction
checkout.session.completedStripe Checkout finishesLink visitor ID to customer
invoice.paidAny invoice is paidBook the revenue once
charge.refundedA full or partial refundSubtract the amount

Events from Stripe's subscription and refund documentation, October 2026.

A completed Checkout Session is not always a settled sale

Stripe's Checkout fulfillment guide says ACH direct debit and other delayed methods fire checkout.session.async_payment_succeeded only once the payment succeeds, so credit a channel on that event.

Step 5: How do you group paid invoices by source?

A source report is a table that totals paid invoices per source, net of refunds. Credit one amount and write the rule down. A Checkout Session reports amount_subtotal, amount_total and total_details.amount_tax, so the pre-tax figure is easy to isolate.

Stripe's refund guide says a charge can take several refunds and the original processing fee is not returned, so keep gross and net in separate columns. The SQL below totals customers, gross, refunded and net per channel from 2 tables.

In the worked example, the Newsletter row nets $2,964 of $6,123 across 166 invoices. Unattributed rows stay visible as their own channel, which shows how much of the 100% of revenue the join misses.

Revenue by channel from your own payments and refunds tables (SQL)
-- payments: one row per paid invoice or one-time charge, filled from the webhook-- refunds: one row per charge.refunded amount, linked to the paymentwith refunded as (  select payment_id, sum(amount_cents) as cents  from refunds  group by payment_id)select  coalesce(p.source, 'unattributed')                   as channel,  count(distinct p.customer_id)                        as customers,  sum(p.amount_cents) / 100.0                          as gross,  sum(coalesce(r.cents, 0)) / 100.0                    as refunded,  sum(p.amount_cents - coalesce(r.cents, 0)) / 100.0   as netfrom payments pleft join refunded r on r.payment_id = p.idwhere p.livemode  and p.paid_at >= date '2026-07-01'group by 1order by net desc;

Step 6: How do you test the chain in a sandbox?

A sandbox test is a rehearsal that proves the chain before real revenue depends on the chain.

Click a tagged link in a private window, sign up and pay with Stripe's test card 4242 4242 4242 4242 and a future expiry such as 12/34.

Then refund the payment: the channel should gain the amount and lose it again. Check 3 rows afterward, namely the visitor row, the payment row and the refund row.

Production queries must skip test events, as the break table below explains.

What do the numbers look like after the join?

Take a $39 monthly plan and 90 days of sales from 3 channels. The figures are invented to show the arithmetic, so replace them with your own.

ChannelTrials (share)Paid invoicesRefunded invoicesNet revenue (share)
Paid social400 (57.1%)344$1,170 (19.1%)
Search ads180 (25.7%)543$1,989 (32.5%)
Newsletter120 (17.1%)782$2,964 (48.4%)
Total7001669$6,123

Net revenue is paid invoices minus refunded invoices, times $39, over 90 days. Illustrative figures.

Paid social leads on trials, with 400 of 700. It earns $1,170 of the $6,123, while the newsletter's 120 trials return $2,964. Per trial, that is $24.70 for the newsletter, $11.05 for search ads and under $3 for paid social.

Paid social also refunded 4 of 34 invoices, or 11.8%, against 2.6% for the newsletter, so gross revenue would have flattered it by $156.

Renewals shift the picture again. If a report credits only each customer's first payment, the newsletter's share falls from 48.4% to 39.0%, because its customers paid 2.6 invoices each against 1.7 for paid social.

The subscription LTV guide covers 3 ways to credit renewals.

ChannelPaying customersInvoices per customerFirst payments only (share)Net revenue (share)
Paid social201.7$780 (26.0%)$1,170 (19.1%)
Search ads272.0$1,053 (35.1%)$1,989 (32.5%)
Newsletter302.6$1,170 (39.0%)$2,964 (48.4%)

First payments are paying customers times $39, before refunds. Same 90 days of sales as above.

How do you choose a window and a credit rule?

A window is the number of days a click can still earn credit for a payment.

In our attribution benchmark data, the median time from first click to first paid charge is 6.3 days and the 90th percentile is 48.2 days. The counts cover only conversions inside each workspace's window.

Pull the click-to-payment gap for your last 100 customers and set the window just past the 90th percentile. Rounding the 48.2-day benchmark up gives a 49-day starting window, which your own figure then replaces.

Last touch gives the closing click all the credit, first touch gives the credit to the introducer, and linear splits the credit evenly, so a sale touched by 2 channels counts 0.5 on each.

In our Q2 2026 data, 64% of TrackRev workspaces default to last touch, 22% to linear and 14% to first touch. The attribution models comparison matches each rule to a funnel.

Credit ruleShare of TrackRev workspacesWho gets the credit
Last touch64%The closing click
Linear22%Every touch, evenly
First touch14%The introducing click

Default credit rule per workspace in TrackRev's Q2 2026 benchmark data.

How do Stripe attribution tools compare?

Stripe attribution tools are the reports and software that total Stripe revenue by source, from Stripe Sigma to billing-side tools.

The Sigma guide says Stripe Dashboard financial reports can include metadata and Sigma's templates leave it out, with a Metadata to column template to add it.

Sigma runs ANSI SQL, shows up to 1,000 rows, exports all of them to CSV and costs nothing in a Stripe sandbox.

Pricing starts at $15 a month on monthly billing and falls to 2¢ per additional charge on the 25,000-charge annual tier, per Stripe (October 2026).

The second table compares 4 approaches by what each can see, from Google Analytics 4 to billing-side software.

Stripe Sigma billingCharges included a monthPrice a monthEach additional charge
MonthlyNot stated$156¢
Annual250$104¢
Annual2,500$602.5¢
Annual10,000$2252.5¢
Annual25,000$4502¢

From Stripe's Sigma pricing page, October 2026. New users get a 30-day free trial.

ApproachSees the clickRenewals and refundsEffort
Stripe Dashboard reports or Stripe SigmaNo, only stored metadataYes, in Stripe's dataA query plus the metadata write
Your own webhook and databaseYes, once you build the click logYes, from invoice.paid and charge.refundedAn endpoint, 2 tables and a report
Google Analytics 4 with the Measurement ProtocolYes, inside GA4Limited by the 48-hour windowA webhook and a GA4 property
A billing-side tool such as TrackRevYes, via pixel and tracked linksYes, renewals credit the first clickA pixel and a restricted key

Where does the chain break?

The chain breaks in 3 common places, and each break is a number that disagrees with Stripe. Check the time zone first, then test events, then split buyers.

For example, a Sigma query and a Dashboard report can disagree on one day's total near midnight (October 2026). The table lists all 3 symptoms with their causes and fixes.

SymptomCauseFix
Your total differs from Stripe's reportStripe Dashboard reports default to your local time zone, Sigma templates use UTC, and a day's balance report publishes by 12:00 pm the next dayMatch the time zone and compare after noon
Test payments inflate a channelTest events arrive with livemode falseSkip them in production queries
One buyer shows up as 2 channelsA phone click and a laptop payment leave 2 cookiesJoin on the email saved at signup

Causes from Stripe's reporting and Sigma documentation, October 2026.

What does TrackRev do with a Stripe charge?

TrackRev is SaaS affiliate software with revenue attribution built in, and we built it to read Stripe with a restricted key, so checkout code can stay as it is.

The first sync reads the previous 30 days of charges, a scheduled job picks up new ones, and a webhook that TrackRev registers when the key allows it starts a sync on a successful charge, a refund or a completed Session.

For each charge the sync checks a vid key in the charge metadata, then the Session's client_reference_id or metadata, then the buyer's email, which the pixel binds to the visitor at signup or checkout.

A renewal inherits the first order's credit, and a charge with any refund is marked refunded on the next sync, so even a partial refund removes the whole charge.

Credit defaults to last touch, with first touch and linear available, and the window runs from 1 to 365 days, 30 by default. Six processors feed the same model: Stripe, Paddle Billing, Polar, Lemon Squeezy, Creem and Dodo Payments.

What does TrackRev cost, and when is another option better?

TrackRev pricing is simple: revenue figures need a paid plan, from Indie at $29 a month, and the free plan is link tracking only, with 50 links and 1,000 tracked events a month.

The pixel and key permission steps sit on our own Stripe integration page (2026).

Pick something else when your payments run through none of its 6 processors, when you want a standalone attribution product, or when you close a handful of sales a month.

In that case, a metadata write and a spreadsheet will answer the question.

SettingValue
First syncPrevious 30 days of charges
Attribution window1 to 365 days, 30 by default
Processors6
Free plan50 links, 1,000 tracked events a month, no revenue figures
Indie plan$29 a month, 1 workspace, 1 tracked domain

TrackRev settings used in this guide, October 2026.

Found this useful? Share it.

PostLinkedIn

Frequently asked questions

Muzahid Maruf — Founder of TrackRev.io

Written by

Muzahid Maruf

Founder, TrackRev.io & Contant.io

Muzahid Maruf founded TrackRev.io, SaaS affiliate software with no limit on tracked revenue, and Contant.io. He writes about affiliate programs.

Writes about Marketing attribution · Link tracking · Revenue analytics · SaaS growth

Run your affiliate program without a revenue cap.

Affiliate software for indie hackers and small SaaS teams: $29 a month flat, 0% fees, link tracking and revenue attribution built in. Free to start, no card.