Meta Instant Forms
Instant Forms (Lead Ads) collect contact data inside Facebook and Instagram – the person never visits your website. X3 picks these leads up from Meta and stores them like any other lead: CRM rules, X3 App push, webhooks and the lead list all work the same way.
What X3 does with each lead:
- One lead per Meta lead id, even if the webhook arrives twice or the polling finds it again.
- Contact fields from the form's standard questions (full name or first/last name, e-mail, phone, company, city, postal code, country). A custom question that asks for the company („Unternehmensname“, „Firma“, „Company name“) also fills the company. Your other questions become the lead's message („Frage: Antwort“).
- Attribution: channel Meta,
utm_sourcefacebook or instagram,utm_mediumpaid_social (social for organic leads), campaign, ad set and ad names (from the lead, else from your synced Meta ad data). The lead page shows this origin as sure („Anzeige laut Meta“) and the lead counts for its Meta ad, ad set and campaign (leads from ads, cost per lead) everywhere – Sources & campaigns, Pulse,ads_performance,analytics_leadswithchannel_grouppaid – even though there is no website visit. Per-visit rates (leads ÷ visits) count only leads with a visit. See Leads from ads 0. - Origin and tag:
origin: meta_instant_form, the form's name and ids, and the form's tag (e.g.leadmagnet:guide) – use them as webhook filters. - No conversion is reported back – not to Meta (Meta counts its own form leads) and not to Google, LinkedIn or TikTok. Lead-triggered definitions do not fire for these leads. The lead page says „zählt Meta selbst“ instead of offering „An Meta melden“, and the hint „Lead nicht gemeldet“ ignores these leads.
How leads arrive
- Webhook (seconds): Meta calls
https://<api-host>/v1/webhooks/metawith the new lead's id; X3 checks theX-Hub-Signature-256signature and reads the lead with the page token. - Polling (every 15 minutes): X3 asks every enabled form for leads since its last check. This catches missed webhooks and works even before the webhook is set up. Leads that could not be read are retried.
- Backfill (when a form is switched on): Meta keeps Instant Form leads for 90 days. When you switch a form
on, the dashboard asks what to import and shows how many leads Meta still has for it: Alle (90 Tage)
importieren, Nur neue Leads ab jetzt or a number of days. Claude asks the same before it switches a form
on (
backfillDays0–90; over REST the PATCH and the token connect still default to 90). Leads already in X3 are skipped (one lead per leadgen id), leads skipped while the form was off are taken over; the answer says „x neu, y schon vorhanden“.
Never twice: a Meta lead id becomes at most one X3 lead, whatever happens – webhook and sync for the same lead, a backfill run twice, a form switched off and on again, a page disconnected and connected again, or the same page connected another way (token, Facebook login, Meta ad login). X3 keeps the record of every lead id it imported even after a page is disconnected, so reconnecting only adds the leads it does not know yet.
Editing a published form: Meta does not change a published form. It creates a new form with the same name and a new id and renames the old one to „<name> (v2)“. X3 reads the page's forms with every poll; the new version takes over the routing of the switched-on old one (on, target project, tag) within 15 minutes, so its leads keep arriving with the same tag. Changing a form's tag also gives its leads already in X3 the new tag (no webhook is sent for them).
Historic leads stay quiet: a lead older than 24 hours goes in without X3 App push and without outgoing webhooks (and the lead chime only rings for new leads anyway); younger leads take the normal path. Instant Form leads are never reported to an ad platform, backfilled or not. The Sales Engine still gets every one of them as a contact (see Hand leads on).
Through the Meta ad login
If Meta is already connected for ad costs (Einstellungen › Werbekonten & Budget), you do not need another sign-in: that Meta login can read the lead forms of the Facebook pages you manage. Right after you connect Meta there, X3 shows „Deine Kampagnen nutzen Instant Forms. Leads auch in X3 übernehmen?“ when your campaigns collect leads or your pages have lead forms with leads.
- Einstellungen › Instant Forms › Über Deine Meta-Verbindung: X3 lists the pages of your Meta login and per page its lead forms with the number of leads Meta still keeps and how many X3 already has.
- Tick the pages and the forms whose leads X3 should take over.
- Choose what to import: Alle (90 Tage) importieren, Nur neue Leads ab jetzt or Eigener Zeitraum (days). Then Verbinden und übernehmen. X3 reports per form „x neu, y schon vorhanden“.
Good to know:
- Every 15 minutes, no real-time webhook: the page token of this way belongs to the Meta app of X3's connection partner (Composio), not to X3's own app. A webhook subscription would go to that app, so X3 does not subscribe the page; the sync fetches new leads every 15 minutes, Jetzt abgleichen at once. The page says „Abruf alle 15 Minuten“; that is no error. For real time connect the same page with Mit Facebook verbinden or your own token later: the forms, their routing and the leads stay.
- Permissions: the Meta login needs
leads_retrieval,pages_show_list,pages_read_engagementandpages_manage_ads. An older login may lack one: X3 names it and offers Meta neu verbinden (Werbekonten › Werbekonto verbinden › Meta); keep every permission ticked in Meta's dialog, then come back. - X3 Konto › Verbindungen shows the use „Instant-Form-Leads“ at the Meta login. Disconnecting that login disconnects its pages too (forms and routing go, leads already in X3 stay). Connecting Meta again („Neu verbinden“) keeps the pages.
Connect with Facebook
The recommended way, and the only one most customers need: Einstellungen › Instant Forms › Mit Facebook verbinden. Nobody copies a token. The dashboard shows the same guide next to the button.
What you need
- A Facebook account with full control (admin) of the Facebook page your Lead Ads run on. The Ads task on the page is enough to read leads, too.
- Ideally the page belongs to a Meta business portfolio (Business Manager, business.facebook.com). In the Facebook dialog you then pick the portfolio and the page.
- If lead access is restricted: Business settings › Integrations › Leads access › your page › allow „X3 Growth Intelligence“ under CRMs.
What X3 may read, and what not
Only the pages you tick in the Facebook dialog, with these permissions:
| Permission | Why |
|---|---|
leads_retrieval | read the leads of the page's Instant Forms |
pages_show_list | list the pages you shared, to let you pick them |
pages_read_engagement | read the page name and its lead forms |
pages_manage_metadata | subscribe X3 to the page's leadgen webhook (real time) |
pages_manage_ads | read the lead forms of the page's ads |
ads_read | campaign, ad set and ad names of each lead |
X3 reads no posts, no messages and no comments, publishes nothing, changes no ads and spends no budget. The page tokens are stored encrypted (AES-256-GCM) and never shown; the user token from the login is dropped right after the page tokens are read.
Steps (about 2 minutes)
- Click Mit Facebook verbinden. Facebook opens in the same tab.
- Sign in if needed and click Continue as ….
- Pick the business portfolio and the page(s) with your lead forms. Keep every permission ticked.
- Confirm with Save. Facebook sends you back to Einstellungen › Instant Forms.
- Tick the pages X3 should take over and click Ausgewählte Seiten verbinden. X3 stores each page token
encrypted, subscribes the app to the page's
leadgenfield and loads the forms (switched off). - Route the forms (next section).
The attempt is valid for 30 minutes and works once. Pages that cannot be connected are shown with the reason:
| Shown | Cause | What to do |
|---|---|---|
| Facebook shows „App nicht aktiv“ / „Feature unavailable“ | the X3 app is not approved by Meta yet (development mode): only people with a role on the app can connect | ask X3 support to add your Facebook account as a tester, or use a token |
| Verbindung abgebrochen | the dialog was cancelled | start again and click Save at the end |
| Es fehlen Berechtigungen | a permission was unticked | connect again, Facebook asks for the missing ones again |
| Keine Seite freigegeben | no page ticked, or no role on any page | check Meta Business Suite › Settings › Pages, connect again |
| Kein Lead-Zugriff | neither full control nor the Ads task on that page | an admin of the page grants it under Settings › Page access |
| Schon in einem anderen X3-Projekt verbunden | a page can feed one project only | disconnect it there first (forms can still route leads to other projects) |
Connecting a page again renews its token; forms keep their routing.
Advanced: paste a token
For agencies with their own Meta app, or while Facebook Login is not available on an installation: Einstellungen › Instant Forms › Erweitert: Token einfügen.
- Meta Business Suite › Settings (business.facebook.com/settings) › Users › System users › add a system user (role Admin).
- Assign assets › Pages › your page › Full control, then the ad account (view ads is enough).
- Generate new token › pick the app (the X3 app „X3 Growth Intelligence“ if it is listed in your
portfolio under Accounts › Apps, otherwise your own business app) › expiry Never › tick
leads_retrieval,pages_show_list,pages_read_engagement,pages_manage_metadata,pages_manage_ads,ads_management› Generate token › copy. - Leads access: Settings › Integrations › Leads access › your page; if access is restricted, add the app under CRMs and the system user under People.
- Paste it in X3 and click Seite verbinden (optional page ids: empty = every page the token reaches). X3 fetches the page token of each page, stores it encrypted and never shows the token again.
A token of your own app subscribes your app to the page: Meta's real-time webhook then goes to your app, not to X3, and X3 picks the leads up every 15 minutes – unless you point your app at X3:
Real time with your own Meta app
Einstellungen › Instant Forms › Echtzeit mit Deiner eigenen Meta-App (MCP instant_forms_own_app_update):
- Enter the app id and the app secret of your app (Meta app › Settings › Basic) and save. The secret is write-only: X3 stores it encrypted and only shows „gesetzt …“ afterwards.
- X3 shows this project's callback URL (
/v1/webhooks/meta/p/<id>) and a verify token. In your Meta app: Webhooks › Page › Subscribe to this object, paste both, then subscribe to the fieldleadgen. Meta checks the URL right away; X3 shows the time under „Geprüft von Meta“. - Click Webhook neu abonnieren at each page (MCP
instant_forms_resubscribe): X3 renews the page's subscription with the stored page token and reads back the subscribed apps.
Every message must carry your app's signature (X-Hub-Signature-256); X3 only reads leads of pages connected
in this project. A wrong secret shows as „Fehler“ next to the setup. The 15-minute sync keeps running as the
safety net. Pages connected with „Mit Facebook verbinden“ use the installation's X3 app and need none of this.
Route forms and test
Per form in Formulare: switch it on, choose the target project (another project of the
organization needs project:admin there), set a tag (e.g. leadmagnet:guide) and optionally the X3 form id.
Leads nachladen: choose 7, 30 or 90 days and X3 fetches every lead of the switched-on form Meta still has for that period. The answer lists how many were found, newly imported (and of those how many quietly, older than 24 h), already there, skipped or failed. Running it again changes nothing.
Test:
- Test-Lead simulieren injects a synthetic test lead through the whole pipeline (marked as test).
- For a real test lead from Meta use the Lead Ads Testing Tool (developers.facebook.com/tools/lead-ads-testing › page › form › Create lead; delete an existing test lead first). Meta's test leads contain values like „<test lead: dummy data for email>“ and are marked as test leads in X3. It shows up within seconds (webhook) or at the next poll.
The status card shows whether the webhook is set up on this installation, the last lead and the last poll per page.
Hand leads on
Create a webhook with event lead.created, filter tags: ["leadmagnet:guide"] (or
origins: ["meta_instant_form"]) and contact data on – your server then receives every Instant Form lead of
that form with name and e-mail, e.g. to send the promised download.
Sales Engine: when the project is linked to the Sales Engine with „Leads automatisch als Kontakte übernehmen“, every Instant Form lead becomes a contact exactly once – status Neu, lead kind inbound, origin Meta Instant Form with the form, campaign and ad. A new lead is distributed with a call task like any inquiry. A lead older than 24 hours from an import becomes a contact too, only without call task, bell, push or mail (an old lead is no fresh inquiry). Importing the same leads again creates no second contact.
Data deletion
Somebody who connected a page with Facebook can remove X3 in Facebook (Settings › Business integrations ›
X3 Growth Intelligence › Remove) and request the deletion of their data. Meta then calls
POST /v1/meta/data-deletion (signed_request, HMAC-SHA256 with the app secret). X3 deletes at once every
page that person connected (page token, forms, routing) and their open connect attempts, and answers with a
confirmation code and the status page https://<dashboard-host>/oauth/meta/data-deletion?code=<code>.
Leads that already arrived belong to the business that runs the forms and stay in its project. The same page
without a code explains both ways (Facebook and Trennen in X3) and is the app's data deletion
instructions URL.
Set up the Meta app (operators)
One Meta app serves every customer of an installation (webhook and Facebook Login for Business). Hosted X3 uses the app „X3 Growth Intelligence“; a self-hosting operator creates their own:
- developers.facebook.com › My apps › Create app › type Business, owned by your business portfolio.
- Webhooks › object Page › Subscribe to this object › callback URL
https://<api-host>/v1/webhooks/meta, verify token =X3_META_WEBHOOK_VERIFY_TOKEN› Verify and save › field leadgen › Subscribe. App settings › Basic › App secret intoX3_META_APP_SECRET. - Facebook Login for Business › Settings › Valid OAuth Redirect URIs:
https://<api-host>/v1/meta-leads/oauth/callback(Client OAuth login and Web OAuth login on, Enforce HTTPS on, Strict mode on). - Facebook Login for Business › Configurations › Create configuration › name „X3 Instant Forms“ ›
login variation General › access token User access token › expiry: the default (60 days; the page
tokens read with it do not expire) › assets Pages › permissions
leads_retrieval,pages_show_list,pages_read_engagement,pages_manage_metadata,pages_manage_ads,ads_read› Create. Copy the configuration id intoX3_META_LOGIN_CONFIG_IDand the app id (App settings › Basic) intoX3_META_APP_ID(environment). The button appears once all three values are set. - App settings › Basic: privacy policy URL, terms URL, User data deletion › Data deletion callback URL
https://<api-host>/v1/meta/data-deletion, app icon, category; then switch the app to Live. - Until App Review grants Advanced Access for the permissions above, only people with a role on the app
(admins, developers, testers) can connect – fine for your own pages. For other businesses submit the app
for review, then set
X3_META_APP_LIVE=1so the dashboard stops showing the testers-only notice. Business verification of the owning portfolio is required for Advanced Access.
REST and MCP
| Route | MCP | Purpose |
|---|---|---|
GET /v1/projects/{project}/meta-leads/status | instant_forms_status | webhook set up, callback URL, counts, permissions, oauth (button available, testers only, redirect URI) |
POST /v1/projects/{project}/meta-leads/oauth | – | start „Mit Facebook verbinden“ (dashboard user), returns Meta's dialog URL |
GET /v1/meta-leads/oauth/callback | – | redirect URI of Facebook Login for Business (state check, code exchange) |
GET /v1/projects/{project}/meta-leads/oauth/{sessionId} | – | result of an attempt: shared pages or the reason it failed |
POST /v1/projects/{project}/meta-leads/oauth/{sessionId}/connect | – | connect the chosen pages (pageIds) |
GET /v1/projects/{project}/meta-leads/meta-ads | instant_forms_meta_ads_list | through the Meta ad login: missing permissions, reachable pages, per form leads at Meta and already in X3 |
POST /v1/projects/{project}/meta-leads/meta-ads | instant_forms_meta_ads_connect | connect pages through the Meta ad login, switch forms on, import by backfillDays (required), counts per form |
GET /v1/projects/{project}/meta-leads/pages | instant_forms_pages_list | connected pages (connectedVia, delivery realtime or poll) |
POST /v1/projects/{project}/meta-leads/pages | – | connect with a token (accessToken, optional pageIds) |
DELETE /v1/projects/{project}/meta-leads/pages/{pageId} | – | disconnect |
POST /v1/projects/{project}/meta-leads/pages/{pageId}/sync | instant_forms_sync | reload forms, fetch missed leads |
POST /v1/projects/{project}/meta-leads/pages/{pageId}/subscribe | instant_forms_resubscribe | „Webhook neu abonnieren“: renew the page's leadgen subscription, read back the subscribed apps |
GET · PUT · DELETE /v1/projects/{project}/meta-leads/own-app | instant_forms_own_app_get / instant_forms_own_app_update | real-time webhook with your own Meta app: app id, app secret (write-only), verify token, callback URL, verification, last message |
GET · POST /v1/webhooks/meta/p/{hookId} | – | callback of your own app (verification with the project's verify token, signature with your app secret) |
POST /v1/projects/{project}/meta-leads/forms/{formId}/backfill | instant_forms_sync with days or since (form_id or page_id) | „Leads nachladen“: every lead Meta keeps for the window (days 1–90 or since), counts per form |
GET /v1/projects/{project}/meta-leads/forms | instant_forms_list | forms with routing |
PATCH /v1/projects/{project}/meta-leads/forms/{formId} | instant_forms_update | on/off, target project, tag, form id, backfillDays when switching on |
POST /v1/projects/{project}/meta-leads/forms/{formId}/simulate | instant_forms_simulate | synthetic test lead |
POST /v1/meta/data-deletion · GET /v1/meta/data-deletion/{code} | – | Meta's data deletion callback and its status |
Everything needs project:admin; the Facebook login routes need a dashboard user session (the attempt
belongs to the person who started it). Tokens are only accepted over REST or in the dashboard, never by MCP;
the Meta ad login needs no token, so Claude can connect through it itself (it asks you which pages and forms and
what to import first).