Paddle affiliate tracking works by carrying the affiliate’s referral into Paddle Checkout as custom data, then reading it back off Paddle’s signed webhooks when money actually moves. Paddle doesn’t do any of this itself (it’s a Merchant of Record, not an affiliate platform), so a tracking tool supplies the links, the commission math, and the payouts, while Paddle supplies two genuinely good primitives: a customData field that sticks to the transaction for life, and webhooks that report every sale, renewal, refund, and chargeback.
This article walks the full round trip: the click, the handoff into Checkout, the webhook that comes back, and the clawbacks when refunds happen. I’ll name the exact fields and events at every step, because attribution is a plumbing subject, and vague plumbing is how programs end up with affiliates asking where their commission went.
One useful thing to know up front: I wrote Rekomi’s Paddle webhook handler personally, so what follows describes code I maintain, not a spec I skimmed. That also means you can hold me to it – every claim below checks out against Paddle’s developer docs, and I’d encourage you to look.
Here’s the round trip:
The click: a one-line script stores the affiliate’s link slug in the visitor’s browser for 90 days and logs the click server-side.
The handoff: your checkout call passes
customData: { rekomi_ref: ... }, and Paddle keeps that value on the transaction and the subscription it creates.The money: every
transaction.completedwebhook (first sales and renewals alike) carries the custom data back, signature-verified, and the commission records on the pre-tax amount.The cleanup: refund and chargeback adjustments reverse the commission automatically once Paddle approves them.
Does Paddle track affiliates on its own?
No. Paddle handles checkout, billing, and the Merchant of Record tax burden, and it stops there on purpose: no referral links, no commission engine, no affiliate dashboard. What it does provide is exactly the raw material tracking needs, which is why every serious affiliate tool on Paddle is built the same basic way you’re about to see.
Two boundaries so we’re reading the same article. The program-building half (commission structure, recruiting, payout rails, the W-9s) is covered in the Paddle affiliate program guide, and if you’re still choosing software, the best affiliate software for Paddle roundup compares six options honestly. This page is about what happens under the hood once a tool is connected.
The click half: everything starts on your site
Your affiliate shares a link like yoursite.com?via=jess. A small script in your site’s <head> (Rekomi’s is literally one line) does two jobs the moment the page loads:
- It stores the referral in the browser. The slug
jessgoes into local storage with a 90-day expiry, plus a first-party cookie when a custom tracking domain is set up. The script recognizes 19 attribution params by default (?via=,?ref=,?fpr=, and the other dialects the industry has invented), so links built for a previous tool survive a migration. - It logs the click server-side. Referrer, UTM params, an optional sub-ID. That’s what later answers the affiliate’s favorite question: which of my posts actually converts?
If the same visitor clicks two different affiliates’ links, the newer click overwrites the older one. Last click wins, which is the convention affiliates already expect.
Also, notice that Paddle hasn’t entered the picture yet. The referral just sits in the browser, waiting for a buy button.
The handoff: rekomi_ref rides in on customData
Here’s how it works: when your site opens Paddle Checkout, you attach the stored referral to the checkout’s custom data under one exact key, rekomi_ref.
const referral = window.Rekomi && window.Rekomi.getReferral();
Paddle.Checkout.open({
items: [{ priceId: 'pri_xxx', quantity: 1 }],
customData: { rekomi_ref: referral || null },
});
One key, a few lines, and the handoff is done! Paddle then does something quietly excellent with it: custom data passed at checkout is held on the transaction, copied to the subscription that transaction creates, and copied back onto every transaction the subscription generates later, renewals and upgrades included. Stamp the slug once and it reappears on every payment, which you can confirm in Paddle’s custom data docs.
One timing quirk to respect: Paddle Checkout runs in an iframe your page scripts can’t reach into, so the referral must already be captured before the buyer opens the overlay. The async loader is nearly always fast enough; if a cold visitor can hit “Buy” within the first second of a page load and you see misses, defer the overlay open by ~200ms.
The webhook half: six events, one of them money
On the Paddle side, you point a notification destination at the tracking tool’s webhook URL and enable six events: transaction.completed, subscription.created, subscription.updated, subscription.canceled, adjustment.created, and adjustment.updated. There’s no relay server to build – Paddle talks straight to the tool.
The money event: transaction.completed. On Paddle, everything that charges a card is a transaction: first purchases, subscription renewals, one-time add-ons. That means this single event carries every dollar. When it arrives, the tool reads custom_data.rekomi_ref and matches the slug to an approved affiliate. No match? It checks whether this Paddle customer_id already has an attributed purchase, the customer-history net that catches edge cases, and failing that the sale records as unattributed and waits in a review queue rather than guessing.
The lifecycle events: subscription.created writes a $0 signup row so your dashboard shows the referred subscription from day one, and subscription.updated / subscription.canceled keep the customer’s status current. None of them move money; the transactions do.
The cleanup events: the two adjustment events, which earn their own section below.
And before any of that runs, every delivery gets authenticated. Paddle signs each webhook with a Paddle-Signature header: a timestamp plus an HMAC-SHA256 of {timestamp}:{raw body} computed with the destination’s pdl_ntfset_ secret, a format Paddle’s verification docs spell out exactly. Rekomi verifies that signature with a constant-time comparison, rejects events outside a 5-minute replay window, and processes each event_id exactly once, so a retried delivery can never double-credit a commission. I genuinely enjoy this layer of the system: it’s the part nobody ever sees, and it’s the reason the numbers can be trusted.

