Skip to main content
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.
Replace YOUR_PUBLIC_KEY with the key shown in Settings → Tracking. It looks like pk_live_xxxxxxxx.
The ?w= key is what identifies your workspace. Without it the snippet fires hits to the wrong account (or none at all). Always copy it from your dashboard — don’t type it manually.

Framework examples

Verify it works: Go to Settings → Tracking, scroll to the live test, enter your site URL, and click Run test. A confirmed hit means step 1 is complete.

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.
Affixo.track() is only available after the main snippet (Step 1) has loaded. If your thank-you page doesn’t include the <head> snippet, add it there too before calling track().
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]

Without this, a first-touch cookie referral through Stripe cannot be attributed — the sale is recorded but earns the affiliate nothing. (Coupon-code and returning-subscriber attribution still work without it; this is specifically about link/cookie clicks.)
When you create the Stripe Checkout Session, set the Affixo visitor id on it. Affixo reads it from client_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.
Where: Your payment confirmation or order success page — the page that only appears after a payment has successfully processed. Also callable from your backend webhook (see Server-side tracking). What it does: Records the lead as a paying customer and triggers the affiliate’s commission calculation. Pass the sale amount so the commission engine can apply percentage-based rules correctly.
amount is in major units (dollars, euros, …), not cents. 99.00=99.00.Passingcents(9900)registersa99.00 = `99.00`. Passing cents (`9900`) registers a 9,900 sale and produces a 100× commission overpayment.
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) to Affixo.getVisitorId() — otherwise cookie/link referrals through Stripe don’t attribute
  • amount is in major units (99.00), not cents
  • order_id is 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

Common mistakes