Troubleshooting conversions
Each conversion has an overall status and one status per platform (uploads.<provider>), visible in
the dashboard, in GET /v1/projects/{project}/conversions/{id} and in MCP conversions_list.
Per-platform status
| Status | Meaning | Retried? |
|---|---|---|
pending | queued for the next dispatch | – |
uploaded | accepted by the platform (ref holds the platform's id when it returns one) | final |
feed | listed in the Google Ads CSV feed | final |
failed | network error, 5xx, 408 or 429 | yes: 5 min → 30 min → 2 h → 6 h → 24 h, max 6 attempts, < 90 days |
error | rejected with a 4xx (bad token, invalid parameter) | no – fix the cause, then retry manually |
skipped | not sendable: no identifier, too old, test session, web daily cap | final |
not_configured | destination disabled, missing secret, or no mapping on the definition | final |
dry_run | built but not sent (mode or deployment ceiling) | final |
Overall: held (waiting for server confirmation), pending (a platform is still due), uploaded
(at least one platform uploaded or listed) or skipped.
Manual retry: dashboard button, POST …/conversions/{id}/retry (optionally
{"providers": ["meta"], "force": true}) or MCP conversions_retry.
Common causes
| Symptom | Cause | Fix |
|---|---|---|
skipped "no customer identifiers" (Meta) | no e-mail/phone/external id, no fbclid/_fbc/_fbp, no IP | send contact data or request context from your server |
skipped "no Google click id" | visit without gclid/gbraid/wbraid | expected for non-Google traffic; enable enhanced conversions for leads to use e-mail |
skipped "no LinkedIn identifiers" | no e-mail, li_fat_id or full name | send e-mail or first + last name |
skipped "older than 7 days" | Meta/TikTok limit | record conversions promptly |
skipped "test session" | the session was test traffic (?cm_test=1, test flag, internal IP rule) | use test mode to send test traffic |
skipped _guard: web_daily_cap | more than webDailyCap web conversions today | raise settings.conversions.webDailyCap if legitimate |
held for days | definition requires server confirmation, nobody confirmed | confirm with the same eventId from your server or PATCH …/status |
not_configured "access token missing" | destination without secret | set secrets.accessToken |
not_configured "no conversion action for this definition" | Google mapping missing | set providers.google_ads.conversionAction |
error 401 / 190 | token expired or revoked (LinkedIn tokens: 60 days) | renew the token, then retry |
error 426 (LinkedIn) | API version sunset | raise settings.apiVersion, then retry |
dry_run on production | X3_CONVERSIONS_MODE caps it, X3_CONVERSIONS_DISABLED=1, or destination mode | check the ceiling (Test modes) |
| No conversion at all for a form | the trigger never fired: wrong event name, form filter, or the session failed the web guards (no engagement) | check the session in Sessions, then the definition's trigger |
| Duplicate result, nothing uploaded | the eventId was used before | expected – one upload per event id |
| Conversion without channel/UTMs | session id not sent from the browser | pass getIds().sessionId with your form |
Google Ads feed
401when Google fetches: wrong user name/password, or a redirect dropped the credentials (curl -Ithe URL – it must answer401without redirect).- Google reports "conversion action not found":
feedNamediffers from the action's name (case and spaces matter). - Rows missing: only conversions of the last 60 days with a click id (or hashed e-mail with enhanced conversions for leads) are listed.
Privacy checks
Transient fields (IP, user agent, _fbp/_fbc/_ttp, company) are cleared once no upload is pending,
at the latest after 7 days. Hashes are never returned by the API. Erasing a lead
(DELETE …/leads/{id}) also clears the hashes on its conversions.