Affiliate Marketing skill

Affiliate Marketing is an agent skill for AI coding assistants (Claude Code, OpenClaw, Cursor, Codex). Affiliate/partner program design, commission economics, fraud-resistant tracking & attribution, compliance (FTC/GDPR/CPRA/tax/KYC), recruitment, and payout ops. Use when launching an affiliate program, designing commission terms, building click/conversion tracking, reviewing affiliate fraud, vetting payouts, or recruiting partners. Install with: npx skills-ws install affiliate-marketing.

growthv1.0.0Updated
copied ✓
openclawclaude-codecursorcodex
0 installsSecurity scan: cleanSource code

Affiliate Marketing

Workflow

1. Program Structure

In-house vs network:

FactorIn-houseNetwork (Awin, Impact, CJ, etc.)
Setup costHigher (build/integrate tracking)Lower (platform onboarding fee)
Ongoing costSaaS tracker fee + payment ops + fraud ops + tax/1099 ops + eng maintenanceNetwork override (commonly ~20-30% on top of commission) + per-payout fees
ControlFullLimited by platform rules/TOS
RecruitmentYou do it allAccess to affiliate marketplace
TrackingCustom or SaaS (Rewardful, PartnerStack, FirstPromoter, Tolt)Built-in
Best forSaaS, high-value products, brand controlE-commerce, consumer products, fast volume recruitment

"In-house = free" is a myth. Even self-hosting, you pay: SaaS tracker subscription (or build/maintain a click table), payment rails (PayPal/Wise/Tipalti fees, FX, reversals), fraud review labor, tax compliance (W-9/W-8BEN collection, 1099-NEC/1042-S filing), sanctions screening, and ongoing engineering. Budget 3-8% of affiliate GMV for ops on top of commissions; networks bundle most of this into their override.

Recommendation: Start in-house with a SaaS tracker (Rewardful, PartnerStack, FirstPromoter, Tolt) so you keep first-party data and brand control. Add a network only when you need volume recruitment in a marketplace and can absorb the override. Prices/overrides change: verify current network rates at awin.com / impact.com and tracker pricing on each vendor's site (as of Jul 2026); note ShareASale was folded into Awin and its platform closed in late 2025.

2. Commission Models

ModelStructureBest forExample
CPA (Cost Per Acquisition)Flat fee per signup/saleSaaS free trials, lead gen$50 per paid signup
CPS (Cost Per Sale)% of sale valueE-commerce, variable pricing20% of first purchase
Recurring% of subscription revenueSaaS with monthly billing20% for a defined window (see below)
TieredIncreasing % at volume thresholdsMotivating top performers20% (1-10), 25% (11-50), 30% (50+)
HybridBase CPA + recurring bonusBalanced motivation$25 CPA + 10% recurring

Setting commission rates (margin/LTV-anchored, not a fixed rule):

  • Compute blended CAC and gross-margin LTV per segment. Cap total affiliate payout (CPA + lifetime recurring) so it stays a fraction of contribution margin — a common target is ≤25-40% of gross-margin LTV, but the right number depends entirely on your margins and competitive landscape.
  • Recurring duration is a business choice, not a universal "12 months." Pick the window from margin and partner type:
Partner / productTypical recurring termWhy
SMB SaaS, thin marginFirst 12 monthsCaps liability where churn + payback risk is high
High-margin SaaS, sticky product24 months or lifetimeHigh LTV/long retention justifies sharing more; lifetime is a recruiting magnet (e.g., many infra/dev tools)
EcommerceOne-time % of first order (sometimes 30-day repeat)No subscription to share
High-ticket / enterpriseFlat CPA or % of first contract, sometimes Y1 onlyLong sales cycle, large deal size, finance prefers a fixed liability
Agency / resellerMargin share or revenue share for life of the accountThey own the relationship and support
Influencer / large creatorHigher % or flat fee + bonus, often negotiated per-dealReach commands a premium; negotiate per partner
  • Trade-off to state explicitly: lifetime/long terms maximize recruitment and partner loyalty but create perpetual liability and harder unit-economics forecasting; short windows protect margin but recruit fewer top affiliates. Model both against gross-margin LTV before committing.
  • Review rates quarterly using affiliate-sourced cohort LTV, refund/chargeback rate, and payback period vs other channels.

