Affihub
DocsGetting StartedHow It Works

How It Works

The referral lifecycle

Every affiliate referral follows a six-step lifecycle:

  1. Click — A visitor clicks a partner's referral link
  2. Track — The tracking script records the click and stores attribution
  3. Convert — The visitor makes a purchase through your checkout
  4. Attribute — Affihub matches the transaction to the original referral
  5. Approve — The provider reviews and approves the commission
  6. Pay — The commission is included in the next payout to the partner

Step by step

Each partner gets a unique slug (e.g., john). They share links to your site with the ref parameter:

https://yourproduct.com/pricing?ref=john

Partners can create multiple referral links in their portal, each pointing to different pages on your site.

2. Tracking script captures the click

When a visitor lands on your site with ?ref=john in the URL, the Affihub tracking script:

  1. Reads the ref parameter from the URL
  2. Stores {ref: "john", program: "prog_xxx", ts: 1234567890, landing: "/pricing"} in localStorage
  3. Sends a POST /track/click beacon to the API with the referral data, landing page, and referring URL

The attribution data persists for 90 days in the visitor's browser. If the same visitor returns without a ref parameter, the original referral is preserved.

3. Visitor completes a purchase

When the visitor reaches your checkout, your code reads the stored referral:

const ref = window.AffiHub.getRef();
// { ref: "john", program: "prog_xxx" }

You pass this reference to your payment provider:

  • Stripe: Set client_reference_id on the checkout session
  • Paddle: Include affihub_ref in custom_data
  • Custom: Call the Affihub API directly

4. Webhook attributes the conversion

When the payment succeeds, your payment provider sends a webhook to Affihub:

POST https://api.affihub.com/webhooks/stripe?program_id=prog_xxx

Affihub processes the webhook:

  1. Verifies the webhook signature
  2. Extracts the partner slug from client_reference_id or metadata
  3. Looks up the partner in your program
  4. Evaluates your commission flow rules to determine the rate
  5. Creates a commission record with status pending
  6. Logs the event in the audit trail
  7. Fires an outbound webhook (commission.created) to your app if configured
ℹ️

Each transaction is deduplicated by provider_event_id. If Stripe or Paddle retries a webhook, the same commission won't be created twice.

5. Provider approves the commission

In the provider dashboard, new commissions appear with pending status. You can:

  • Approve — Commission is ready for payout
  • Reject — Commission is denied (e.g., fraudulent referral, refunded transaction)

Approval can be done individually or in bulk via the dashboard or API.

6. Partner gets paid

Once commissions are approved, the provider generates a payout:

  1. Select a date range (e.g., last month)
  2. Affihub sums all approved commissions per partner
  3. Partners meeting the minimum payout threshold get a payout record
  4. Pay via Stripe Connect (direct bank transfer) or mark as paid manually

Partners see their payout history in the portal and receive notifications.

Commission calculation

Affihub uses a priority-based rules engine to calculate commission amounts:

  1. Flow rules — Evaluated first, in priority order. The first matching rule determines the rate.
  2. Partner override — If no flow matches and the partner has a custom commission_pct, use that.
  3. Program default — Fall back to the program's default_commission_pct (default: 20%).

Commission types:

  • Percentage — A percentage of the transaction amount (e.g., 20% of $100 = $20 commission)
  • Flat — A fixed amount per transaction (e.g., $15 per sale)

Attribution model

Affihub uses last-click attribution with a 90-day window:

  • The most recent ?ref= parameter wins
  • If a visitor clicks partner A's link, then later clicks partner B's link, partner B gets credit
  • Attribution expires after 90 days of no interaction
  • Each transaction is attributed to exactly one partner

Data flow diagram

Visitor clicks ?ref=john


┌──────────────────────┐
│  Tracking Script     │  → localStorage (90 days)
│  affihub.js          │  → POST /track/click (beacon)
└──────────────────────┘


┌──────────────────────┐
│  Your Checkout       │  AffiHub.getRef() → client_reference_id
└──────────────────────┘


┌──────────────────────┐
│  Payment Provider    │  checkout.session.completed
│  (Stripe / Paddle)   │  → POST /webhooks/stripe
└──────────────────────┘


┌──────────────────────┐
│  Affihub API         │  Verify signature
│                      │  Attribute to partner
│                      │  Evaluate flow rules
│                      │  Create commission
└──────────────────────┘


┌──────────────────────┐
│  Provider Dashboard  │  Review → Approve / Reject
└──────────────────────┘


┌──────────────────────┐
│  Payout              │  Generate → Pay via Stripe Connect
└──────────────────────┘