Meta Conversion Leads: How to Send CRM Stages Back

digital advertising
A steel gold prospector's pan on sage linen with a few gold nuggets separated from grey river gravel, representing Meta conversion leads optimization filtering qualified leads from form fills
The standard Leads goal hands you the whole pan. Conversion leads optimization only works once your CRM tells Meta which pieces were gold.

What is Meta's conversion leads optimization?

Meta's conversion leads optimization tells lead ads to find people likely to reach a stage you choose in your CRM, like "appointment booked," instead of anyone willing to submit a form. It only works if your CRM sends every lead stage back to Meta through the Conversions API, keyed on the Meta lead ID. Without that feed, Meta has nothing to learn from except form fills, and form fills are what you already have too many of.

Meta says advertisers using the Conversions API for CRM with this goal saw an average 21% lower cost per quality lead than the standard Leads goal. We treat that as Meta's number, not a promise. What we can say from setting it up: the hard part is never the ad set. It's getting clean, timely stage data out of a CRM that was never built to talk to Meta.

This guide covers the requirements, the exact payload, the n8n setup we use, and the mistakes that quietly stop it from working.

Why the standard Leads goal fills your CRM with junk

The default lead ads goal optimizes for submissions. Meta finds the people most likely to tap through an Instant Form, and it gets very good at it. Those people are not always the people who answer the phone.

We see the same pattern in almost every lead gen account we audit. Cost per lead looks great in Ads Manager. The sales team says half the leads are unreachable, wrong numbers, or people who don't remember filling anything out. Both are true at once, because Meta is optimizing for exactly the signal you gave it.

You can push back at the form level with Higher Intent forms, a typed phone number and one qualifying question. We covered that in our Facebook lead ads guide for service businesses. It helps. But it filters at the door, while conversion leads changes who Meta sends to the door in the first place.

What does Meta require before you can use it?

Meta's CRM integration documentation sets four bars. Check all of them before anyone writes a workflow:

  • At least 200 leads per month. Below that, there isn't enough downstream data to learn from.
  • CRM data uploaded at least once a day. Weekly CSV exports don't qualify.
  • A target stage that happens within 28 days of the lead being created. "Closed won" on a 60-day sales cycle won't work.
  • A target stage with a 1% to 40% conversion rate from lead. Too rare and there's no signal; too common and it's no better than a form fill.

And two that people miss:

  • Instant Forms only. The goal currently supports native Facebook and Instagram lead ads, not website forms. If your leads come from a landing page, send a qualified lead event through your regular Conversions API setup and optimize toward that instead.
  • The Meta lead ID has to be in your CRM. It's the 15 to 17 digit leadgen_id from the lead ads webhook. Meta calls it the highest-priority match key. A lot of CRM connectors drop it on the way in, which you only discover when you go looking for it.

Run the stage math before you pick a target. Say a client gets 300 Instant Form leads a month. If 25% book an appointment, that's 75 target events a month, a healthy signal. If 3% close, that's 9. Technically inside the 1% to 40% range, but thin enough that we'd optimize on the appointment and track closes separately.

What does the CRM event payload look like?

The payload specification is short. It's also different enough from website CAPI that you should build it as a separate integration. Here's a stage event as we send it:

{
  "data": [
    {
      "event_name": "Appointment Booked",
      "event_time": 1760018400,
      "action_source": "system_generated",
      "user_data": {
        "lead_id": 1234567890123456
      },
      "custom_data": {
        "event_source": "crm",
        "lead_event_source": "GoHighLevel"
      }
    }
  ]
}

It goes to POST https://graph.facebook.com/v25.0/{DATASET_ID}/events with a system user access token. The fields that matter:

  • event_name is free-form. It's your CRM stage name, not a standard event like Lead or Purchase.
  • event_time is when the stage changed in the CRM, in Unix seconds. Not when your workflow ran.
  • action_source must be system_generated for every conversion leads event.
  • custom_data.event_source must be crm, and lead_event_source names the tool the lead lives in: HubSpot, Salesforce, GoHighLevel, or "In-house CRM."
  • user_data.lead_id is the match key. If it's invalid, Meta rejects the event. If you don't have it, send a SHA-256 hashed email or phone instead, normalized first (lowercase and trimmed email, phone digits with country code).

Two rules in the spec cause most of the silent failures we've seen. First, event_time can be at most 7 days before you send the event. Second, it has to be after the lead was created, or the event may be discarded. That first rule kills the "we'll backfill last quarter" plan. You can't. The integration only learns from what you send going forward.

Which lead stages should you send?

All of them, in order. Meta's spec says to send every stage as it updates, including the initial lead stage, and that a lead reaching the final stage should have had all previous stages sent first.