Renewals: one click, recurring commissions
So, what happens in month two? Paddle generates a renewal transaction, the subscription’s custom data gets copied onto it, and transaction.completed arrives looking almost identical to the first sale. The tool credits the same affiliate again, automatically, every cycle.
The math is the fun part. A $49/mo product with a 20% recurring commission pays the affiliate $9.80 on the first sale and $9.80 every renewal after it: twelve months of retention turns one referred click into $117.60. Nobody stamps anything twice, and there’s no job re-checking cookies. The metadata inheritance does all the work!
Even if custom data somehow went missing on a renewal, the customer-history fallback would still catch it: same customer_id, same affiliate.
Refunds, chargebacks, and the Merchant of Record wrinkle
Money going back out is modeled as adjustments in Paddle Billing, and this is where a careful implementation separates itself from a naive one. Three details matter:
- Only real money-out claws back. Paddle adjustment actions include refund, credit, chargeback, and a few reversal variants. Only refunds and chargebacks reverse commission; a credit note isn’t cash leaving.
- Only approved adjustments claw back. Paddle creates most refunds as
pending_approvaland reviews them before approving or rejecting. Clawing back at creation would punish an affiliate for a refund request that ends up rejected, so the commission reverses only when the status hitsapproved. Listening to bothadjustment.createdandadjustment.updatedis what catches that transition, and each adjustment applies exactly once no matter how many times Paddle delivers it. - Partials reverse proportionally. A $15 refund on a $60 sale claws back exactly a quarter of the commission, and the affiliate’s ledger shows the line item.
Now the tax wrinkle. Paddle is a Merchant of Record: it collects the buyer’s VAT or sales tax itself, and that tax was never your revenue. So commissions calculate on the pre-tax amount, the transaction total minus its tax, net of any customer-balance credit Paddle applied. Concretely: a checkout that reads $60 with $10 of VAT inside it earns a 25% affiliate $12.50 (25% of $50), not $15. Refund clawbacks subtract the refund’s own pre-tax share too, so the reversal stays exactly symmetric with what was credited. Your affiliates earn on the sale; the buyer’s tax authority stays out of the equation entirely.
Why coupon codes don’t attribute on Paddle
No sugarcoating this one: on Rekomi’s Paddle rail, an affiliate discount code won’t attribute a sale by itself. The cause is a Paddle payload detail plus an honest trade-off on our side. Paddle’s webhook reports the discount as a discount_id (a dsc_... identifier), not the code the buyer typed, so mapping it back to an affiliate’s code would mean calling the Paddle API while recording the conversion. I went back and forth on that trade-off and landed firmly against it: Rekomi’s recording path makes zero Paddle API calls by design, which means a Paddle API outage can never stop verified sales from being recorded. Reliability won, and honestly it was a no-brainer.
So here’s what is true on Paddle: links carry the attribution, customer history backs them up, and a code-only promotion (an influencer saying “use JESS10” with no click behind it) attributes only if the buyer clicked earlier or you credit it manually from the review queue. If code-based attribution is the heart of your program, Stripe is the gateway where that works fully; on Paddle, treat coupons as a discount, not a tracker.
A note on Paddle Classic
Everything above describes Paddle Billing. Classic is an earlier product generation with a different webhook contract: it signs with p_signature and has no customData in this shape. Rekomi supports Billing only. If you’re on Classic and planning the migration, budget for redoing the tracking wiring as part of the move rather than assuming it carries over.
What your affiliates watch while this runs
The plumbing’s payoff is a boring, trustworthy dashboard. Each affiliate sees their clicks, their conversions landing as the webhooks arrive, and a pending balance that renewals keep nudging upward. Refund reversals show up as itemized lines rather than silent deductions, which does more for affiliate trust than any FAQ page could. And when balances become payouts, Rekomi moves the money itself in 165+ countries (Stripe Express in 42, bank deposits in 60 more, PayPal in 66 more), tax forms handled.
Quick answers on Paddle affiliate tracking
Does Paddle have built-in affiliate tracking?
No. Paddle provides custom data fields and signed webhooks; affiliate links, commission math, and payouts come from a tracking tool built on top of them.
Which Paddle webhook event triggers a commission?
transaction.completed. It fires for first purchases and every renewal, carries the checkout’s custom data, and reports amounts as integer minor-unit strings, so “4900” means $49.00 with no conversion needed.
Do subscription renewals keep paying the affiliate?
Yes. Paddle copies checkout custom data to the subscription and back onto each renewal transaction, so every cycle credits the original affiliate, with customer history as the fallback.
Can I track Paddle affiliates with coupon codes?
No, not as a standalone signal. Paddle’s webhooks report a discount_id rather than the redeemed code, so coupon-only sales don’t attribute on Paddle. Use links as the primary mechanism.
When does a refund claw back the commission?
When Paddle approves the adjustment. Pending refunds reverse nothing, rejected ones never do, and approved refunds and chargebacks reverse the commission proportionally on the pre-tax amount.
Run the loop once in sandbox
Trust in tracking comes from watching it catch a sale, and Paddle makes the rehearsal super easy. Connect a Paddle sandbox account to the Paddle integration, click your own test link, run a sandbox checkout with rekomi_ref stamped, and watch the conversion land with the right affiliate’s name on it. Sandbox even auto-approves refunds every ten minutes, so you can watch the clawback fire too. Fifteen minutes, and the round trip stops being an article you read and becomes a thing you’ve seen run!
