How It Works
The referral lifecycle
Every affiliate referral follows a six-step lifecycle:
- Click — A visitor clicks a partner's referral link
- Track — The tracking script records the click and stores attribution
- Convert — The visitor makes a purchase through your checkout
- Attribute — Affihub matches the transaction to the original referral
- Approve — The provider reviews and approves the commission
- Pay — The commission is included in the next payout to the partner
Step by step
1. Partner shares a referral link
Each partner gets a unique slug (e.g., john). They share links to your site with the ref parameter:
https://yourproduct.com/pricing?ref=johnPartners 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:
- Reads the
refparameter from the URL - Stores
{ref: "john", program: "prog_xxx", ts: 1234567890, landing: "/pricing"}inlocalStorage - Sends a
POST /track/clickbeacon 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_idon the checkout session - Paddle: Include
affihub_refincustom_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_xxxAffihub processes the webhook:
- Verifies the webhook signature
- Extracts the partner slug from
client_reference_idor metadata - Looks up the partner in your program
- Evaluates your commission flow rules to determine the rate
- Creates a commission record with status
pending - Logs the event in the audit trail
- 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:
- Select a date range (e.g., last month)
- Affihub sums all approved commissions per partner
- Partners meeting the minimum payout threshold get a payout record
- 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:
- Flow rules — Evaluated first, in priority order. The first matching rule determines the rate.
- Partner override — If no flow matches and the partner has a custom
commission_pct, use that. - 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
└──────────────────────┘