3-Step Integration Guide

Get Affitor tracking live with the supported click, signup, and server-side tracking flows

Three steps get Affitor tracking live: clicks → signups → sales. Steps 1 and 2 establish attribution; step 3 records revenue.

Before You Start

Make sure you have:

  • Your program ID
  • Your program API key for server-to-server calls
  • A decision on how you will track sales (server-side tracking vs Stripe integration):
    • Server-side tracking — your backend calls POST /api/v1/track/sale — for any backend or payment provider
    • Stripe integration — attach Affitor metadata to Stripe Checkout sessions
Info

Use one naming scheme consistently:

  • customerKey — browser helper argument (signup(customerKey, email))
  • customer_key — tracking API field
  • affitor_customer_key — Stripe metadata field

Step 1 — Install the Tracker

Add the tracker to every page where affiliate traffic can land.

Verifying is one click

Once the tracker is live on your public site, Affitor detects it automatically — no debug mode needed. To verify the full pipeline, use the Run verification button on the Share Program step (it runs a synthetic click → signup → sale). See Testing Integration.

<script
  src="https://api.affitor.com/js/affitor-tracker.js"
  data-affitor-program-id="YOUR_PROGRAM_ID"
  data-affitor-debug="false">
</script>

Replace YOUR_PROGRAM_ID with the program ID from your dashboard.

What this does

  • Detects affiliate visits via the ?aff= parameter
  • Creates a tracked customer / click relationship
  • Stores affitor_click_id in a first-party cookie
  • Sends click/pageview tracking data to Affitor

Verify

Visit your site through a real affiliate link or enable debug mode while testing. Then review:

  • browser console / network requests
  • Affitor dashboard → tracking/integration pages

Step 2 — Track Signups

After signup succeeds, tell Affitor which internal user was created.

Option A — Browser-side helper

Use this when your signup flow runs in the browser and the tracker is already loaded.

<script>
await window.affitor.signup('user_123', 'user@example.com');
</script>

Or inside your signup flow:

<script>
document.getElementById('signup-form').addEventListener('submit', async function(e) {
  e.preventDefault();

  const email = document.getElementById('email').value;

  // Run your own signup logic first.
  // After account creation succeeds:
  await window.affitor.signup(currentUser.id, email);
});
</script>

Use this when:

  • you already installed the tracker on the page
  • signup happens in the browser
  • you want the simplest supported flow

Option B — Server-side lead API

Use this when signup logic lives on your backend or you want the server to own the tracking call.

POST https://api.affitor.com/api/v1/track/lead
Authorization: Bearer YOUR_PROGRAM_API_KEY
Content-Type: application/json

{
  "click_id": "cust_42_1234567890",
  "customer_key": "user_123",
  "email": "user@example.com"
}
await fetch('https://api.affitor.com/api/v1/track/lead', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.AFFITOR_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    click_id: req.cookies.affitor_click_id,
    customer_key: newUser.id,
    email: newUser.email,
  }),
});

Lead tracking rules

  • Outside test mode, provide at least one of:
    • click_id
    • customer_key
  • For reliable payment attribution later, always send a stable internal customer ID:
    • customerKey in signup()
    • customer_key in the API
  • Browser-side signup() is the easiest path for most teams
  • Server-side API is best when signup completes on your backend

Response:

{
  "success": true,
  "message": "Lead tracked successfully"
}

Step 3 — Track Sales

When a customer pays, choose one revenue-tracking path.

Option A — Server-side tracking (works with any payment provider)

Send a server-to-server request once payment succeeds.

Endpoint: POST https://api.affitor.com/api/v1/track/sale

