Affiliate tracking
Credit referral partners for signups and purchases with anonymous, browser-side tracking pixels.
Affiliate tracking wires referral pixels so partners get credited for signups and purchases, configured under config.affiliate in @repo/config. Tracking is anonymous and browser-side - no database table, no webhook.
Off by default
config.affiliate is entirely absent from the default config, so affiliate tracking ships off. The AffiliateConfig type is ready to use - you opt in by adding a provider sub-key.
- Presence of a provider sub-key turns it on: there is no single
enabledflag. - All keys are public (publishable) - they ship to the browser.
Never paste a secret API key into config. Affiliate keys are public by design.
Providers
Three providers are supported, each behind its own sub-key carrying a publicKey from that provider's dashboard. Each loads that vendor's pixel script after the page is interactive.
| Sub-key | Provider | Keys | Loads |
|---|---|---|---|
refgrow | Refgrow | publicKey | scripts.refgrowcdn.com/latest.js |
affonso | Affonso | publicKey, cookieDuration? (days, default 30) | affonso.io/js/pixel.min.js |
promotekit | PromoteKit | publicKey | cdn.promotekit.com/promotekit.js |
Each publicKey is required for its sub-key - omit it and that provider stays off. Add a vendor's domain to any Content-Security-Policy script-src allowlist you maintain.
Enable a provider by adding its sub-key with the public key:
// packages/config/src/index.ts
affiliate: {
enableInDev: false, // default - trackers stay off locally
refgrow: { publicKey: "..." },
affonso: { publicKey: "...", cookieDuration: 60 },
promotekit: { publicKey: "..." },
},Behavior
| Aspect | Behavior |
|---|---|
| Tracking | Anonymous and browser-side; no identify hook, no DB row, no webhook |
enableInDev | Optional, default false - scripts stay off in local development; set true to load them locally |
| Cookies | All three providers drop cookies |
| Consent | Trackers surface the banner but never wait on it - pixels load after interactive regardless of consent (unlike consent-required analytics) |
enableInDev also gates the banner: under cookieBanner: "auto", an enabled provider surfaces the banner only when its script would actually load. With enableInDev: false in local dev, no script loads, so the banner stays hidden.
Frequently asked questions
Where do referral conversions get recorded? Nowhere in your app - each provider's pixel reports back to that provider's dashboard. There is no local database table or backend webhook to manage.
Why don't my trackers load on localhost?
config.affiliate.enableInDev defaults to false, keeping local traffic out of your affiliate dashboards. Set it true to test locally.
Do affiliate trackers force the cookie banner to show?
Under cookieBanner: "auto", enabling any one surfaces the banner for visitors who require consent (all three drop cookies) - but only when the script would load, so enableInDev: false keeps it hidden locally. The pixels themselves load regardless of the consent choice. See Cookie consent.