Affiligato

Tracking

How payments find their affiliate

The order an affiliate system uses to credit a payment — customer id, email, promo code, metadata — and how to set up Stripe, Paddle and Chargebee.

Affiligato team,

A click is a promise; a payment is the fact. An affiliate system’s real job is to look at each payment your billing provider reports and decide which partner, if any, it belongs to. Knowing how that decision is made tells you exactly what to set up.

The events that matter

Every billing provider can notify you of payments with a webhook. The ones an affiliate system needs are:

  • A successful payment — in Stripe, invoice.paid; in Paddle, transaction.completed; in Chargebee, payment_succeeded.
  • Refunds and credits — Stripe credit notes and refunded charges, Paddle adjustments, Chargebee payment_refunded.
  • Subscription changes — trials starting, plans changing, cancellations — so partners can see where each customer stands.

Each event is signed by the provider, so the system can reject forgeries, and each has an id, so a retried webhook is applied once.

The matching order

For each payment, the system looks for a referral in a fixed order and stops at the first match:

  1. The billing customer id. If your app reported the signup with the Stripe, Paddle or Chargebee customer id, the payment matches exactly. This is the most reliable path.
  2. The customer’s email. If the signup was reported with an email, a payment from a customer with the same email matches.
  3. A partner’s promo code. If the payment used a discount code assigned to a partner, and no one else referred this customer, the code credits that partner.
  4. Checkout metadata. If the referral code was attached to the invoice, the transaction’s custom data or the customer record at checkout, it identifies the partner directly.

Once a customer is matched, they stay with that partner. Every later payment from the same customer is credited the same way, until the commission window ends.

Set up Stripe

  • Add a webhook endpoint for invoice.paid, credit_note.created, charge.refunded and the customer.subscription.* events.
  • Report signups with the Stripe customer id where you can.
  • Put the referral code in the invoice or customer metadata, for example affiligato_ref, when you create the subscription.
  • For Payment Links, the Pricing Table and Buy Buttons, pass the referral as the client_reference_id, so the completed checkout session carries it.

A note on refunds: on recent Stripe API versions, refunded charges no longer name their invoice directly. Issuing refunds as credit notes keeps the link to the original invoice, and so to the commission.

Set up Paddle

  • Add a notification destination for transaction.completed and adjustment.updated.
  • Pass the referral code in the checkout’s custom data, along with the customer’s email.
  • Approved refund adjustments reverse the commission, fully or in proportion.

Set up Chargebee

  • Add a webhook with basic authentication, for payment_succeeded and payment_refunded.
  • Store the referral code in a customer custom field.
  • Coupons on the invoice can be matched against codes assigned to partners.

Billing elsewhere

If your billing runs on something else, report signups, sales and refunds from your server through the affiliate system’s API. Send your own payment id with each sale, so it is counted once however often you retry.

Mobile apps

App purchases are reported by the store, not your server. A subscription platform such as RevenueCat forwards purchases, renewals and refunds from the App Store, Google Play and web checkouts as webhooks; set a subscriber attribute to the partner’s code, or the subscriber’s email, and the same matching applies.

Why a payment goes uncredited

When a partner says a customer of theirs was not credited, the cause is almost always one of these:

  • The signup was never reported. The tracking script stored the referral, but the app never called the signup function, so there was no referral to match the payment to.
  • Different identifiers. The signup was reported with a work email, and the payment came from a customer with a personal one; or the billing customer was created before the signup was reported and its id was never sent.
  • The webhook did not arrive. It was pointed at the wrong URL, subscribed to the wrong events, or its signing secret was mistyped, so every delivery was refused.
  • Outside the window. The click was older than the cookie window, or the lead lifetime had passed before the first payment.
  • Someone else got there first. Another partner’s referral, or a code assigned to another partner, matched first.

Each of these can be checked from the integration log and the customer’s record, and each points to a concrete fix.

Test the whole path

Use your provider’s test mode:

  1. Open a partner link in a private window.
  2. Sign up in your app.
  3. Pay with a test card.
  4. Confirm the commission appears, then refund the payment and confirm it is reversed.

If the commission does not appear, check in order: was the signup reported, did the webhook arrive, and does the customer id or email on the payment match the one on the signup. Nearly every missed commission is one of those three.

Doing this in Affiligato

Each integration has its own page in the app with the endpoint URL to paste into your provider and a place for its secret. The integration log keeps 30 days of every webhook and API write with its outcome, so when a commission is missing you can see whether the event arrived and what was done with it. The overview shows when your script and your webhook last reached the program.

The matching order above is exactly what the conversions core applies, for Stripe, Paddle, Chargebee, RevenueCat and the conversions API alike, and each provider event is applied once however often it is retried.

Sources

Launch your partner program today.

Fourteen days free, no card needed. Most programs are live in an afternoon.