Stripe affiliate tracking: how referral attribution works end to end

Updated · 6 min read

Stripe affiliate tracking stores the partner’s referral code when a visitor clicks their link, attaches it to the Stripe customer or subscription at checkout, then uses Stripe webhooks to turn each paid invoice into a commission. Refund webhooks reverse those commissions, and coupon codes can attribute customers who never clicked a link.

The chain from click to commission

Stripe knows who paid and how much, but it has no idea which partner sent that customer. Affiliate tracking is the job of carrying one small piece of information, the partner’s referral code, from the moment someone clicks a link to the moment Stripe records a payment. Every tracking tool does some version of these five steps:

  1. 1

    Click

    A visitor follows a partner link such as example.com/?ref=JANE. A script on your site reads the code and records the click.

  2. 2

    Store

    The script saves the code in a first-party cookie so it survives the visitor browsing around, leaving and coming back within the attribution window.

  3. 3

    Sign up

    When the visitor creates an account, the stored code is linked to their user id in your app.

  4. 4

    Link to Stripe

    At checkout, your server attaches the code and the user id to the Stripe Checkout Session, customer or subscription.

  5. 5

    Pay

    Stripe sends webhooks for each paid invoice and refund. The tracking tool looks up which partner owns that customer and creates or reverses a commission.

If any link in this chain breaks, the payment still goes through, but the partner is not credited. Most “my referral wasn’t tracked” complaints come from step 4, where the code never reaches Stripe.

Cookies and the attribution window

The attribution window is how long after a click a sign-up still counts for the partner. Thirty days is the most common default for SaaS, and 60 or 90 days is typical for products with long evaluation cycles. The window only needs to cover the time between click and sign-up; once the customer is linked to a partner, recurring commissions follow the customer, not the cookie.

Two rules decide who wins when several partners are involved. Last click credits the most recent link a visitor followed before signing up. First click credits whoever reached them first. Whichever you choose, the common practice is to lock attribution once a customer exists, so that a later click on another partner’s link does not move an existing paying customer. See affiliate attribution and cookie duration for the trade-offs.

Linking the Stripe customer to the partner

Stripe gives you two places to carry the referral: client_reference_id and metadata. They do different jobs, and a robust setup uses both.

Where the referral travels in Stripe
FieldWhere it livesWhat to put in it
client_reference_idCheckout Session onlyYour own user or account id, so the payment can be matched to the sign-up
metadata on the Checkout SessionCopied into checkout.session.completedThe referral code, for the sign-up event
subscription_data.metadataStored on the subscriptionThe referral code and your user id, so every later invoice carries them
metadata on the customerStored on the Stripe customerThe same, when you create customers without Checkout

The subscription metadata matters most. A Checkout Session happens once, but invoices keep arriving for months, and each invoice webhook includes the subscription’s metadata. Putting the code there means every renewal can be attributed without a lookup.

The browser side is simple: read the stored code from the tracking script and send it to your server along with the checkout request. The server then creates the session with client_reference_id set to your user id, the code in metadata, and the same values in subscription_data.metadata. Never trust a code for anything beyond attribution; it is a label, not a credential.

In Affiliatops this is how the Stripe integration works: the tracker keeps the code in a first-party cookie for the program’s attribution window (30 days by default), the first code that resolves to an active partner owns the customer, and the integration reads the affiliatops_ref and affiliatops_customer_id metadata keys from Stripe’s webhooks. The integration is webhook-only, so it never needs a Stripe API key. The exact checkout snippet is in the docs.

The Stripe webhooks that create commissions

Webhooks are what make recurring commissions automatic. You add an endpoint in the Stripe dashboard, choose the events to send, and the tracking tool verifies each request with the endpoint’s signing secret before trusting it.

Events that matter for affiliate tracking
Stripe eventWhat it means for the partner
checkout.session.completedSign-up: links the customer to the referral code in the session
customer.subscription.createdTrial started or subscription created; can pay a sign-up or trial bonus
customer.subscription.updated / deletedPlan changes, pauses and cancellations; stops future commissions after cancel
invoice.paidA real payment: creates the commission for the first payment and each renewal
invoice.payment_failedNo commission; useful for spotting referred customers at risk of churn
invoice_payment.paidNo money. Sent by Stripe API 2025-05-28.basil and later; it ties the payment to its invoice, so a refund can find the commission to reverse
charge.refundedReverses the commission for the refunded payment, fully or in part

