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

# Connect Keitaro to OnlyFans API Smart Links (/introduction/guides/keitaro-smart-links)

import { Step, Steps } from "fumadocs-ui/components/steps";

## What the Keitaro integration does

Keitaro is a self-hosted traffic tracker and redirect platform used by media buyers. This integration connects Keitaro to OnlyFans API **Smart Links** so that every new subscriber you generate is reported straight back to Keitaro for attribution.

There are two halves: getting Keitaro's click ID into your Smart Link, then sending the conversion back to Keitaro when a subscription happens. Keitaro is not a built-in tracking pixel connection, so you wire it up with a Smart Links **Custom Postback**.

<Callout>
  **What you'll need**

  * An active OnlyFans API account with **Smart Links** enabled
  * A **Smart Link** created for the creator you're promoting
  * A **Keitaro campaign** with an offer, plus your Keitaro **postback URL** (its domain and key)
</Callout>

## How the pieces connect

Keitaro's `{subid}` (its click ID) is passed into your Smart Link as `?ecid={subid}`, where it is saved as your external click ID. When a fan subscribes, the postback sends that value back to Keitaro as `{external_click_id}`, which Keitaro matches to the original click. `{amount_gross}` can also be sent as Keitaro's payout.

<Callout type="warn">
  The chain must start **ad → Keitaro campaign URL** so Keitaro creates `{subid}`. After that, the offer may point directly to the Smart Link or to a landing page that forwards `ecid` and `utm_source` to it. Two setups break tracking:

  * **A page that does not forward `ecid`.** The conversion cannot carry Keitaro's click ID back.
  * **Ads pointing directly at the Smart Link.** If the ad's destination is your `trk.of-traffic.com` link instead of the Keitaro campaign URL, Keitaro never sees the click, so it can never attribute the conversion, no matter how the postback is configured.
</Callout>

## Step-by-step setup

