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

# How attribution works

> The precedence-ordered methods Affixo uses to credit a conversion to the right affiliate.

Every conversion is credited **server-side**. When a sale or lead arrives —
from the Stripe webhook or a `/v1/track` call — Affixo evaluates a chain of
attribution methods **in precedence order** and stops at the **first one that
matches**. A conversion is never credited to two affiliates, and the match is
recorded on the conversion as `match_method` + `match_confidence`.

## The six methods

Listed in the default precedence (strongest, most explicit signal first). The
order and which methods are enabled are configurable per workspace and per
campaign under **Admin → Attribution**.

| # | Method           | How it matches                                                                                                                            | Needs a cookie?      |
| - | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
| 1 | **Manual code**  | The customer types the affiliate's code at checkout (`metadata.sa_ref_code`). Off by default.                                             | No                   |
| 2 | **Coupon**       | A Stripe promotion code resolves to the affiliate that owns it.                                                                           | No                   |
| 3 | **Click**        | The visitor clicked an affiliate link, and their browser still remembers who they are.                                                    | No — browser storage |
| 4 | **UTM**          | UTM parameters on a hard-coded link match an affiliate's `ref_code`.                                                                      | No                   |
| 5 | **Subscription** | A renewal invoice is credited to the affiliate who earned the **first sale on that subscription** — so recurring commission never drifts. | No                   |
| 6 | **Email match**  | The buyer's email matches an earlier attributed purchase (365-day window). Lowest confidence; last resort.                                | No                   |

<Note>
  **No method depends on a third-party cookie**, so none of this breaks when a
  browser blocks them. Methods 1, 2, 4, 5 and 6 need nothing stored in the
  browser at all, and survive ad blockers and cookieless renewals outright.

  Method 3 is the one with a shelf life: it needs the visitor's browser to still
  remember them. **Safari and every iOS browser clear that storage after roughly
  7 days without a return visit**, so a click-based referral older than about a
  week falls through to the identity signals below on those browsers. Chrome,
  Edge and Firefox keep it for the full window you configure.
</Note>

## Identity signals (beneath stored identity)

Two signals re-identify a returning visitor whose browser no longer remembers
them, so the **click** method can still find their original click:

* **Device fingerprint** — a SHA-256 hash of stable device characteristics.
* **IP address** — matched within the attribution window.

These are **not** independent attribution methods — they feed method 3. They
also power duplicate-affiliate and self-referral fraud detection.

## Precedence, idempotency, and reversals

* **First match wins.** The chain runs in the configured order; the first
  enabled method that resolves an affiliate credits the sale and the rest are
  skipped.
* **Idempotent.** Conversions dedupe on the Stripe event id (webhook) or your
  `external_id` (`/v1/track`) — safe to retry.
* **Reversals claw back automatically.** A refund (`charge.refunded`) **and** a
  chargeback (`charge.dispute.created`) reverse the conversion and the
  commission it generated.

## Configure the chain

Reorder methods, toggle any of them off, or set a per-campaign override under
**Admin → Attribution**. The self-attribution (manual-code) field is off by
default because exposing it invites house sales to hunt for a code.