Three details prevent most double counting and phantom commissions:

  • Pick one payment event. invoice.paid and invoice.payment_succeeded fire for the same payment; handling both pays the partner twice.
  • Skip zero-amount invoices. Trials and 100% off coupons produce invoices marked paid at $0, which are not revenue.
  • De-duplicate by the Stripe event id. Stripe retries webhooks, so the same event can arrive more than once.

For refunds, note that charge.refunded carries the charge’s total refunded so far, not just the latest refund. If a customer receives two partial refunds, the commission reduction must be based on the difference, or the second refund will be counted twice.

Attributing sales by coupon or promotion code

Coupon codes let partners earn from audiences that never click a link: podcast listeners, video viewers, people who heard a recommendation in person. The customer types the partner’s code at checkout, and the code itself identifies the partner.

The catch with Stripe is that the customer-facing promotion code is not always visible in webhook payloads. Stripe usually sends it as a promo_ id rather than the text the customer typed, unless the object was expanded. There are two reliable ways around this:

  • Copy the code the customer entered into the session and subscription metadata when you create the checkout, so the webhook carries it as text.
  • Create the Stripe coupon with an id or name equal to the partner’s code, so it can be matched even without metadata.

Decide in your terms which wins when a customer has both a referral cookie and a typed code. Many programs let the typed code win, since it is the clearer signal of intent, but only for customers not already attributed to another partner.

Common pitfalls and how to handle them

Why referrals go missing
PitfallWhat happensFix
Cross-deviceClicks on a phone, signs up on a laptop; no cookie on the laptopOffer partner coupon codes; let partners claim a customer with evidence you can verify
Ad blockers and privacy toolsThe tracking script or its requests are blockedServe the script from your own domain where possible; capture ?ref on your server as a backup
TrialsCheckout happens days after the click, or payment weeks after sign-upAttach the code at sign-up, not only at payment; commissions come from invoice.paid later
Code not passed to StripePayment arrives with no referral; partner not creditedAlways set subscription_data.metadata; test with a real partner link
Marketing site and app on different domainsCookie set on one domain is not readable on the otherPass the code in the sign-up URL or share the cookie across subdomains
Customer created outside CheckoutNo session, so no client_reference_idSet the same metadata on the Stripe customer or subscription

Finally, test the whole chain in Stripe test mode before inviting partners: click a partner link, sign up, pay with a test card, issue a partial refund, then cancel. You should see a sign-up, a commission, a reduced commission and a cancelled subscription, each against the right partner. Once that works, the SaaS demo shows what the resulting dashboard looks like.

Frequently asked questions

Does Stripe have built-in affiliate tracking?

No. Stripe records customers, subscriptions and payments, but it does not track referral links or calculate partner commissions. You need a tracking script plus a tool or your own code that listens to Stripe webhooks.

How do I pass a referral code to Stripe Checkout?

Read the stored referral code in the browser, send it to your server with the checkout request, and create the Checkout Session with the code in metadata and in subscription_data.metadata. Set client_reference_id to your own user id.

Which Stripe webhook should create affiliate commissions?

invoice.paid is the usual choice for subscriptions, because it fires for the first payment and every renewal. Do not also handle invoice.payment_succeeded for the same payments, and ignore invoices paid at $0.

Can affiliates be tracked with Stripe promotion codes?

Yes, but webhooks often carry only the promotion code’s id, not the text. Save the typed code in checkout metadata, or create the coupon with an id or name that matches the partner’s code.

How are affiliate commissions reversed when a Stripe payment is refunded?

The charge.refunded webhook identifies the refunded payment and the amount refunded so far. The tracking tool cancels the commission on a full refund, or reduces it in proportion on a partial refund, and deducts already-paid commissions from the next payout.

Run your partner program on Affiliatops

Recurring commissions, refund holds and clawbacks, and a branded partner portal, from $19 a month. Try it free for 14 days.

Start free trial