For brands
Connect Stripe
Add the partner's ref_code and vp_click to your Checkout Session metadata, then point a webhook from your own Stripe account at your program's address. ViralPayouts reads paid checkouts, subscription renewals and refunds. Stripe is used for tracking only: no payouts go through it.
1. Pass the click to Checkout
Read ref and vp_click from the landing address when the visitor arrives, keep them, and add them to the Checkout Session you create:
const session = await stripe.checkout.sessions.create({
mode: 'payment', // or 'subscription'
line_items: [{ price: 'price_123', quantity: 1 }],
success_url: 'https://yourshop.com/thanks',
metadata: {
ref_code: refFromLandingUrl, // the ?ref= value
vp_click: clickFromLandingUrl, // the ?vp_click= value
vp_coupon: couponCode, // optional: a partner coupon the buyer used
},
});vp_ref is accepted in place of ref_code, and client_reference_id is used as the referral code when neither is set.
2. Add the webhook in Stripe
- In the console, open the program's Integration tab and copy its Stripe webhook address:
POST /api/stripe/webhook/<program id>. - In your Stripe dashboard, add a webhook endpoint at that address for
checkout.session.completed,charge.refunded,charge.dispute.created,charge.dispute.closedand, if you sell subscriptions,invoice.paid. - Stripe shows a signing secret for the endpoint (it starts with
whsec_). Paste it into the Integration tab. Only its last 4 characters are shown afterwards.
What each event does
| Stripe event | Becomes | Notes |
|---|---|---|
checkout.session.completed | A sale | Only when payment_status is paid. The order id is the payment intent. The buyer's email is used for the self-referral check, then stored only as a keyed hash and a masked form. |
invoice.paid | A renewal sale | Only when billing_reason is subscription_cycle. Credited to the partner who brought the subscription's first payment, inside the renewal period. |
charge.refunded | A refund | Matched on the payment intent. Reduces the commission in proportion. |
charge.dispute.created | A chargeback opened | The commission is held while the chargeback is open, so it is not paid out. |
charge.dispute.closed | A chargeback decided | Lost: the commission is reversed in full, as for a full refund. Won: the hold is lifted. |
A sale reported to a program's address is only ever credited inside that program, and a refund only touches that program's orders.
Check it works
Complete a real or Stripe test-mode checkout. The event appears on the Integration tab within seconds, matched or unmatched with the reason. The first signed event also satisfies the go-live check. See Test sales.
Something here does not match what you see in the product? Email max@viralpayouts.com.