Affiliate tracking for subscription products built on Stripe: affiliates get links, conversions are attributed, and commissions are calculated from Stripe events.
Build me affiliate tracking that replaces Rewardful: referrals attributed correctly, commissions computed from real payments, and nothing paid out on money that came back. STACK - Node 20+ with Fastify - SQLite through better-sqlite3, WAL mode - Your payment processor's webhooks as the source of truth for money - Caddy in front THE DATA MODEL - affiliates: id, name, email, code, status, payout_method_json, tax_form_status, created_at, approved_at - programs: id, name, commission_kind, commission_value, recurring_months, cookie_days, min_payout_cents, currency, terms_version - links: id, affiliate_id, program_id, destination, token, created_at - visits: id, link_id, visitor_hash, referrer_host, landing_path, country, device, bot, at - referrals: id, affiliate_id, program_id, visit_id, customer_external_id, email_hash, attributed_at, expires_at, status - commissions: id, referral_id, invoice_external_id, gross_cents, commission_cents, currency, status, earned_at, matured_at, voided_at, void_reason, payout_id — status is pending, mature, paid, or void - payouts: id, affiliate_id, period_start, period_end, amount_cents, currency, method, status, reference, paid_at - processor_events: id, event_id, kind, payload_json, processed_at — idempotency lives here - Everything append-only. A commission is never edited: it is voided and a new one written ATTRIBUTION, WHICH IS WHERE THIS IS EITHER RIGHT OR EXPENSIVE - A click sets a first-party cookie on your own domain with the link token and a timestamp, plus a server-side visit row - Attribution window configurable per program, defaulting to something honest — thirty days is common, ninety is generous, and forever is a promise you will regret - Last touch or first touch, chosen per program and stated in the affiliate terms. Ambiguity here is what produces disputes - When a customer is created, the token is passed from the browser to your signup and stored against the customer at the processor as metadata. From that moment the referral is on the customer record, not in a cookie — this is what makes it survive everything else - Self-referrals blocked: an affiliate cannot earn on their own account, matched by email and by address hash - Bot visits flagged and never attributed COMMISSIONS FROM REAL MONEY - A commission is created from a payment that actually succeeded, never from a signup, a trial start or a subscription created - A trial produces no commission until the first payment clears. This is the single most common way a naive implementation pays out for nothing - Recurring commissions for a stated number of months, counted from the first payment, and the count is a computed property of the payments rather than a stored counter that can drift - Upgrades, downgrades and proration: the commission is a percentage of the amount actually collected on that invoice, whatever it is - Currency: the commission is in the currency of the payment, and a payout in another currency records the rate and its date REFUNDS AND CHARGEBACKS, THE PART THAT DECIDES WHETHER YOU LOSE MONEY - A hold period before a commission matures — thirty days is typical — during which a refund voids it - A refund after payout is recorded as a negative adjustment against the next payout, never as a silent deletion - A chargeback voids the commission and flags the referral for review - A failed recurring payment produces no commission for that period, and a later recovery produces one dated to the recovery - Every void carries a reason and is visible to the affiliate. An affiliate who watches a commission disappear without explanation stops promoting you THE AFFILIATE PORTAL - Their link, their visits, referrals, pending and mature commissions, and their payout history - Numbers that agree with yours because they come from the same rows - The terms with a version, and the version they accepted recorded - Marketing assets, and a way to ask for a custom link PAYOUTS - A run per period: everything mature, above the minimum, grouped per affiliate - Manual by default. Paying automatically is a fine thing to add once you trust the numbers, and a terrible thing to add before that - Tax paperwork status per affiliate, because in many jurisdictions you cannot pay without it. Flag it rather than blocking silently - Every payout with a reference, reconcilable against the bank FRAUD - Watch for: many referrals from one address hash, referrals whose payments are all refunded, coupon stacking, and traffic from a source that converts implausibly well - Flag for review rather than acting automatically, and record every decision OPERATIONS - .env: DATABASE_PATH, BASE_URL, HASH_SALT, SESSION_SECRET, PROCESSOR_KEY, PROCESSOR_WEBHOOK_SECRET, SMTP_URL - Migrations on boot, each once - Reconcile nightly against the processor's own records and alert on any disagreement - Nightly backup off the machine, restore script - Health endpoint reporting webhook lag WHAT MATTERS MOST Paying only on cleared money, and the hold period. Build commission creation from payment webhooks with the maturity delay first, then simulate a trial that never converts, a refund at day twenty and a chargeback at day sixty. Getting attribution slightly wrong costs you an argument; getting refunds wrong costs you cash. Give me the repository, migrations, .env.example, the tracking snippet, a seed with affiliates and a refunded referral, and a README with deploy steps behind Caddy and example affiliate terms.
What you lose
- Attribution that handles trials, upgrades, refunds and failed payments correctly, which is where naive implementations pay out wrongly
- An affiliate portal with links and statistics
- Payout batching and reporting
If you would rather not build
- Stripe metadata plus your own accrual table
- Tolt or FirstPromoter, for the hosted version
- A manual spreadsheet, which works for five affiliates
What it costs
read from their page 15 Aug 2026
| Plan | Billed monthly | Billed yearly | Last read |
|---|---|---|---|
| — | $49/mo | — | 15 Aug 2026 |
Their pricing page is where these came from. Seeing a different price? Tell us.
The escape hatch
open source · no votes, no paid placement
Killbill
$0Subscription billing with plugin hooks where commissions can accrue.
killbill/killbillfree · open source
Why this verdict
our own opinion · changed only by a person
76/100
Verdict yes at 76. Stripe metadata carries the attribution; the rules about trials and refunds are what stop you paying commission on revenue you never kept.
History
tracked since 10 Aug 2026 · nothing is ever overwritten
Questions about Rewardful
answered from the record above
Is Rewardful free?
No — the plan we track is $49 a month. Starter at around $49/month billed monthly, cheaper annually, plus a share of tracked revenue on higher tiers.
Can you replace Rewardful by building your own?
YES. Replaceable in one session with an AI coding agent. Replacement score 76 out of 100, build time one session. Read what you lose before you decide.
How much does Rewardful cost?
$49 a month on Starter — $588 a year. Recorded 10 Aug 2026.
What do you lose by replacing Rewardful?
Attribution that handles trials, upgrades, refunds and failed payments correctly, which is where naive implementations pay out wrongly; An affiliate portal with links and statistics; Payout batching and reporting. If any of those carry weight for you, keep paying.
Is there an open-source alternative to Rewardful?
Yes: Killbill, Medusa. The prompt on this page is for when you want it your way instead.
Related entries
same category first, most replaced first
Every week, something stops being worth paying for.
New verdicts, prices that moved, entries added. One email a week. Unsubscribe in one click. Nothing is being sent yet — your address is kept here, and the first issue is the first thing it is used for.
free forever · no tracking pixel · stored here, never passed to anyone