<Steps>
  <Step>
    ### Point Keitaro's offer URL at your Smart Link

    In your Keitaro campaign, set the **offer URL** to your Smart Link with the click ID and traffic-source parameters:

    ```text
    https://trk.of-traffic.com/go/YOUR_SMART_LINK_ID?ecid={subid}&utm_source=keitaro
    ```

    Replace `YOUR_SMART_LINK_ID` with the ID from your Smart Links dashboard. `{subid}` is Keitaro's macro for the click ID: Keitaro swaps it for the real click ID when it redirects the visitor, and the Smart Link reads it from the `ecid` parameter and saves it. Create a **Keitaro** traffic source with an `utm_source` rule equal to `keitaro` so these visits are grouped and can use source-specific postbacks. See [Traffic sources](/introduction/guides/onlyfans-meta-pixel-smart-links#traffic-sources).

    <Callout type="warn">
      This has to be the **offer URL set inside Keitaro** so Keitaro performs the `{subid}` substitution, not a raw link posted straight to your traffic source. Pasting the link with `{subid}` anywhere else (a bio page button, an ad's URL field) sends the literal text `{subid}` as the click ID, which Keitaro can never match.
    </Callout>
  </Step>

  <Step>
    ### Create the custom postback in OnlyFans API

    Log into your [OnlyFans API Dashboard](https://app.onlyfansapi.com), open **Smart Links → Custom Postbacks**, and create a new custom postback with these settings:

    * **HTTP method:** GET
    * **Conversion type:** `new_subscriber`
    * **Scope:** **Specific Traffic Sources** with the Keitaro source selected. Use **Specific Smart Links** if you did not configure a Keitaro traffic source.
    * **URL:**

    ```text
    https://YOUR_KEITARO_DOMAIN/YOUR_POSTBACK_KEY/postback?subid={external_click_id}&status=sale&payout={amount_gross}
    ```

    A quick note on each value:

    * `{external_click_id}` outputs the Keitaro click ID captured in Step 1. This is what lets Keitaro match the conversion to the original click.
    * `status=sale` because a paid subscription is a confirmed sale. If this link is a free trial with no payment, use `status=lead` instead.
    * `{amount_gross}` is the gross amount the fan paid for the subscription, or `0.00` for free trials.

    Keep the `YOUR_KEITARO_DOMAIN` and `YOUR_POSTBACK_KEY` parts exactly as they appear in your own Keitaro postback URL, those are yours from Keitaro.

    <Callout type="info">
      A Global postback also fires for traffic that did not come through Keitaro. Its `subid` may be empty or may contain another channel's external click ID. Prefer **Specific Traffic Sources**. If you use **Specific Smart Links**, attach every new or replacement link.
    </Callout>

    <Callout type="warn">
      Don't use `status=subscription`, Keitaro doesn't recognize that value. Use `status=sale` for a paid subscription or `status=lead` for a free trial.
    </Callout>
  </Step>

  <Step>
    ### Test it with a single click

    You don't need to wait for a real subscription to verify the click ID capture:

    1. Open your Keitaro **campaign URL** in a browser. You should land on OnlyFans via the Smart Link redirect.
    2. In Keitaro, open **Reports → Clicks log** and note the new click's **Subid**.
    3. In your Smart Link's **Clicks report**, the **External Click ID** column for that click should show the same value.

    If the values match, attribution is wired correctly. After the first real subscription you'll see a `new_subscriber` row in the **Conversions report** with the External Click ID next to it, and the conversion will appear in your Keitaro dashboard.

    <Callout>
      If the **External Click ID** column is empty in the Clicks report, the issue is Step 1 (Keitaro isn't passing the click ID in). Fix that first, no postback settings can work without it.
    </Callout>
  </Step>
</Steps>

## Keitaro ↔ OnlyFans API variables

| Keitaro                     | OnlyFans API                  | Notes                                                              |
| --------------------------- | ----------------------------- | ------------------------------------------------------------------ |
| `{subid}` macro (offer URL) | passed in via `?ecid={subid}` | Keitaro replaces it with the click ID at redirect                  |
| `utm_source=keitaro`        | Traffic-source rule           | Lets reports and source-specific postbacks isolate Keitaro traffic |
| `subid` postback param      | `{external_click_id}`         | Matches the conversion back to the original click                  |
| `payout` postback param     | `{amount_gross}`              | Gross subscription payment; `0.00` for free trials                 |
| `status` postback param     | static `sale` / `lead`        | `sale` = paid sub, `lead` = free trial; never `subscription`       |

<Callout type="info">
  For the full list of postback variables (net vs gross amounts, fan and creator info, transaction details) and every available conversion type, see the [Smart Links guide](/introduction/guides/onlyfans-meta-pixel-smart-links#available-postback-variables).
</Callout>

## Troubleshooting

| Problem                                                        | Fix                                                                                                                                                                                                                                        |
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **External Click ID** column is empty in the Clicks report     | Keitaro is not passing the click ID. Make sure `?ecid={subid}` is on the **offer URL inside Keitaro** and that every later page forwards `ecid` to the Smart Link.                                                                         |
| **External Click ID** shows the literal text `{subid}`         | The macro was pasted somewhere Keitaro doesn't control, usually a bio page button or the ad's URL field. Only the offer URL field inside Keitaro expands `{subid}`.                                                                        |
| Conversion shows in OnlyFans API but not in Keitaro            | Check the postback URL's domain and key match your Keitaro postback exactly, and that `subid={external_click_id}` is present. Keitaro's **Maintenance → Logs → Received postbacks** shows every request it got and the `subid` it carried. |
| Re-subscribed with the same fan account to test, nothing fired | The `new_subscriber` postback fires **once per fan per Smart Link**. Test with a fan account that has never subscribed through that link.                                                                                                  |
| Subscription came long after the click                         | Conversions are attributed when the subscription happens within **6 hours** of the click.                                                                                                                                                  |
| Keitaro ignores or rejects the conversion status               | Use `status=sale` (paid) or `status=lead` (free trial). `status=subscription` is not recognized by Keitaro.                                                                                                                                |
| `payout` shows `0.00`                                          | Expected for free trials. Paid subscribers send the gross amount they paid.                                                                                                                                                                |