Meta Ads tracking
How a Meta ad click becomes a tracked OnlyFans subscriber — tracking links, the webhook to trk.theonlyapi.com, matching, postbacks and your own Meta pixel.
Meta Ads tracking tells you which ad click brought each new OnlyFans subscriber.
It then reports that subscriber, and what they pay, to your own Meta pixel and
to your own systems. The tracking service runs at trk.theonlyapi.com and is
set up from the Meta Ads page of your Xcelerator CRM. Your Only API does two
jobs in the chain: it creates the OnlyFans tracking links, and it sends the
webhook that says a fan subscribed or paid.
Availability
Meta Ads tracking is being rolled out to Xcelerator CRM customers. If your CRM has no Meta Ads page yet, it isn't switched on for you. The Only API side described here (the dashboard page and the two read-only endpoints) works for every panel.
How it works
┌──────────┐ ┌─────────┐ ┌───────────────┐ ┌───────────┐
│ Ad click │ → │ Consent │ → │ Tracking link │ → │ Subscribe │
└──────────┘ └─────────┘ └───────────────┘ └─────┬─────┘
landing page landing page made via Only API OnlyFans
│
┌───────────────────────────┐ ┌───────┐ ┌─────────┐ │
│ Postback + Meta pixel │ ← │ Match │ ← │ Webhook │ ←┘
└───────────────────────────┘ └───────┘ └─────────┘
your systems + your pixel trk service Only API → trk.theonlyapi.comAd click
Someone taps your Meta ad and lands on your landing page. The ad's click id
(fbclid) and UTM tags come along in the address.
Consent
A cookie notice asks first. Nothing about the visitor is recorded until they agree.
Tracking link
When they press your button, the tracking service lends that click one of the funnel's exclusive OnlyFans tracking links for 2 hours (then the link rests for an hour before it is lent again). The links were created earlier, through your Only API, when you published the funnel. Bots, link previewers and repeat clicks get the funnel's shared link instead: they still count for the funnel, just not for one click.
Subscribe
The fan subscribes, renews, buys or tips on OnlyFans through that link.
Webhook
Your Only API sees the new subscriber or payment on its next sync and sends a
signed webhook (new_subscriber, renewed_subscriber, new_purchase or
new_tip) to https://trk.theonlyapi.com/webhooks/onlyapi/….
Match
OnlyFans lists who joined through each link, but not when. The webhook's time fills that gap: the subscriber is matched to the click that held the link at that moment. If no single click fits, they count for the funnel. Events that can't be matched within 2 hours are released as unattributed.
Postback and Meta pixel
For a matched fan, a signed postback goes to the address you set, and
Subscribe / Purchase goes to your own Meta pixel through the Conversions API.
Who does what
| Part | Runs on | You manage it in |
|---|---|---|
| Landing page, consent notice, button | Your landing page | CRM → Meta Ads → Funnels & Landing Pages |
| Which creators are tracked | The tracking service | CRM → Meta Ads → Settings → Only API (Connect Only API / Update creators) |
Tracking links (XA …) | OnlyFans, created through your Only API | CRM → Meta Ads (read-only view in the Only API dashboard) |
| Subscriber / payment webhook | The Only API | Only API dashboard → Meta Ads Tracking |
| Matching clicks to subscribers | trk.theonlyapi.com | — |
| Postbacks to your systems | trk.theonlyapi.com | CRM → Meta Ads → Events & Postbacks; history in Activity |
| Subscribe / Purchase to your pixel | trk.theonlyapi.com → Meta | CRM → Meta Ads → Settings (pixel); history in Activity |
What the Only API side needs
Open Meta Ads Tracking in the Only API dashboard. Its setup list checks each of these for you.
- The creator is connected and syncing. Events only exist for accounts the Only API syncs. Fansly can't be used: it doesn't say who joined through a link.
- Write actions are on for that creator. Creating a tracking link is a write
on OnlyFans, so it needs the per-account switch
(
PATCH …/accounts/{of_user_id}/polling {"allow_of_write_actions": true}). Without it, link creation stops withONLYAPI_WRITES_DISABLEDin the CRM. - The tracking connection is approved. The tracking service registers the
webhook itself when you press Connect Only API in your CRM (Meta Ads →
Settings → Only API); you never create it by hand. The creators sent with it are
your CRM's active creators; press Update creators there after adding or
removing one. Webhooks to a new domain wait for approval
(Webhooks → Approval),
so until
trk.theonlyapi.comis on the built-in list the connection shows Waiting for approval and delivers nothing. - All four events are subscribed.
new_subscriber,renewed_subscriber,new_purchaseandnew_tip. Reconnecting from the CRM restores a missing one.
Leave the XA links alone
Links named XA <funnel> main (shared) or XA <funnel> #N (exclusive) belong to
Meta Ads tracking. Deleting or renaming one on the Campaigns page breaks
attribution for it. Manage them from the CRM.
The tracking service always answers our webhook with a 2xx, even for events it ignores (another creator, a test). Any 4xx would count toward the 5-failure auto-disable, which would switch tracking off for the whole panel.
Check it over the API
Two read-only endpoints back the dashboard page. They read stored data only: no OnlyFans request, nothing counted against your monthly quota.
Status
curl "$BASE/api/crm/$CRM/meta-tracking/status" -H "X-API-Key: $KEY"{
"success": true,
"tracking_domain": "trk.theonlyapi.com",
"required_event_types": ["new_purchase", "new_subscriber", "new_tip", "renewed_subscriber"],
"domain": { "allowlisted": false, "approved_for_panel": true, "state": "approved_for_panel" },
"webhooks": [
{
"id": 41,
"url": "https://trk.theonlyapi.com/webhooks/onlyapi/t_8f2c",
"status": "approved",
"is_active": true,
"consecutive_failures": 0,
"auto_disable_after": 5,
"missing_event_types": [],
"health": "healthy",
"deliveries": {
"last_24h": { "delivered": 37, "retrying": 0, "retried": 1, "failed": 0 },
"last_7d": { "delivered": 212, "retrying": 0, "retried": 3, "failed": 0 },
"last_success_at": "2026-10-13T09:41:07.512000",
"last_failure": { "at": "2026-10-13T02:10:44.100000", "result": "retried", "response_code": 503,
"reason": "The receiver had an error (HTTP 503). We retry automatically." },
"next_retry_at": null
}
}
],
"creators": [
{ "of_user_id": "482687148", "username": "examplecreator", "platform": "onlyfans",
"supports_tracking_links": true, "write_actions": true, "polling_enabled": true,
"last_polled_at": "2026-10-13T09:40:12", "events_7d": { "new_subscriber": 41, "new_purchase": 9,
"new_tip": 3, "renewed_subscriber": 12 } }
],
"summary": { "connected": true, "delivering": true, "all_events_subscribed": true,
"creators": 1, "creators_with_write_actions": 1 }
}domain.state | Meaning |
|---|---|
allowlisted | trk.theonlyapi.com is on the built-in list; its webhooks go live at once |
approved_for_panel | An admin approved it for your panel |
needs_review | New webhooks to it wait as pending until approved |
health | Meaning |
|---|---|
healthy | Approved, on, delivering |
idle | Approved and on, but nothing to send in the last 7 days |
failing | Retries are queued or the last delivery failed |
awaiting_approval / rejected | Domain review pending / declined |
auto_disabled | Turned itself off after 5 failures in a row. PATCH /webhooks/{id} {"is_active": true} turns it back on |
disabled | Turned off by hand |
Times are UTC, written without a zone suffix, like the rest of the API. The signing
secret is not included; GET /webhooks/{id} returns it to the key
holder as before.
Delivery log
curl "$BASE/api/crm/$CRM/meta-tracking/deliveries?limit=50&result=failed" -H "X-API-Key: $KEY"| Parameter | Notes |
|---|---|
webhook_id | Optional. Must be one of this panel's tracking webhooks, otherwise 404 |
result | Optional. delivered, retrying, retried (failed, then tried again) or failed (gave up) |
limit | 1–100, default 50 |
before | Paging cursor: pass the previous page's next_before |
{
"success": true,
"deliveries": [
{
"id": 90211, "webhook_id": 41, "at": "2026-10-13T09:41:07.512000",
"attempt": 1, "max_attempts": 6, "result": "delivered", "response_code": 200,
"reason": null, "reply_excerpt": null, "next_retry_at": null,
"event": { "id": 5512093, "type": "new_purchase", "occurred_at": "2026-10-13T09:40:58",
"creator": { "of_user_id": "482687148", "username": "examplecreator" },
"fan": "Fan #a1b2c3", "value": 25.0, "test": false }
}
],
"has_more": true,
"next_before": 90211
}Each row is one attempt. A failed attempt is retried after 5 s, 30 s, 5 min,
30 min and 2 h (6 attempts in all); reason says what went wrong in plain words.
A row with "event": {"type": "test"} came from POST /webhooks/{id}/test.
Privacy
- Fans are anonymous tags. The dashboard page and the delivery log show a fan
only as
Fan #a1b2c3: stable for one fan on your panel, different on every other panel, and not reversible without our server secret. No fan id, username, display name or message text is returned. - Meta receives only what it needs. The event name and time, its value for
purchases, and the consented click's details from your landing page (
fbc,fbp, IP address and browser, a hashed click id). Never a fan's OnlyFans id, username or name, and only for subscribers matched to an exact click. - Nothing before consent. The landing page records nothing until the visitor accepts the notice.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Connection shows Waiting for approval | trk.theonlyapi.com not approved yet | Ask support to approve it for your panel |
| Funnel stuck creating links | Write actions off for the creator | Turn on Write actions for that creator |
| No deliveries though fans subscribe | The creator's sync is off, or the connection is off | Turn sync on; turn the connection back on |
| Turned off after failures | 5 failed deliveries in a row | Check the delivery log's reason, then Turn back on. Events from while it was off are not resent |
| Subscribers counted for the funnel, not a click | The click was a bot or preview, every exclusive link was lent out, or the fan subscribed after the 2-hour window | Ask support about a larger link pool or a longer window |
| Postback or pixel missing | Downstream of the Only API | CRM → Meta Ads → Activity shows each postback and pixel attempt (delivered, retrying, failed, dead), what was sent and what came back, with Retry, Send again and Send test |
Related
- Webhooks: approval, signatures, the retry ladder and auto-disable.
- Events: what triggers
new_subscriber,new_purchaseand the rest. - Subscribers & fans: how new subscribers are detected.