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

# Integration Types

> Widget, Backend + First-party and Backend (S2S) compared: how the click flows, what to forward, and when to pick each.

There are three ways to serve creator cards. They differ in who renders the cards and where the click link on your page points.

|                                | Widget                        | Backend + First-party                                    | Backend (S2S)                                               |
| ------------------------------ | ----------------------------- | -------------------------------------------------------- | ----------------------------------------------------------- |
| Cards rendered by              | our script, in the browser    | your server                                              | your server                                                 |
| Click link on your page        | our tracking domain           | **your own domain**                                      | our tracking domain                                         |
| Click resolved by              | the visitor's browser         | your server, through the resolve API                     | the visitor's browser                                       |
| External ad links in your HTML | yes                           | **none**                                                 | yes                                                         |
| Setup                          | paste a snippet               | API fetch + a small relay endpoint                       | API fetch                                                   |
| Best for                       | regular pages, quickest start | pages that rank in search, ad-block-sensitive placements | server-rendered pages where the link profile doesn't matter |

## Widget

Paste one snippet where the cards should appear; rendering, impressions and clicks are handled for you. Layouts, themes and custom templates are covered in [Widgets](/partners/cpc-widgets).

## Backend (S2S)

Your server fetches creatives as JSON with the widget API key and builds its own HTML. Cards link to the ready-made tracking URLs from the response. Rules and examples: [Widgets, Backend (S2S)](/partners/cpc-widgets#backend-s2s).

## Backend + First-party

Server-side rendering like S2S, plus first-party click links: every link on your page stays on your own domain, and your server resolves each click through our API before redirecting the visitor.

Why choose it:

* **Clean link profile.** Your HTML contains no external ad links, so pages that rank in search carry no ad-network footprint.
* **Ad blockers can't cut the click path.** A same-origin link can't be blocked without breaking the site itself.
* **You control the referrer.** The page URL travels in the resolve call explicitly, and on the final redirect you decide what the destination site sees: a `Referrer-Policy: no-referrer` header hides your domain entirely.

Every click still goes through OnlyTraffic: the token in each card comes from us, and a click counts (and pays) only after your server resolves it.

### How it works

<Steps>
  <Step title="Fetch creatives">
    Same request as Backend (S2S): call the widget endpoint from your server with the `X-Api-Key` header, forwarding the visitor's `uip`, `uua` and `page`.
  </Step>

  <Step title="Render first-party links">
    Each creative includes a `click_token` and a `click_fallback`. Link the card to your own route, for example `https://yoursite.com/go?t=<click_token>&s=<click_fallback>`. Don't use `click_url` in this mode: clicks that go straight to `click_url` from a first-party widget are not paid. The impression pixel (`impression_url`) works the same as in S2S.
  </Step>

  <Step title="Resolve the click">
    When a visitor hits your route, call the resolve endpoint server-to-server:

    ```text theme={null}
    GET https://otsync.com/re?t=<click_token>&uip=<visitor IP>&uua=<visitor user agent>&uref=<page URL>
    X-Api-Key: <widget API key>
    ```
  </Step>

  <Step title="Redirect">
    The response contains the destination URL. Reply `302 Location: <url>`. Optionally add `Referrer-Policy: no-referrer` so the destination site doesn't see your domain.
  </Step>
</Steps>

### What to send on every resolve

| Field                      | Required    | What it is                                                                                                                                   |
| -------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `t`                        | yes         | The `click_token` from the creative                                                                                                          |
| `X-Api-Key` header         | yes         | Your widget API key; proves the call comes from your server                                                                                  |
| `uip`                      | yes         | The visitor's IP address                                                                                                                     |
| `uua`                      | yes         | The visitor's User-Agent                                                                                                                     |
| `uref`                     | recommended | URL of the page the click happened on; empty only raises a warning                                                                           |
| `s`                        | no          | The creative's `click_fallback`, passed through from your click link; lets clicks from stale cached pages still resolve (logged, never paid) |
| `asn`                      | no          | The visitor's network ASN. On Cloudflare, expose `ip.src.asnum` with a Transform Rule header and forward it                                  |
| `country`                  | no          | ISO2 override; normally resolved from `uip`                                                                                                  |
| `X-OT-Bot-Score` header    | no          | Cloudflare bot score, when your plan provides it                                                                                             |
| `X-OT-Verified-Bot` header | no          | Cloudflare verified-bot flag (`1` or `true`)                                                                                                 |

The values must describe the visitor's request to your site, not your server: click validation, geo stats and uniqueness all run on what you forward. A click without a valid `uip` or without `uua` is never paid (you'll see `no_uip` / `no_uua` in the response). An empty `uref` only raises a warning; the click still pays. The optional fields let more of the fraud filtering work for your traffic, which keeps your placement attractive to advertisers.

<Warning>
  Call the resolve endpoint from your server only, on every click, and never cache the response. A token yields at most one billable click: repeats, suspicious and non-unique clicks still redirect but don't pay.
</Warning>

### The response

```json theme={null}
{ "url": "https://...", "billable": true, "reason": "", "via": "proxy" }
```

* `url`: where to redirect the visitor. Always present for a live token. `null` means the token expired and no `s` was passed: redirect to a page of your own instead. With `s` passed through, even expired tokens resolve to the creator's page (logged, not paid).
* `billable`: whether this click passed validation and counts toward earnings. Diagnostic only; redirect either way.
* `reason`: why a click didn't pay. Common values: `duplicate` (token already resolved), `not_unique` (same visitor and creator within the uniqueness window), `no_uip` / `no_uua` (required context missing), `stale_token`, bot markers. `ref_not_forwarded` is a warning: the click still pays, but `uref` was empty and you should fix the integration.

### Relay example

A quick smoke test with a `click_token` from a fresh widget response:

```bash cURL theme={null}
curl "https://otsync.com/re?t=CLICK_TOKEN&uip=203.0.113.10&uua=Mozilla%2F5.0&uref=https%3A%2F%2Fyoursite.com%2Fpage" \
  -H "X-Api-Key: YOUR_WIDGET_API_KEY"
```

The relay route itself (the path, `/go` here, is your choice):

```javascript Node theme={null}
app.get('/go', async (req, res) => {
  const visitorIp = req.headers['cf-connecting-ip'] || req.ip;
  let url = 'https://otsync.com/re?t=' + encodeURIComponent(req.query.t || '')
    + '&uip=' + encodeURIComponent(visitorIp)
    + '&uua=' + encodeURIComponent(req.headers['user-agent'] || '')
    + '&uref=' + encodeURIComponent(req.headers['referer'] || '');
  if (req.query.s) url += '&s=' + encodeURIComponent(req.query.s);

  const r = await fetch(url, { headers: { 'X-Api-Key': 'YOUR_WIDGET_API_KEY' } });
  const data = await r.json();
  if (!data.url) return res.redirect(302, '/');

  res.set('Referrer-Policy', 'no-referrer');
  res.redirect(302, data.url);
});
```

`uref` normally comes from the Referer header of the same-origin click. If your site sets a global `no-referrer` policy, append the page URL to your click links yourself (for example `/go?t=...&p=<page URL>`) and forward that value as `uref`.

The widget form contains full copy-paste examples for Node and PHP (page render plus relay) and a ready prompt for an AI assistant.

## Which one to pick

* The page ranks in search, or you want a clean outbound-link profile: **Backend + First-party**.
* You render server-side and want the fastest backend setup: **Backend (S2S)**.
* Everything else: **Widget**.