A typical service-business funnel:

  1. Lead (sent the moment the form arrives)
  2. Contacted
  3. Appointment Booked (our usual optimization target)
  4. Showed
  5. Closed Won

Keep stage names stable. Because event_name is free-form, renaming "Appt Set" to "Appointment Booked" in the CRM creates a brand-new event as far as Meta is concerned, and your funnel mapping breaks. We map CRM stage IDs to fixed event names inside the workflow, so a sales manager tidying up pipeline labels can't wreck the signal.

Collapse messy pipelines. If the CRM has 14 stages including "Left voicemail 2," don't send all 14. Map them down to 4 to 6 meaningful milestones. Meta needs a funnel, not your team's to-do list.

The n8n setup we use

We build this as two small workflows plus a safety net. It runs fine on a self-hosted n8n instance, and nothing here needs a paid connector.

Workflow 1: capture the lead and send the first stage

  1. Facebook Lead Ads trigger (or a raw webhook subscribed to leadgen) receives the submission.
  2. Create or update the contact in the CRM, writing the Meta lead ID, form ID, ad ID and created time into dedicated custom fields.
  3. Post the "Lead" stage event to the Conversions API with event_time set to the lead's created time.
  4. Hand off to the follow-up sequence. Speed to lead still matters more than any of this; our CRM lead follow-up automation post covers that part.

Workflow 2: report every stage change

  1. CRM stage-change webhook fires (HubSpot, GoHighLevel and most others support this).
  2. Look up the contact's Meta lead ID. If it's empty, the lead didn't come from an Instant Form, so stop here.
  3. Map the CRM stage to a fixed event name. Unmapped stages are dropped and logged.
  4. Build the payload with event_time taken from the CRM's stage-change timestamp.
  5. HTTP Request node posts to the dataset events endpoint and checks the response for events_received: 1.
  6. Write a log row: lead ID, stage, event time, response. This is your audit trail when someone asks why Meta shows fewer conversions than the CRM.

Make the send idempotent. CRM webhooks retry, and the same stage change can arrive twice. We key each send on lead ID plus stage and skip anything already logged. Same problem, same fix as duplicate n8n webhook executions.

The safety net: a nightly reconciliation

Webhooks fail. A CRM outage, an expired token or an n8n restart can drop a few hours of stage changes. A scheduled workflow runs every night, pulls stage changes from the last 48 hours, compares them to the send log, and posts anything missing. Because of the 7-day limit, a gap you catch tomorrow is fixable. A gap you find next month is gone.

How do you know it's working?

Check in this order:

  • The API response. {"events_received": 1} means Meta accepted the event. An error about lead_id usually means the field was stored as text with formatting, or the ID came from a different form or page.
  • Events Manager. The CRM events should appear on the dataset with your stage names. Meta then walks you through ordering the funnel and choosing the stage to optimize for.
  • Wait for Meta's validation. Meta's own timeline puts data validation at a day or two and the learning phase at 2 to 4 weeks after that. Total time from start to optimizing is usually three to four weeks for a custom integration.
  • Switch the goal on a new ad set. Set the performance goal to maximize the number of conversion leads, then judge it on cost per appointment from the CRM, not cost per lead in Ads Manager. Cost per lead will usually go up. That's the point.

Mistakes that quietly break conversion leads

  • No lead ID in the CRM. The connector imported name, email and phone but dropped the ID. Fix the intake first, then wait for new leads.
  • Batching weekly. A Friday export sends Monday's stage changes 4 days late and anything older than 7 days not at all.
  • Using the workflow's run time as event_time. The event then looks newer than it was, and stages can arrive out of order.
  • Skipping the initial lead stage. Meta expects the first stage to arrive before the later ones.
  • Optimizing on a stage that's too rare. Closed-won at 2% on 200 leads is 4 events a month. Pick the earlier stage.
  • Judging it in Ads Manager. The in-platform lead count will drop. Look at what sales actually booked. This matters even more now that Andromeda leans on conversion signal quality for delivery.

Is it worth the setup?

If you run Instant Forms at 200+ leads a month and sales complains about quality, yes. It's the most direct way to stop paying Meta to find form-fillers. If you're under 200 leads, or most of your leads come from landing pages, start with a qualified lead event on your website CAPI. It's the same idea with fewer requirements, and it's the same logic we use for cleaning up junk leads on Google Ads.

Either way, the work isn't in Ads Manager. It's in the plumbing between your CRM and Meta, and in someone owning it after launch.

Get a free automation audit

If you're running lead ads and can't say which ads produce booked appointments, send us your CRM stages and a sample of recent leads. We'll check whether the Meta lead ID is reaching your CRM, whether you clear the 200-lead and 1%-to-40% bars, and what it takes to get stage data flowing back to Meta every day. No pitch deck.

Get a Free Automation Audit, or see how we build n8n workflow automation and run paid social for clients.