Stripe

Track sales from Stripe Checkout and Payment Links with a webhook – one-off purchases, subscriptions and refunds.

Time
about 15 min · needs a developer
You need
The Stripe dashboard (Workbench) and the code that creates Checkout
View as Markdown

If your customers pay through Stripe Checkout or Payment Links on your own site, Stripe reports each sale straight to us through a webhook. That covers one-off purchases, subscriptions and renewals. You don't need a tracking script on the page to report the sale – but the click ID has to reach Stripe, and that takes a little code.

Before you start

  • Access to your Stripe dashboard (Workbench).
  • Access to the code that creates Checkout Sessions – or to your Payment Links. This is usually a job for your developer, and Setup can send the guide straight to them.
  • Your store ID. The address under Program → Setup already has it filled in; on this page it appears as the placeholder DIN_BUTIK.

In Setup, Stripe has three steps: Choose platform, Stripe setup (webhook and signing secret) and Confirm (the test).

We never ask for your Stripe API key. All you give us is the webhook's signing secret, which can only confirm that a message really comes from you.

Step 1: Create the webhook

In Stripe, go to Workbench → Webhooks → Create an event destination.

  1. Choose Your account and the Snapshot payload format – not Thin, which Stripe suggests. Thin leaves out the order data, and without it the sale can't be recorded.
  2. Select the events (listed below).
  3. Choose Webhook endpoint and use this URL:
Webhook URLTekst
https://app.affilyflow.com/api/stripe/webhook/DIN_BUTIK

Always:

  • checkout.session.completed
  • checkout.session.async_payment_succeeded
  • charge.refunded
  • charge.dispute.created

Only for subscriptions:

  • invoice.payment_succeeded
  • invoice_payment.paid
  • customer.subscription.deleted

invoice_payment.paid gives us the payment reference on subscription payments, so a refund or dispute on a renewal can be matched to the sale – without it, the commission stays in place.

Step 2: Add the signing secret

Copy the endpoint's Signing secret (it starts with whsec_) and paste it under Setup → Stripe in Affilyflow. Without it, we reject every event. Don't send it by email – the store owner pastes it in themselves.

If you also want to test in Stripe's test mode, create a matching event destination in test mode and paste its signing secret into the same field, separated by a space. We try both.

Step 3: Pass the click ID along

Affiliates send customers to your site with ?afid=… in the address. Store the click ID in a cookie on your main domain when the customer lands, so it survives the move from www to, say, an app subdomain:

Every pageJavaScript
// On every page: keep the click ID from ?afid= in a cookie on your main domain (90 days)
const afid = new URLSearchParams(location.search).get('afid');
if (afid && /^c_[A-Za-z0-9_-]{4,64}$/.test(afid)) {
  const domain = location.hostname.split('.').slice(-2).join('.');
  document.cookie = 'af_click=' + afid + '; domain=.' + domain + '; path=/; max-age=7776000; SameSite=Lax; Secure';
}
// On your server, read the af_click cookie from the request when creating the Checkout Session.

Then pass it as client_reference_id when you create the Checkout Session:

client_reference_idJavaScript
// stripe.checkout.sessions.create({ ...,
client_reference_id: req.cookies.af_click || undefined,
// })
  • The domain is taken as the last two parts of the hostname. If your domain has more parts (such as .co.uk), change it to your own.
  • If you create the session on the server, the browser has to send the cookie along with the request.
  • If you use Payment Links, add the click ID to the link as ?client_reference_id=…. The easiest way: put the tracking code on every page – it stores the click itself and adds it automatically to every link to buy.stripe.com, including links rendered later.

Afterwards, check in Stripe that client_reference_id on the checkout.session.completed event is "c_…" and not null. If it is null, the click ID never arrived – check the cookie domain.

Test

The test is in the Confirm step in Setup. You can test in Stripe's test mode without moving any money:

  1. Press Open test link in Setup.
  2. Complete a one-off purchase in Stripe Checkout with a test card (e.g. 4242 4242 4242 4242) in the same browser. The webhook also has to receive test events – create it in test mode, or create a matching one for testing (see step 2).
  3. The live test in Setup shows the test click and the purchase as a test sale: no commission, no fee, no emails.

In test mode, only a Checkout purchase made after a click on the test link is recorded – everything else in test mode is ignored. If you would rather test in live mode, buy something cheap with a real card after opening the test link, and refund it in Stripe afterwards.

Without a test, tracking is confirmed on its own by the first affiliate purchase. Your program becomes visible to affiliates once we have received the first event from your webhook.

What Stripe reports

  • The amount. Commission is calculated on the payment amount excluding VAT, taken directly from Stripe.
  • Currency. Sales in other currencies are converted to Danish kroner at the ECB rate at the time of the sale, and the rate is locked on the sale.
  • Subscriptions. Turn on Recurring commission (subscriptions) under Program, and every renewal automatically earns commission for as long as the program says. The same invoice can never count twice. Subscriptions that are not created through Stripe Checkout are not covered.
  • Trial periods. If the subscription starts with a free trial, the sale is only created at the first paid invoice. A renewal of DKK 0 earns no commission.
  • Refunds. A full refund or a dispute rejects the sale, and the affiliate is notified. A partial refund reduces commission and fee in the same proportion. If the program pays a fixed amount per sale, a partial refund doesn't change it. For subscriptions, this requires invoice_payment.paid on the webhook – without it, a refund of a renewal can't be matched to the sale.

Personal discount codes

A personal discount code earns the affiliate commission, even without a click. On Stripe, this only works for one-off payments – subscriptions still need a click.

Stripe only sends us the coupon's ID, not the promotion code the customer typed. So:

  1. Create the code under Program → Discount codes in Affilyflow, and choose the affiliate under Who is the code for?.
  2. Create the coupon in Stripe with the same ID as the code – e.g. ANNA10. The promotion code the customer types can have the same name.

If the customer has a valid click, the click always wins. If the click has expired, or there is no click, the sale is credited to the affiliate the coupon ID belongs to. The webhook address contains your store ID (as above), so we know which store the code belongs to.

Missing something?

Write to us – we answer quickly, and the page gets fixed.

Contact support