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

# Track clicks and attribute fans with tracking links

> Create tracking links with the Fanvue API, attribute link clicks to signed-in fans, measure per-link earnings, and attach custom metadata to each click.

A tracking link is a short link a creator shares off-platform. Every click is
recorded as an impression, and once the visitor signs in, the click is attributed
to their account. That gives you per-link click counts, the list of fans a link
brought in, and their earnings.

You can also attach your own key/value **metadata** to a click, so you can tie a
fan back to the campaign, creative, or record in your own system that sent them.

<Note>
  #### Authentication Required

  Tracking-link endpoints require OAuth with these scopes:

  * `read:tracking_links` - List links, list a link's users, read a user's metadata
  * `write:tracking_links` - Create and delete links

  See the [OAuth Tutorial](/docs/authentication/implementation-guide) for setup instructions.
</Note>

## Step 1: Create a link

```bash theme={null}
curl -X POST https://api.fanvue.com/tracking-links \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "X-Fanvue-API-Version: 2025-06-26" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Spring launch - Instagram", "externalSocialPlatform": "instagram" }'
```

The response contains the link's `uuid` (which you use on the API) and its
`linkUrl` (the short slug the creator shares):

```json theme={null}
{
  "uuid": "f9c1a2b4-5d6e-4f70-8a91-2b3c4d5e6f70",
  "name": "Spring launch - Instagram",
  "linkUrl": "fv-3",
  "externalSocialPlatform": "instagram",
  "clicks": 0
}
```

The shareable URL is the creator's handle followed by the slug:

```
https://www.fanvue.com/<handle>/fv-3
```

## Step 2: Attach your own metadata

Metadata is captured **from the query string of the shared link**. There is no
API call and no field at creation time. Append your own parameters as plain
query parameters, one per key:

```
https://www.fanvue.com/janedoe/fv-3?campaign=spring_launch&creative=story_a&utm_source=instagram
```

<Warning>
  Tracking links use **plain** query parameters (`?campaign=spring_launch`). They
  do **not** use the `metadata[<key>]=<value>` bracket syntax that
  [checkout links](/docs/checkout/attribution) use.
</Warning>

Every non-reserved parameter on the URL becomes a metadata entry. There is no
prefix to add and no allowlist to register: `utm_source`, `campaign`, `gclid` and
your own names are all treated the same way and captured as-is.

## Step 3: Read the metadata back

Once the click is attributed to a fan, read it with the fan's UUID:

```bash theme={null}
curl https://api.fanvue.com/tracking-links/f9c1a2b4-5d6e-4f70-8a91-2b3c4d5e6f70/users/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d/metadata \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "X-Fanvue-API-Version: 2025-06-26"
```

```json theme={null}
{
  "metadata": {
    "campaign": "spring_launch",
    "creative": "story_a",
    "utm_source": "instagram"
  }
}
```

Response behaviour:

| Situation                                                    | Response                      |
| ------------------------------------------------------------ | ----------------------------- |
| Link UUID is not one of your links (or was deleted)          | `404`                         |
| The fan has no attributed click on this link                 | `200` with `"metadata": null` |
| The fan's most recent attributed click carried no parameters | `200` with `"metadata": null` |

To find the fans to look up, use
[`GET /tracking-links/{uuid}/users`](/docs/api-reference/list-users-for-a-tracking-link).
Only clicks matched to an account appear there.

## Limits

Metadata is sanitized at capture time. Nothing is rejected: over-limit input is
silently trimmed, so a click is never lost because of its query string.

| Rule           | Limit                    | What happens on breach                                              |
| -------------- | ------------------------ | ------------------------------------------------------------------- |
| Keys per click | **10**                   | Keys past the tenth are dropped, keeping the first ten in URL order |
| Value length   | **500 characters**       | The value is truncated to 500 characters                            |
| Key length     | No limit enforced        | Keys are stored as given                                            |
| Total size     | No explicit limit        | Bounded in practice by the maximum URL length accepted in transit   |
| Value type     | Strings only             | A repeated parameter (`?a=1&a=2`) keeps the **first** value only    |
| Empty values   | Not stored               | `?campaign=` is dropped and does not use up one of the ten keys     |
| Reserved names | `handle`, `trackingLink` | Dropped, and they do not use up one of the ten keys                 |

If nothing valid remains, the click is still recorded and the metadata endpoint
returns `null`.

<Warning>
  Metadata is passthrough only: Fanvue never interprets it, and it is readable by
  anyone holding the creator's `read:tracking_links` scope. Do not put secrets or
  personal data in it.
</Warning>

## Overwrite semantics

Each click creates a new impression, and the metadata endpoint returns the
metadata of the **most recent** click attributed to that fan on that link.
Metadata is never merged across clicks.

* A later click **replaces** the previous metadata wholesale. Keys present on the
  earlier click but absent from the later one are gone, not carried forward.
* A later click with **no** query parameters at all returns `"metadata": null`.
  The earlier value is not preserved.

If you need the values to survive later visits, keep every parameter on every
copy of the link you publish, or store the values in your own system the first
time you read them.

## Attribution timing

* A click made while the visitor is **signed in** is attributed immediately.
* A click made while **signed out** is recorded straight away, but stays
  unattributed until that visitor signs in from the same browser. Until then the
  metadata endpoint returns `null` for them.
* A click made while signed in **as the creator who owns the link** is not
  recorded at all. Use a separate fan account when testing.

## Metadata on webhooks

The `new_follower` and `new_subscriber`
[legacy events](/docs/webhooks/webhooks-overview) also carry the metadata of the fan's
most recent attributed click on any of the creator's tracking links, as
`trackingLinkMetadata`, alongside `trackingLinkUrl`. The sanitizing and
most-recent-click rules above apply identically.

Next: [Tracking-link endpoints](/docs/api-reference/list-tracking-links),
or [Checkout attribution](/docs/checkout/attribution) for the equivalent on checkout links.
