Stripe Revenue Attribution: How to Tie Every Stripe Payment to Its Traffic Source
What Stripe records about marketing source and what it does not, the three ways to link a Stripe payment to the visit that caused it, code for Checkout Sessions and Subscriptions, and how to join the result to Meta and Google Ads spend by utm_campaign.

The short answer: As of October 8, 2026, Stripe does not attribute revenue to traffic sources on its own. It records the payment, the customer and whatever metadata you attach, not the ad or channel that brought the buyer. To attribute Stripe revenue, capture a visitor or session ID on your site and make Stripe carry it: put it in
metadataon the Checkout Session, PaymentIntent, Subscription or Customer, read the Checkout Session ID from a Payment Link's success URL, or match on email. The session already holds the UTM source and campaign, so the payment inherits them. Put the ID on the Subscription and Stripe copies it to every renewal invoice.
This guide covers the plumbing: what Stripe stores, the three ways to link a payment to a visit, the exact Stripe parameters to use, and what happens on renewals, refunds and disputes. If you already have that link working and want to read ROAS for subscription campaigns and set up ad naming, read how to track Meta and Google Ads ROAS through to Stripe subscriptions instead.
TL;DR
- Stripe has no attribution report. Payment Links forward UTM codes to your redirect URL, but Stripe does not tell you which campaign earned which dollar.
- The link between a payment and a visit is a session ID you store in Stripe
metadata, a Checkout Session ID on the success URL, or a shared email.- Metadata does not copy between Stripe objects, except in cases Stripe lists. Metadata on a Checkout Session does not reach the PaymentIntent or Subscription unless you use
payment_intent_data.metadataorsubscription_data.metadata.- Subscription metadata is copied onto each invoice the subscription creates. That is how renewals keep their original source.
- Join attributed revenue to Meta and Google Ads spend on
utm_campaignand date to get Stripe-verified ROAS.
What Stripe records about marketing source, and what it does not
Stripe is a payment system. Its objects describe money: a Customer, a Checkout Session, a PaymentIntent and its Charge, a Subscription and its Invoices, Refunds and Disputes. None of them has a field for referrer, landing page, ad click or campaign.
What Stripe does give you:
- Metadata. Up to 50 key-value pairs on supported objects, keys up to 40 characters, values up to 500 characters. Stripe does not use it, except with Radar, and customers do not see it unless you show it (Stripe Docs, Metadata). This is where an attribution ID goes.
- UTM pass-through on Payment Links. You can append
utm_source,utm_medium,utm_campaign,utm_termandutm_contentto a Payment Link URL. If the link's confirmation behavior is a redirect, those UTM codes are added to your redirect URL after payment (Stripe Docs, Track a payment link). Useful, but it only carries tags you put on the link yourself, not the source of the visit that preceded it. client_reference_id. A string up to 200 characters you can attach to a Checkout Session, including through a Payment Link URL. It is sent in thecheckout.session.completedwebhook (Stripe Docs, Track a payment link).
What Stripe does not give you: any record of where the buyer came from before they reached checkout, any report of revenue by channel or campaign, and any connection to ad spend. A buyer who clicks a Meta ad, reads three pages, leaves, returns from a Google search and then pays shows up in Stripe as a payment. The marketing context lives on your site, so attribution means joining the two.
Metadata does not travel on its own
This is where most homemade setups break. Stripe states that an object's metadata does not automatically copy to related objects. The exceptions it lists (Stripe Docs, Metadata):
| From | To | Behavior |
|---|---|---|
| PaymentIntent | Charge | One-time snapshot when the Charge is created |
| Payment Link | Checkout Session | One-time snapshot when the session is created |
| Subscription | Invoice | Copied to parent.subscription_details.metadata as a one-time snapshot |
| Subscription | Invoice Line Item | Line items of type subscription show the subscription's current metadata |
Stripe also lets you set metadata on an underlying object when you create the parent, through nested parameters. The ones that matter for attribution:
- Checkout Session to PaymentIntent:
payment_intent_data.metadata - Checkout Session to Subscription:
subscription_data.metadata - Payment Link to PaymentIntent and Subscription: the same two parameters on the Payment Link
So if your code puts metadata on a Checkout Session in subscription mode, the Subscription and its invoices do not get it. Your attribution tool has to read the session, or you have to set subscription_data.metadata too.
Three ways to link a Stripe payment to a visit
Every method answers the same question: which session on your site turned into this payment? Once you know the session, you know its UTM source, campaign, landing page and referrer.
| Method | How the link is made | Best for | Weak spot |
|---|---|---|---|
| Metadata with a session ID | Your backend writes the visitor's session ID into metadata on the Checkout Session, PaymentIntent, Subscription or Customer |
Custom checkout on the Stripe API | Needs a small code change on the server |
| Checkout Session ID on the success URL | A Payment Link redirects to your site with {CHECKOUT_SESSION_ID} in the URL, and your analytics reads it on the thank-you page |
Stripe Payment Links, no code | Breaks if the buyer pays on another device or never lands on the redirect page |
| Email match | Your site identifies the visitor by email, and the payment is matched on the same email | Stripe Elements, mobile and other custom flows | Fails when the buyer uses a different email at checkout |
Rank them in that order. Metadata is deterministic: the ID is either on the object or it is not. The success URL method depends on the browser. Email matching depends on people.
Method 1: metadata on Checkout Session, PaymentIntent, Subscription or Customer
First, read the session ID in the browser and send it to your server with the checkout request. With Humblytics the value is window.Humblytics.viewId, stored under the key humblytics_view_id (Humblytics Docs, Stripe API). Any analytics tool that exposes a session ID works the same way.
// Browser: send the current session ID with the checkout request
await fetch("/api/checkout", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
priceId,
humblytics_view_id: window.Humblytics.viewId,
}),
});
One-time payment with Stripe Checkout. Put the ID on the session and on the PaymentIntent the session creates:
const session = await stripe.checkout.sessions.create({
mode: "payment",
line_items: [{ price: priceId, quantity: 1 }],
success_url: "https://example.com/thanks?session_id={CHECKOUT_SESSION_ID}",
metadata: { humblytics_view_id },
payment_intent_data: {
metadata: { humblytics_view_id },
},
});
Subscription with Stripe Checkout. Use subscription_data.metadata so the ID lands on the Subscription, which then copies it onto each invoice:
const session = await stripe.checkout.sessions.create({
mode: "subscription",
line_items: [{ price: priceId, quantity: 1 }],
success_url: "https://example.com/welcome?session_id={CHECKOUT_SESSION_ID}",
metadata: { humblytics_view_id },
subscription_data: {
metadata: { humblytics_view_id },
},
});
Subscription created directly with the API:
const subscription = await stripe.subscriptions.create({
customer: customerId,
items: [{ price: priceId }],
metadata: { humblytics_view_id },
});
On the Customer, if you want every later payment from that customer to carry the same origin:
await stripe.customers.update(customerId, {
metadata: { humblytics_view_id },
});
Humblytics looks for the first humblytics_view_id across PaymentIntents, Invoices, Subscriptions, Checkout Sessions and Customers. When the ID is on a Subscription or Customer, future invoices and payments for that customer are attributed too, with no webhooks to build (Humblytics Docs, Stripe API).
One rule from Stripe applies here: metadata is only returned to requests made with a secret key, and it is redacted from publishable key responses (Stripe Docs, Metadata). Write it on the server. Never put card data or other sensitive values in it.
Method 2: Checkout Session ID on the Payment Link success URL
Payment Links are built in the Stripe Dashboard, so there is no server code to add metadata from. Instead, set the link's confirmation behavior to redirect to your site and include Stripe's {CHECKOUT_SESSION_ID} template in the URL. Stripe replaces it with the real session ID after payment. Your analytics script on the thank-you page reads that ID and ties the payment to the current browser session.
In Humblytics, open the Payment Link's After payment settings, choose to redirect to your website, and append:
?stripe_session_id={CHECKOUT_SESSION_ID}
Humblytics reads stripe_session_id from the URL, ignores duplicate events from repeated redirects, and works best when the buyer finishes on the same device and browser that started the visit (Humblytics Docs, Stripe Payment Links).
You can add Stripe's own UTM codes to the Payment Link URL as well. They help when you share the link directly in an email or a post, where there is no site visit to attribute.
Method 3: email match
For Stripe Elements, embedded flows, mobile purchases and anything else where you cannot easily write metadata or control the redirect, match on the buyer's email. Your site tells the analytics tool who the visitor is, and the tool matches that email to the Stripe payment.
In Humblytics that call is:
window.Humblytics.trackCustomer(customerEmail);
Call it right before or after you confirm the payment (Humblytics Docs, Stripe other methods). The match fails when someone browses logged out and pays with a different email, so treat this as the fallback.
How renewals inherit attribution
A subscription produces revenue for months. If attribution only covers the first payment, every channel that wins long-lived customers looks worse than it is.
The fix is where you store the ID:
- On the Subscription. Stripe copies subscription metadata onto each invoice the subscription creates, as a one-time snapshot in
parent.subscription_details.metadata(Stripe Docs, Metadata). Renewal invoice number twelve carries the same session ID as the first. - On the Customer. Stripe does not copy Customer metadata onto invoices, but an attribution tool that reads the Customer can apply it to every payment from that customer. Humblytics does this.
- Only on the first PaymentIntent or Checkout Session. Renewals arrive with nothing. Stripe will not copy it forward.
Two edge cases follow from "one-time snapshot". If you add or change subscription metadata later, invoices already created keep the old value. And a customer who cancels and starts a new subscription gets a new Subscription object, which needs its own ID or a Customer-level one.
For reading the numbers once renewals flow in, including the trial lag and cohort comparisons, see the subscription ROAS guide.
Refunds and disputes: the caveats
Attribution answers "which campaign produced this payment". Refunds and disputes change how much that payment is worth after the fact, and attribution setups handle them differently.
- Refunds can be full or partial, issued after a payment succeeds from the Dashboard or the Refunds API (Stripe Docs, Refunds). A partial refund means a campaign's revenue for a month can change after you have already reported it.
- Disputes arrive late. Card networks typically let cardholders open a dispute within 120 days of the original payment, and longer in some cases. When one is opened, Stripe debits your balance for the disputed amount plus a dispute fee (Stripe Docs, How disputes work).
- Gross and net are different numbers. Before you compare tools or compare a tool with your finance report, find out whether each one reports gross charges or net of refunds and disputes, and on which date a refund is counted: the original payment date or the refund date. Ask the vendor if the documentation does not say.
- Re-pull recent months. Because refunds and disputes land weeks after the sale, campaign revenue for the last few months is provisional. Compare closed months when you make budget decisions.
Joining attributed revenue to Meta and Google Ads spend
Once each payment has a session, and each session has a utm_campaign, ad spend is a join on two keys: campaign and date.
- Tag the ads. In Meta, set URL parameters with
utm_campaign={{campaign.name}}. Google Ads has no ValueTrack parameter for campaign name, so setutm_campaignper campaign in the final URL suffix. The subscription ROAS guide covers naming in detail, including why Meta names freeze at first publish. - Group Stripe revenue by campaign. Sum attributed revenue per
utm_campaignper day. - Pull spend by campaign. Export spend per campaign per day from Ads Manager and Google Ads, or connect the ad accounts to a tool that does it for you.
- Join and divide. Stripe-verified ROAS for a campaign is its matched Stripe revenue divided by its spend over the same dates.
Expect two lists of leftovers, and work them weekly:
- Spend with no revenue match. Usually a tagging error: the campaign name in
utm_campaigndoes not match the name in the ad platform. - Revenue with no spend match. Usually an email, partner or organic link that reuses a UTM value.
The Stripe number will not equal the platform's reported ROAS. Meta and Google credit conversions inside their own attribution windows, which can include view-through. Stripe-matched revenue is last touch on a site visit. Read them side by side.
In Humblytics, Meta and Google Ads connect read-only from Connectors. Spend, impressions and clicks come in per campaign, and sessions, Stripe trials and Stripe revenue are matched by utm_campaign, with the unmatched lists above built in. See Stripe integration and revenue attribution.
Stripe revenue attribution tools compared
Facts checked on vendor sites on October 8, 2026. Prices change; confirm on each vendor's pricing page.
| Tool | Stripe link | Ad spend and attribution | Published price |
|---|---|---|---|
| Humblytics | humblytics_view_id metadata, Payment Links session ID redirect, or email match; restricted read-only Stripe key |
Meta and Google Ads spend matched to Stripe revenue by utm_campaign; last touch on first-party UTM and session matching; A/B tests scored on revenue |
Business $79/month, Scale $279/month, Enterprise custom; 14-day trial |
| DataFast | Stripe via Checkout API, Payment Links or PaymentIntent | Meta Ads attribution by utm_campaign |
Starter $9/month, Growth $19/month at 10k events |
| Cometly | Stripe connected over OAuth with webhooks set up automatically | Meta, Google, LinkedIn, TikTok and more; first touch, last touch and multi-touch models | Not published on the pricing page; see cometly.com/pricing |
| Attribution | Stripe integration listed | Multi-touch: first and last touch, linear, time decay, position based | Pro from $399/month; Shopify from $199/month |
| Hyros | Stripe listed as a payment processor integration | Ad tracking and attribution | From $230/month for up to $20K tracked monthly revenue |
How to choose:
- Bootstrapped product, Stripe only, want to know which source pays: DataFast is the cheapest entry point.
- Paid acquisition across many ad platforms, want multi-touch models: Cometly, Attribution or Hyros. Our Triple Whale and Hyros alternatives for SaaS covers that group.
- Meta or Google Ads into your own landing pages, and you want to fix the pages that lose money: Humblytics, because the same script runs the analytics, heatmaps and A/B tests, and a test result resolves to Stripe revenue rather than to a click. Compare directly in Humblytics vs DataFast.
Humblytics limits, stated plainly: revenue attribution works with Stripe and Foxy only, ad spend comes from Meta and Google Ads only, and attribution is last touch, not multi-touch. For store checkouts, see ecommerce revenue attribution.
Setup checklist
- Analytics script on every page that can lead to checkout
- Session ID sent from the browser to your checkout endpoint
-
subscription_data.metadataorpayment_intent_data.metadataset when creating Checkout Sessions, not only sessionmetadata - For Payment Links: redirect confirmation with
{CHECKOUT_SESSION_ID}in the URL - Email match as a fallback for Elements and mobile
- Every Meta and Google Ads campaign carrying
utm_campaign - Stripe connected with a restricted, read-only key
- Weekly review of unmatched spend and unmatched revenue
- Refund and dispute treatment confirmed with your tool before comparing to finance
Ready to try it on your own Stripe account? Start a 14-day trial, connect Stripe with a restricted key, and add the metadata to one checkout first.
Sources and freshness
- Stripe Docs, Metadata, retrieved October 8, 2026. Supports metadata limits, secret-key-only access, the rule that metadata does not copy between objects, the listed copy exceptions including Subscription to Invoice, and the
payment_intent_data.metadataandsubscription_data.metadataparameters. - Stripe Docs, Track a payment link, retrieved October 8, 2026. Supports UTM pass-through to the redirect URL and
client_reference_id. - Stripe Docs, Refund and cancel payments, retrieved October 8, 2026. Supports full and partial refunds.
- Stripe Docs, How disputes work, retrieved October 8, 2026. Supports the typical 120-day dispute window and the balance debit plus dispute fee.
- Humblytics Docs, Stripe API, Stripe Payment Links and Stripe other methods, retrieved October 8, 2026. Supports
humblytics_view_id, the objects checked, the restricted key, thestripe_session_idredirect andtrackCustomer. - DataFast, Attribute Stripe revenue to X posts and pricing, retrieved October 8, 2026. Supports Stripe setup methods, Meta Ads attribution by
utm_campaign, and Starter and Growth prices. - Cometly, Stripe integration and pricing, retrieved October 8, 2026. Supports OAuth connection, attribution models, ad platforms and the starting seat price.
- Attribution, pricing and Stripe integration, retrieved October 8, 2026. Supports plan prices, attribution models and the Stripe integration.
- Hyros, documentation, retrieved October 8, 2026. Supports Stripe as a listed integration. Pricing from hyros.com/pricing-ai-tracking, retrieved October 8, 2026.
Stripe and vendor interfaces change. Check the linked pages before you rely on a specific setting or price.