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_source facebook or instagram, utm_medium paid_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_leads with channel_group paid – 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

  1. Webhook (seconds): Meta calls https://<api-host>/v1/webhooks/meta with the new lead's id; X3 checks the X-Hub-Signature-256 signature and reads the lead with the page token.
  2. 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.
  3. 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 (backfillDays 0–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.

  1. 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.
  2. Tick the pages and the forms whose leads X3 should take over.
  3. 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_engagement and pages_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:

PermissionWhy
leads_retrievalread the leads of the page's Instant Forms
pages_show_listlist the pages you shared, to let you pick them
pages_read_engagementread the page name and its lead forms
pages_manage_metadatasubscribe X3 to the page's leadgen webhook (real time)
pages_manage_adsread the lead forms of the page's ads
ads_readcampaign, 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)

  1. Click Mit Facebook verbinden. Facebook opens in the same tab.
  2. Sign in if needed and click Continue as ….
  3. Pick the business portfolio and the page(s) with your lead forms. Keep every permission ticked.
  4. Confirm with Save. Facebook sends you back to Einstellungen › Instant Forms.
  5. 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 leadgen field and loads the forms (switched off).
  6. 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:

ShownCauseWhat 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 connectask X3 support to add your Facebook account as a tester, or use a token
Verbindung abgebrochenthe dialog was cancelledstart again and click Save at the end
Es fehlen Berechtigungena permission was untickedconnect again, Facebook asks for the missing ones again
Keine Seite freigegebenno page ticked, or no role on any pagecheck Meta Business Suite › Settings › Pages, connect again
Kein Lead-Zugriffneither full control nor the Ads task on that pagean admin of the page grants it under Settings › Page access
Schon in einem anderen X3-Projekt verbundena page can feed one project onlydisconnect 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.

  1. Meta Business Suite › Settings (business.facebook.com/settings) › Users › System users › add a system user (role Admin).
  2. Assign assets › Pages › your page › Full control, then the ad account (view ads is enough).
  3. 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.
  4. Leads access: Settings › Integrations › Leads access › your page; if access is restricted, add the app under CRMs and the system user under People.
  5. 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):

  1. 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.
  2. 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 field leadgen. Meta checks the URL right away; X3 shows the time under „Geprüft von Meta“.
  3. 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:

  1. developers.facebook.com › My apps › Create app › type Business, owned by your business portfolio.
  2. 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 into X3_META_APP_SECRET.
  3. 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).
  4. 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 into X3_META_LOGIN_CONFIG_ID and the app id (App settings › Basic) into X3_META_APP_ID (environment). The button appears once all three values are set.
  5. 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.
  6. 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=1 so the dashboard stops showing the testers-only notice. Business verification of the owning portfolio is required for Advanced Access.

REST and MCP

RouteMCPPurpose
GET /v1/projects/{project}/meta-leads/statusinstant_forms_statuswebhook 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-adsinstant_forms_meta_ads_listthrough the Meta ad login: missing permissions, reachable pages, per form leads at Meta and already in X3
POST /v1/projects/{project}/meta-leads/meta-adsinstant_forms_meta_ads_connectconnect pages through the Meta ad login, switch forms on, import by backfillDays (required), counts per form
GET /v1/projects/{project}/meta-leads/pagesinstant_forms_pages_listconnected 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}/syncinstant_forms_syncreload forms, fetch missed leads
POST /v1/projects/{project}/meta-leads/pages/{pageId}/subscribeinstant_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-appinstant_forms_own_app_get / instant_forms_own_app_updatereal-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}/backfillinstant_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/formsinstant_forms_listforms with routing
PATCH /v1/projects/{project}/meta-leads/forms/{formId}instant_forms_updateon/off, target project, tag, form id, backfillDays when switching on
POST /v1/projects/{project}/meta-leads/forms/{formId}/simulateinstant_forms_simulatesynthetic 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).