3. Tracking Implementation

Track in your database, not just a cookie. The cookie is a pointer to a server-side click record that carries the data you need to attribute, de-fraud, and reverse. Never derive a payout directly from a raw cookie value.

Schema (Postgres):

CREATE TABLE affiliates (
  id            BIGSERIAL PRIMARY KEY,
  status        TEXT NOT NULL DEFAULT 'pending', -- pending | active | paused | banned
  payout_hash   BYTEA,            -- hash of payout destination (detect linked accounts)
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE affiliate_clicks (
  click_id      UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  affiliate_id  BIGINT NOT NULL REFERENCES affiliates(id),
  landing_path  TEXT,
  utm_source    TEXT, utm_medium TEXT, utm_campaign TEXT,
  ip_hash       BYTEA,            -- hash, not raw IP (privacy)
  ua_hash       BYTEA,            -- coarse device/UA fingerprint hash
  consent       BOOLEAN NOT NULL DEFAULT FALSE,  -- analytics/marketing consent at click time
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON affiliate_clicks (affiliate_id, created_at);

CREATE TABLE affiliate_conversions (
  id            BIGSERIAL PRIMARY KEY,
  click_id      UUID REFERENCES affiliate_clicks(click_id),
  affiliate_id  BIGINT NOT NULL REFERENCES affiliates(id),
  customer_id   BIGINT NOT NULL,
  event_type    TEXT NOT NULL,          -- 'signup' | 'sale' | 'rebill'
  amount_cents  BIGINT NOT NULL,
  commission_cents BIGINT NOT NULL,
  idempotency_key  TEXT UNIQUE NOT NULL, -- e.g. order_id + event_type
  status        TEXT NOT NULL DEFAULT 'pending', -- pending | locked | approved | paid | reversed | rejected
  locked_until  TIMESTAMPTZ,            -- payout hold (refund/chargeback window)
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Session fingerprints for fraud joins in §5 (self-referral / IP & device overlap)
CREATE TABLE customer_sessions (
  customer_id   BIGINT NOT NULL,
  ip_hash       BYTEA,
  ua_hash       BYTEA,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON customer_sessions (customer_id);

On click — validate, then store a click record (signed click_id in the cookie):

const crypto = require('crypto');
const SECRET = process.env.AFFILIATE_COOKIE_SECRET; // 32+ random bytes

const sign = (v) => crypto.createHmac('sha256', SECRET).update(v).digest('base64url');

app.get('/ref/:affiliateId', async (req, res) => {
  // 1. Validate the affiliate exists AND is approved/active (not pending, banned, or paused)
  const aff = await getAffiliate(req.params.affiliateId);
  if (!aff || aff.status !== 'active') return res.redirect('/'); // silently drop, no cookie

  // 2. Record the click server-side with fraud + consent signals
  const click = await createClick({
    affiliateId: aff.id,
    landingPath: req.query.lp || '/',
    utm: { source: req.query.utm_source, medium: req.query.utm_medium, campaign: req.query.utm_campaign },
    ipHash: hashIp(req.ip),          // hash; do not store raw IP
    uaHash: hashUa(req.get('user-agent')),
    consent: req.cookies.consent === 'granted', // see Compliance: set strictly-necessary only pre-consent
  });

  // 3. Cookie holds an HMAC-signed click_id, not a guessable affiliate id
  const value = `${click.click_id}.${sign(click.click_id)}`;
  res.cookie('aff_click', value, {
    maxAge: cookieWindowMs(aff),  // per-program window, see table below
    httpOnly: true, secure: true, sameSite: 'lax', path: '/',
  });
  res.redirect(click.landingPath);
});

On conversion — verify signature, enforce window + attribution rules, idempotent, reversible:

app.post('/api/checkout/complete', async (req, res) => {
  const raw = req.cookies.aff_click;
  if (!raw) return res.json({ ok: true }); // organic / direct — no attribution, do not invent one

  const [clickId, sig] = raw.split('.');
  if (!clickId || sig !== sign(clickId)) return res.json({ ok: true }); // tampered cookie

  const click = await getClick(clickId);
  if (!click) return res.json({ ok: true });

  // Attribution-window check (the click, not the cookie, is the source of truth)
  if (Date.now() - click.created_at.getTime() > cookieWindowMs({ id: click.affiliate_id })) {
    return res.json({ ok: true }); // expired
  }

  // Exclusions: existing customers, self-referral, paused affiliate
  const aff = await getAffiliate(click.affiliate_id);
  if (!aff || aff.status !== 'active') return res.json({ ok: true });
  if (await isExistingCustomerBeforeClick(req.user.id, click.created_at)) return res.json({ ok: true });
  if (await isSelfReferral(aff, req.user, click)) return res.json({ ok: true });

  // Idempotent write — survives retries / duplicate webhooks; hold for refund/chargeback window
  await recordConversion({
    clickId,
    affiliateId: aff.id,
    customerId: req.user.id,
    eventType: 'sale',
    amountCents: req.body.amount_cents,
    commissionCents: computeCommission(aff, req.body.amount_cents),
    idempotencyKey: `${req.body.order_id}:sale`, // UNIQUE — duplicate => no-op
    status: 'locked',
    lockedUntil: addDays(new Date(), 30), // do not pay until refund window passes
  });
  res.json({ ok: true });
});

Reversal on refund/chargeback (clawback before payout):

// Stripe webhook: charge.refunded / charge.dispute.created
await db.query(
  `UPDATE affiliate_conversions SET status='reversed'
     WHERE idempotency_key=$1 AND status IN ('locked','approved')`,
  [`${orderId}:sale`]
);
// If already paid, record a negative adjustment against the affiliate's next payout.

Cookie window standards:

Product typeCookie windowRationale
SaaS30-90 daysLonger consideration cycle
E-commerce7-30 daysShorter purchase cycle
High-ticket90-180 daysEnterprise sales cycle

Coupon-code attribution (cookieless fallback): Map a unique discount code → affiliate. At order time, if a tracked coupon is used, attribute to that affiliate. Resolve conflicts explicitly with the cookie/click (define which wins — usually the explicitly-entered coupon since it is a stronger intent signal than a stale cookie). Codes survive cross-device and consent-blocked tracking, so most programs offer both a link and a code.

Attribution rules:

  • Last click wins — standard and simplest. The most recent valid affiliate click within the window gets credit.
  • First click wins — rewards discovery (Amazon historically used variants of this). Keep the earliest valid click; later clicks don't overwrite.
  • Linear / multi-touch split — complex and rarely worth it for affiliate; avoid unless you have multiple affiliates per journey and a reason to split.
  • Direct traffic does NOT erase a valid affiliate click. A user clicking an affiliate link and later returning via direct/bookmark/branded-search should still convert to the affiliate while the click is within the window — that is the normal, fair behavior. Wiping it under-credits affiliates and is not an anti-fraud measure. (Self-referral fraud is handled by the isSelfReferral check and the fraud rules in §5, not by nuking direct traffic.) If you intentionally run paid-search-last-touch rules to stop affiliates poaching your own branded-search traffic, document that policy in the affiliate agreement — don't bury it in code.

4. Partner Recruitment

Ideal affiliate profiles:

TypeCharacteristicsApproach
Content creatorsBlog/YouTube in your nicheOutreach with free product + custom commission
Review sitesG2, Capterra, niche review blogsEnsure listing, offer affiliate tracking
InfluencersSocial following in target audienceCustom landing page + higher commission
Existing customersHappy users with audienceIn-app referral prompt + affiliate upgrade option
AgenciesServe your target marketReseller/referral hybrid program

Recruitment outreach template:

Subject: Partner with [Product] — [X]% commission

Hi [Name],

I've been following your content on [specific topic] — [genuine compliment].

We're building [Product], which helps [audience] with [value prop].
I think it'd be a natural fit for your audience.

Our affiliate program:
- [X]% recurring commission (or flat $X per signup)
- [X]-day cookie window
- Dedicated affiliate dashboard
- Custom landing pages and creatives

Interested in trying it out? Happy to set you up with a free account
and walk through the program.

[Name]

5. Compliance

This is operational guidance, not legal advice. Affiliate programs move money and touch privacy, tax, and advertising law across jurisdictions — have counsel review your agreement, disclosures, and data flows. Rules change; verify against the linked primary sources.

FTC disclosure (US) — Endorsement Guides, updated 2023 and actively enforced through 2026:

  • Affiliates MUST disclose a material connection clearly and conspicuously, before/near the link, in the same medium (in-video for video, in-stream for audio), not only in a description or "link in bio."
  • A bare #ad/#sponsored can be sufficient if unavoidable; vague terms like #collab, #sp, #ambassador, or #partner are not. Platform "paid partnership" toggles do not replace a clear disclosure.
  • The brand can be liable for affiliates' deceptive claims. The FTC's 2024 Consumer Reviews and Testimonials Rule (effective October 2024) allows civil penalties for fake/incentivized reviews and undisclosed insider endorsements; your contract must require truthful, substantiated claims and ban fake reviews and "review gating." Primary source: FTC Endorsement Guides + the Rule on Consumer Reviews and Testimonials (ftc.gov).
  • Put disclosure obligations, an approved-claims list, and audit rights in the affiliate agreement, and monitor (don't just promise to monitor — the FTC expects active monitoring).

Privacy & consent (table stakes by 2026 — do not ship cookie tracking without this):

  • EU/UK (GDPR + ePrivacy): affiliate/analytics cookies are not "strictly necessary," so you need prior opt-in consent before setting them. Pre-consent, set only a strictly-necessary cookie; gate the /ref click cookie and any device hashing on consent === granted. Honor IAB TCF signals if you use a CMP. Use coupon-code attribution as the cookieless fallback for non-consenting EU users.
  • US (CPRA/CCPA + state laws): offer a "Do Not Sell or Share My Personal Information" / opt-out, honor Global Privacy Control (GPC) browser signals, and disclose affiliate tracking in your privacy policy. Sharing click data with networks can count as a "sale/share."
  • Store IP/UA as salted hashes, set a data-retention limit on click logs, and write affiliate data sharing into your DPA / privacy policy. Verify current obligations at gdpr.eu, ico.org.uk, and oag.ca.gov/privacy (as of Jun 2026).

Advertising-channel & trademark rules (protect brand + avoid account bans):

  • Email: affiliates emailing on your behalf must comply with CAN-SPAM (US), CASL (Canada — express consent + identification), and GDPR/PECR (EU/UK). Ban purchased lists and require working unsubscribe + sender identification in the agreement.
  • Paid search: forbid bidding on your brand/trademark terms and trademark + "coupon/discount/promo" combos, and ban direct-linking / typosquatting / fake domains. Forbid running ads that impersonate you.
  • Platform policies: Google/Meta/TikTok/Amazon Associates each restrict how affiliate links and incentivized content run — affiliates violating these can get your assets flagged. Reference them in the agreement.

Tax, KYC & sanctions (before you pay anyone):

  • Collect tax forms before first payout: W-9 (US persons) / W-8BEN(-E) (non-US). File 1099-NEC for US payees over the IRS threshold (verify the current-year threshold at irs.gov) and 1042-S for applicable foreign payees; withhold where required.
  • KYC/identity verification on affiliates (especially high-payout) to prevent payout fraud and money laundering; many payout providers (Tipalti, Trolley/PayPal, Wise) bundle this.
  • Sanctions screening: screen affiliates and payout destinations against OFAC SDN and equivalent EU/UK lists; block payouts to sanctioned persons/countries. Bake "we may withhold payment for legal/sanctions/fraud reasons" into the agreement.
  • VAT/GST: in some jurisdictions affiliate commission is a taxable supply — clarify who issues invoices and whether commissions are inclusive/exclusive of VAT.

Affiliate agreement must-have clauses: disclosure & truthful-claims obligations + audit rights; prohibited methods (brand bidding, spam, cookie stuffing, self-referral, incentivized/fake reviews, adware); payout terms, hold/lock period, clawback on refund/chargeback/fraud; consent/data-handling obligations; right to withhold for legal/sanctions/fraud; termination + survival of clawback.

Fraud detection — run these as scheduled reviews, hold suspicious conversions before payout (uses the §3 schema, including customer_sessions and the hashed affiliates.payout_hash of each affiliate's payout destination):

-- 1. Self-referral / IP & device overlap (click and conversion share fingerprint)
SELECT cv.affiliate_id, cv.customer_id
FROM affiliate_conversions cv
JOIN affiliate_clicks ck ON ck.click_id = cv.click_id
JOIN customer_sessions cs ON cs.customer_id = cv.customer_id
WHERE ck.ip_hash = cs.ip_hash OR ck.ua_hash = cs.ua_hash;

-- 2. Cookie stuffing / forced clicks: huge click volume, near-zero conversion, sub-second dwell
SELECT affiliate_id,
       COUNT(*) AS clicks,
       AVG(EXTRACT(EPOCH FROM (first_conv.created_at - ck.created_at))) AS avg_dwell_s
FROM affiliate_clicks ck
LEFT JOIN LATERAL (
  SELECT created_at FROM affiliate_conversions c
  WHERE c.click_id = ck.click_id ORDER BY created_at LIMIT 1
) first_conv ON true
WHERE ck.created_at > now() - interval '7 days'
GROUP BY affiliate_id
HAVING COUNT(*) > 5000
   AND COUNT(*) FILTER (WHERE first_conv.created_at IS NOT NULL)::float / COUNT(*) < 0.001;

-- 3. Abnormal conversion rate (suspiciously high CVR vs program median)
WITH per_aff AS (
  SELECT a.id AS affiliate_id,
         COUNT(DISTINCT ck.click_id) AS clicks,
         COUNT(DISTINCT cv.id)       AS conversions
  FROM affiliates a
  LEFT JOIN affiliate_clicks ck      ON ck.affiliate_id = a.id
  LEFT JOIN affiliate_conversions cv ON cv.affiliate_id = a.id
  WHERE ck.created_at > now() - interval '30 days'
  GROUP BY a.id
)
SELECT affiliate_id, clicks, conversions,
       ROUND(conversions::numeric / NULLIF(clicks,0), 4) AS cvr
FROM per_aff
WHERE clicks > 100 AND conversions::numeric / NULLIF(clicks,0) > 0.20  -- tune to your niche
ORDER BY cvr DESC;

-- 4. High refund/chargeback rate (low-quality or fraudulent traffic)
SELECT affiliate_id,
       COUNT(*) AS conversions,
       COUNT(*) FILTER (WHERE status = 'reversed') AS reversed,
       ROUND(COUNT(*) FILTER (WHERE status='reversed')::numeric / COUNT(*), 3) AS reversal_rate
FROM affiliate_conversions
WHERE created_at > now() - interval '90 days'
GROUP BY affiliate_id
HAVING COUNT(*) >= 10
   AND COUNT(*) FILTER (WHERE status='reversed')::numeric / COUNT(*) > 0.10
ORDER BY reversal_rate DESC;

-- 5. Duplicate / linked accounts (same payout destination across "different" affiliates)
SELECT payout_hash, array_agg(id) AS affiliate_ids, COUNT(*)
FROM affiliates
GROUP BY payout_hash
HAVING COUNT(*) > 1;

Additional non-SQL checks: brand-bidding violations (monitor paid-search SERPs for your trademark via a rank/ad monitor), minimum click→conversion dwell (reject sub-second), and a manual quarterly review of the top affiliates by revenue. Default-hold (status='locked') all conversions through the refund window so fraudulent ones can be reversed before any payout.

6. Performance Optimization

Monthly affiliate dashboard:

MetricCalculateBenchmark
Active affiliatesAffiliates with ≥1 conversion/month10-20% of total
Revenue per affiliateTotal affiliate revenue / Active affiliatesTrack trend
Conversion rateConversions / Clicks2-5% (depends on niche)
EPC (Earnings Per Click)Total commissions / Total clicks$0.50-2.00
Average commissionTotal paid / Total conversionsTrack vs CAC
Affiliate-sourced %Affiliate revenue / Total revenue10-30% target

Top performer strategy:

  • Identify top 10% of affiliates by revenue
  • Offer exclusive commission rates (+5-10%)
  • Provide early access to new features for content
  • Quarterly check-in call with affiliate manager
  • Custom creatives and co-branded landing pages