Using an LLM to implement this? Every section in this guide is written to be unambiguous for automated implementation. Each snippet is labelled with the exact page or event trigger it belongs to. You can paste this entire page into your AI assistant and ask it to find the right places in your codebase.
How Affixo tracking works
Affixo tracks three events in an affiliate’s journey:
All three share a single attribution chain. The snippet records the click on Affixo’s side and remembers who the visitor is;
track('signup') and track('sale') carry that visitor forward, and Affixo matches the event back to the right affiliate from their click history automatically.
Step 1 — Add the snippet to every page
Where: The<head> of every page on your site (layout file, base template, _document.js, etc.).
What it does: Detects when a visitor arrives via an affiliate link (?ref=, ?via=, ?fpr=, and others), records the click and remembers the visitor in their browser, and fires a page-view hit so you can see which domains are active.
The snippet does not set a cookie on your domain — it can’t, because it’s
served from
go.affixo.dev. Visitor identity is kept in your visitors’
browser storage instead, and read back with Affixo.getVisitorId(). Practical
consequence: Safari and every iOS browser clear that storage after about 7
days of no return visit, so a click-based referral older than a week may
fall back to weaker matching (device fingerprint, then IP) on those browsers.
Coupon, manual-code, subscription-renewal and email-match attribution are
unaffected — see Attribution.YOUR_PUBLIC_KEY with the key shown in Settings → Tracking. It looks like pk_live_xxxxxxxx.
Framework examples
Step 2 — Track signups (leads)
Where: Your signup confirmation or thank-you page — the page a user lands on after they successfully sign up or opt in. Do not put this on the form page itself; it must fire only after the account is created. What it does: Records the referred visitor as a lead. This tells Affixo “this affiliate sent us a signup.” No commission is earned at this stage — leads are a count metric that proves attribution is working before money changes hands.With user identity (recommended)
Pass the user’s email or ID so Affixo can deduplicate signups and link this lead to a future purchase:Framework examples
Step 3 — Track sales (customers)
Using Stripe? Don’t call
track('sale') — but do wire the visitor id into Checkout (below). If you’ve connected Stripe to Affixo (Integrations → Stripe), sales are recorded automatically and server-side — with the exact amount paid after discounts, coupon-code attribution, and automatic refund/chargeback reversal. Adding track('sale') on top would double-count the sale and report the pre-discount amount. But for a cookie-tracked referral (the visitor clicked an affiliate link, no coupon code), Affixo can only connect the payment back to the affiliate if your Checkout Session carries the visitor id — see Stripe: pass the visitor id immediately below. The manual track('sale') further down is only for sites with no connected payment integration.Stripe: pass the visitor id [#stripe-pass-the-visitor-id]
When you create the Stripe Checkout Session, set the Affixo visitor id on it. Affixo reads it fromclient_reference_id or metadata.sa_visitor_id — either works. Read the id on the page with Affixo.getVisitorId() and hand it to your backend:
customer_creation: 'always' is payment-mode only — Stripe rejects it in subscription mode, which always creates a Customer anyway. Its default, if_required, means a one-off purchase mints no Customer at all: the sale still attributes and pays commission normally, but the referral records no UID, so a repeat purchase by the same buyer can’t be tied back to the same Stripe identity. It has to be set when the session is created — once the checkout completes with no Customer, there is nothing to look up or backfill.For subscriptions, the
subscription_data.metadata.sa_visitor_id line is what lets renewal invoices attribute — a renewal invoice carries no client_reference_id of its own. One-off payments don’t need it.Already using another affiliate tool (e.g. FirstPromoter) that sets
client_reference_id to its id? Put the Affixo id in metadata.sa_visitor_id instead — Affixo prefers a metadata match over a foreign client_reference_id.order_id is strongly recommended. If the page reloads or the user refreshes, the same order_id prevents a duplicate commission from being created.Framework examples
Server-side alternative
If you can’t rely on browser JavaScript for sales tracking (server-rendered checkouts, webhooks, payment processors that redirect off-site), use the server-side API instead. For Stripe, prefer the native integration (Integrations → Stripe) — it captures sales automatically with the correct discounted amounts and needs no code. Use the API below for Paddle, Lemon Squeezy, or any provider Affixo isn’t directly connected to. See Server-side tracking for the full API reference. Quick example — record a sale from a Stripe webhook:Summary checklist
Use this to verify your integration before going live:- The snippet (
sa.js?w=YOUR_PUBLIC_KEY) is in<head>on every page -
Affixo.track('signup')fires on the signup/thank-you page only, after account creation - Sales are tracked — via the connected Stripe integration, or
Affixo.track('sale', { amount, currency, order_id })on the payment confirmation page if there’s no connected payment integration - Stripe only: the Checkout Session sets
client_reference_id(and, for subscriptions,subscription_data.metadata.sa_visitor_id) toAffixo.getVisitorId()— otherwise cookie/link referrals through Stripe don’t attribute -
amountis in major units (99.00), not cents -
order_idis set to your unique order/invoice ID to prevent duplicate commissions - The snippet live test in Settings → Tracking shows a confirmed hit
- The end-to-end test in Settings → Tracking shows a lead and a sale both register