> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vibestrap.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Affiliate program

> Pay people to bring you customers — pick a SaaS provider, or run the built-in commission tracker that works with any payment gateway.

Affiliate programs are a growth flywheel — your customers bring you more
customers, often at a fraction of paid-ad CAC. vibestrap ships the plumbing
so you can run one in days instead of weeks: cookie capture, signup
attribution, commission calculation, and a one-line provider switch.

Pick **internal** (zero monthly fee, your data, works with any payment
gateway including Creem and NOWPayments) or hand off to **Rewardful** /
**Affonso** (managed dashboards, \~\$30-50/mo, Stripe-only). Switching is
one config line — never a rewrite.

## Prerequisites

* For SaaS providers: an account with the provider and the public API key /
  program ID from their dashboard.
* For internal: nothing. The `affiliate_referral` and `affiliate_commission`
  tables are already in the schema (`src/db/affiliate.schema.ts`) and migrate
  with `pnpm db:push`.
* A payment provider already configured (Stripe, Creem, or NOWPayments).

## Step-by-step (internal)

1. **Enable the internal provider** in `src/config/site.ts`:

   ```ts theme={null}
   affiliate: {
     enable: true,
     provider: 'internal',
     internalCommissionPct: 20,    // % of payment amount
     referralCookie: 'vbs_ref',    // ?ref=CODE → cookie name
     referralCookieDays: 60,
   },
   ```

2. **Push the schema** if you haven't already — the affiliate tables ship in
   the default schema:

   ```bash theme={null}
   pnpm db:push
   ```

3. **That's it.** The flow is automatic:
   * A visitor lands on `?ref=CODE` → middleware sets the `vbs_ref` cookie.
   * They sign up → `recordSignupReferral(userId)` writes a row to
     `affiliate_referral` (idempotent on `userId`).
   * They pay → the payment webhook calls `recordCommission()` which reads the
     referral and inserts an `affiliate_commission` row at your default %.

4. **Build a payout dashboard** — Vibestrap doesn't ship one. Query
   `affiliate_commission WHERE status = 'pending'`, group by `referrer_code`,
   pay out via Stripe Connect / wire / whatever, then `UPDATE … SET status = 'paid', paid_at = now()`.

## Step-by-step (SaaS providers)

1. **Pick a provider** in `src/config/site.ts`:

   ```ts theme={null}
   affiliate: { enable: true, provider: 'rewardful' },
   ```

2. **Set the matching env var** in `.env.local`:

   ```bash theme={null}
   NEXT_PUBLIC_AFFONSO_PROGRAM_ID=...   # for Affonso
   NEXT_PUBLIC_REWARDFUL_API_KEY=...    # for Rewardful
   ```

3. **Connect the provider to your payment gateway** in their dashboard
   (Stripe Connect for Affonso/Rewardful). Both SaaS providers
   are Stripe-only — they read payment events directly from Stripe and
   Vibestrap doesn't relay anything for them.

4. **Restart `pnpm dev`** to pick up the public env var.

## Pick the right provider

| Provider  | When to pick                                                                                                                                                             |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| internal  | You want zero ongoing fees, full control over commission logic, and your data in your DB. Works with any payment provider — pick this if you're on Creem or NOWPayments. |
| Affonso   | Stripe-only. Lifetime tracking, low monthly cost.                                                                                                                        |
| Rewardful | Stripe-only. Most polished Stripe-native option. Pick if you want a managed dashboard for your affiliates.                                                               |

## Verify it works (internal)

1. Open the site at `https://your.app/?ref=alice` in incognito.
2. In devtools → Application → Cookies, confirm `vbs_ref=alice`, expires in 60 days.
3. Sign up. In your DB:
   ```sql theme={null}
   SELECT * FROM affiliate_referral WHERE referrer_code = 'alice';
   ```
4. Buy something. Then:
   ```sql theme={null}
   SELECT * FROM affiliate_commission WHERE referrer_code = 'alice';
   ```
   You should see one row with `commission_cents = amount_cents * 0.20`.

## Common pitfalls

1. **Safari ITP blocks cookies.** First-party cookies set by your own server
   on a `?ref=` landing are fine, but if you use cross-domain redirects
   (e.g. landing on a marketing subdomain → app subdomain) the cookie will
   be dropped. Keep the referral landing on the same eTLD+1 as the signup.
2. **Refunds don't reverse commissions.** v0.1 doesn't auto-reverse — you
   need to manually insert a refund row (negative `commission_cents`, status
   `cancelled`) or `UPDATE … SET status = 'cancelled'` in your payout query.
3. **Self-referrals.** Nothing blocks a user from setting their own code as
   the referrer. Add a guard in `recordCommission` if this matters:
   `if (referral.userId === input.userId) return;`.
4. **Switching from internal to a SaaS provider.** The SaaS providers track
   on their own backend — historical commissions in `affiliate_commission`
   stay where they are; only new payments will be tracked by the SaaS provider.
5. **Cookie name collision.** If your buyers add their own analytics that
   also uses `vbs_*` prefixed cookies, change `referralCookie` to something
   unique to your brand.

## Going beyond

vibestrap stops at "wires connected, ready to extend" — by design.
The internal provider gives you data; how you turn it into a product
is yours to shape:

* **Payout admin UI** — query `affiliate_commission` directly while
  you have under five affiliates; build a `/admin` page when manual
  SQL hurts.
* **Affiliate self-service dashboard** — they ask for it before you
  need to build it. A copy-able referral link is enough at first.
* **Auto payouts** — Stripe Connect, PayPal Mass Pay, Wise — pick
  when you have a monthly-or-tighter cadence.

The API surface won't move under you: `recordSignupReferral`,
`recordCommission`, and the two affiliate tables. Build on top —
don't rewrite.

## Official docs

* Affonso: [affonso.io/docs](https://affonso.io/docs)
* Rewardful: [help.rewardful.com](https://help.rewardful.com/)
* Internal schema: `src/db/affiliate.schema.ts`
* Internal helpers: `src/affiliate/track.ts`
