The Affiliate module is a full referral-and-partner platform: define a program, register affiliates, generate tracked links, attribute orders, accrue commissions, and pay out. It plugs into the Storefront so a regular customer order automatically attributes to the right partner, and it routes payouts through the Finance module.
Three controllers
| Controller | Path | Principal | What for |
|---|---|---|---|
AffiliateController | /affiliate/* | User (staff) | Program setup, affiliate management, referral admin, stats |
AffiliateClientController | /client/affiliate/* | Customer | Self-service partner portal — join, fetch link, see referrals + earnings |
AffiliatePublicController | /affiliate/public/* | Public | Resolve a referral code, track a click, apply a code at checkout |
The split keeps the partner portal ergonomic while admin tooling and public click-tracking each have their own surface.
Concepts
| Concept | Owns |
|---|---|
| Program | The ruleset — commission structure, attribution window, hold days, fraud limits, payout config |
| Affiliate | A registered partner — code, status, type, override commission, lifetime stats |
| AffiliateLink | A resolvable shareable URL containing the partner's code |
| Referral | A click → conversion record. Carries order ref, commission amount, status |
| Commission | The money owed for a referral. Status flows pending → held → credited → paid |
| Payout | A withdrawal of accrued commission balance. Routed via Finance |
| Click | An anonymous tracking event. Attributes a future order if it lands within the attribution window |
What's in each page
- Program setup — create a program, set commission structure (flat, percentage, tiered), configure fraud and payout rules.
- Tracking — public click tracking, resolving codes, conversion attribution from orders.
- Commissions — accrual rules, hold periods, manual transitions, clawback.
- Payouts — request payouts, integration with Finance, payment methods.
How an order becomes a commission
The Storefront calls AffiliateTrackingService.attributeOrder on every paid order. The service:
- 1
Resolve the affiliate code
Looks up the order's
affiliateCode(set from the click cookie or the applied checkout code). - 2
Validate program + affiliate state
Skips if either is inactive. Idempotent — only attributes once per order.
- 3
Run fraud checks
Applies program-level rules: max referrals per day, unique customer email, paid-order requirement, IP collision.
- 4
Calculate commission
Based on program type (
flat,percentage,tiered) plus any per-affiliate override or per-item override on the product. - 5
Create the referral
Initial status is
commission_held(under the hold window) orqualified(immediate credit ifpayout.holdDays === 0). - 6
Notify
Fires
referral-convertednotification to the affiliate.
The whole pipeline is non-blocking — it never fails the order. If commission attribution fails, the order completes and the failure is logged for retry.
Multiple programs
An org can run multiple programs in parallel — say, a referral program for end customers and an influencer program with higher rates. Each affiliate is registered against a specific program, and a single person can be enrolled in more than one. Commission rules and payout configs are per-program.
Public links
The public controller (/affiliate/public/*) is for unauthenticated traffic — landing pages, share buttons, redirect handlers. It can resolve a code without a token, track a click, and validate a code at checkout. All other endpoints (program admin, partner self-service) require auth.