{
  "transaction_id": "txn_abc123",
  "customer_key": "user_123",
  "click_id": "cust_42_123456",
  "amount_cents": 9999,
  "currency": "USD",
  "sale_type": "payment",
  "is_recurring": false,
  "subscription_id": "sub_xyz",
  "subscription_interval": "monthly",
  "product_id": "prod_456",
  "line_items": [
    { "name": "Pro Plan", "amount_cents": 9999, "quantity": 1 }
  ]
}
ParameterRequiredTypeDescription
transaction_idYesstringUnique transaction identifier used for deduplication
amount_centsYesnumberPositive integer amount in cents
customer_keyConditionalstringYour internal customer ID
click_idConditionalstringTracked click identifier
currencyNostringUSD, EUR, or VND. Default: USD
sale_typeNostringpayment or subscription. Default: payment
is_recurringNobooleanUse true for recurring charges
subscription_idNostringExternal subscription ID
subscription_intervalNostringe.g. monthly, quarterly, annual
product_idNostringExternal product identifier
line_itemsNoarrayOptional item breakdown
await fetch('https://api.affitor.com/api/v1/track/sale', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.AFFITOR_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    transaction_id: order.id,
    customer_key: currentUser.id,
    click_id: req.cookies.affitor_click_id,
    amount_cents: order.totalCents,
    currency: 'USD',
    sale_type: 'payment',
  }),
});

Response:

{
  "success": true,
  "sale_id": 42,
  "commission_id": 18,
  "message": "Sale tracked successfully"
}
Info

transaction_id must be unique. Reusing the same value returns 409 Conflict.

Option B — Stripe integration

If you already use Stripe Checkout, keep taking payment in your own Stripe account — just attach Affitor metadata to the checkout session.

const session = await stripe.checkout.sessions.create({
  line_items: [{ price: 'price_xxx', quantity: 1 }],
  mode: 'payment',
  success_url: 'https://yoursite.com/success',
  cancel_url: 'https://yoursite.com/cancel',
  metadata: {
    affitor_click_id: clickId,
    affitor_customer_key: currentUser.id,
    program_id: 'YOUR_PROGRAM_ID',
  },
});

For subscriptions

Include the same fields in both places:

  • metadata
  • subscription_data.metadata
const session = await stripe.checkout.sessions.create({
  line_items: [{ price: 'price_xxx', quantity: 1 }],
  mode: 'subscription',
  success_url: 'https://yoursite.com/success',
  cancel_url: 'https://yoursite.com/cancel',
  metadata: {
    affitor_click_id: clickId,
    affitor_customer_key: currentUser.id,
    program_id: 'YOUR_PROGRAM_ID',
  },
  subscription_data: {
    metadata: {
      affitor_click_id: clickId,
      affitor_customer_key: currentUser.id,
      program_id: 'YOUR_PROGRAM_ID',
    },
  },
});

Stripe integration rules

  • One-time payments are attributed from Stripe checkout metadata and webhook processing
  • Subscriptions and renewals rely on invoice.payment_succeeded
  • If subscription_data.metadata is missing, renewal attribution can fail
  • Required metadata fields:
    • affitor_click_id
    • affitor_customer_key
    • program_id

Which Sales Path Should You Use?

PathBest for
Server-side trackingPOST /api/v1/track/saleAny backend, any payment provider, custom checkout, Paddle/LemonSqueezy/manual server events
Stripe integrationExisting Stripe Checkout integration

Use server-side tracking when your backend controls the revenue event. Use Stripe integration when you want Affitor to attribute sales directly from your Stripe webhook flow.


Verify it worked

Verify success
Browser
  • Visit your site with `?aff=TESTCODE` — an `affitor_click_id` cookie is set
Network
  • Your signup handler's `trackLead` call returns 2xx; your Stripe webhook (or S2S call) fires `trackSale` on a test payment
Dashboard
  • Click, lead, and sale all appear under your program's tracking events — or run `npx affitor onboard verify` to fire the whole synthetic chain in one command
If it doesn't work
  • Use `additional_data: { test_mode: true }` so test events never create real commissions

You're Done

All three steps working means your integration is live:

StepEventOutcome
Tracker installedClick/pageview trackingaffiliate visit captured
Signup trackedLead eventcustomer linked to partner
Sale trackedSale + commission flowrevenue attributed

Next:

© 2026 Affitor