Skip to content
Can Elmas

Attribution · 8 min read

Offline Conversion Tracking: Send CRM Revenue Back to Google and Meta

TL;DR

Offline conversion tracking sends CRM outcomes such as qualified leads, opportunities and closed revenue back to Google Ads and Meta, so bidding learns to find buyers instead of form fillers. Capture click IDs and contact data at submission, store them on the lead and deal, send two to four stages with consistent values, and reconcile weekly.

· Published · Updated

Offline conversion tracking closes the gap between what ad platforms see (a form fill) and what you actually want (qualified pipeline and revenue). You capture click IDs and contact data when a lead submits, store them in your CRM, and send qualified stages and revenue back to Google Ads and Meta so their bidding learns which clicks become customers. This covers the CRM side; web-side Conversions API setup is a separate job.

Why optimizing to form fills misleads algorithms

Smart Bidding and Meta’s delivery system find more of whatever conversion you count. Count form submissions and they find form fillers, and the cheapest ones are often students, job seekers, vendors, competitors and bots.

A hypothetical example with round numbers: Campaign A produces 100 leads at $50 each, and Campaign B produces 40 leads at $100 each. On form fills alone, A looks twice as efficient, so the algorithm shifts budget toward it. Now add the CRM: A’s leads turn into 2 opportunities and B’s into 8. Cost per opportunity is $2,500 for A and $500 for B. The platform optimized the wrong way while reporting success.

Broad automation makes this worse: Performance Max, broad match and Advantage+ audiences excel at finding cheap conversions, including where junk leads are plentiful. CRM outcomes give that reach something worth finding, and they’re the foundation of running Google Ads for B2B SaaS on pipeline instead of clicks.

Capturing click IDs and user data at submission

The whole loop depends on the form submission. Identifiers missed there can’t be matched later. Capture these on every lead form:

FieldSourceUsed by
gclidURL parameter from Google Ads auto-taggingGoogle offline imports
gbraid / wbraidURL parameters on some iOS traffic that arrives without a GCLIDGoogle offline imports
fbcThe _fbc cookie, or built from the fbclid URL parameterMeta Conversions API
fbpThe _fbp browser ID cookie set by the Meta pixelMeta Conversions API
Email and phoneThe form itselfEnhanced conversions for leads, Meta matching
UTMs and landing pageURL on first landingReporting and QA
Submission timestampServer time, with time zoneUpload timing
Consent statusYour consent toolFiltering before upload

The mechanics:

  1. Turn on auto-tagging in Google Ads. Without it, there’s no GCLID to capture.
  2. Persist click IDs on landing. A short script stores the URL parameters in a first-party cookie, because most people don’t convert on the first page. Some browsers cap the life of JavaScript-set cookies, so a server-set cookie survives longer.
  3. Write them into hidden fields at submission, with the UTMs. A UTM naming convention keeps those usable for QA.
  4. Turn on enhanced conversions for leads in Google Ads so the Google tag also sends hashed contact data from the form, letting Google match later uploads by email when the GCLID is missing.

Test with a real click on a live ad, then check the record in the CRM, not the form tool. Integrations often drop hidden fields nobody mapped.

Storing it in your CRM

Create dedicated fields and treat them as system fields that reps can’t edit:

  • Click ID fields on the contact or lead: GCLID, GBRAID, WBRAID, FBC, FBP, plus the Meta lead ID for instant form leads
  • Original submission timestamp and consent status
  • The same click IDs copied onto the deal or opportunity when it’s created, since revenue lives on the deal
  • A “sent” timestamp per stage and per platform, so a re-run never uploads the same conversion twice

Two rules prevent most of the messes I untangle in audits. First, don’t overwrite a stored click ID when a known contact submits another form; add a separate “latest click” field if you want it. Second, keep raw email and phone in the CRM and hash at send time, because stored hashes go stale when someone fixes a typo.

Google Ads has a native Salesforce import, and HubSpot can sync lifecycle stage changes to both Google Ads and Meta. Check what your CRM already supports before building a custom pipeline.

In Google Ads, create one conversion action per CRM stage you’ll send, using the import option for conversions from clicks via CRM, files or other data sources. Data can arrive via scheduled file or Google Sheet uploads, the Google Ads API, or a CRM connector.

Each conversion row needs:

  • The click identifier (GCLID, GBRAID or WBRAID), hashed email and phone, or both
  • The conversion action name, exactly as it appears in Google Ads
  • The conversion time with time zone, which must be later than the click
  • Value and currency

Enhanced conversions for leads matches on hashed contact data instead of, or alongside, the click ID. Normalize first: trim and lowercase emails, format phone numbers in E.164 with the country code, then hash with SHA-256. Send both GCLID and email when you have them; the email rescues conversions where the ID was lost.

Mind the window. A conversion action’s click-through window maxes out at 90 days, and later conversions aren’t credited to the click. If your sales cycle runs longer, closed-won imports cover only your fastest deals, so earlier stages carry the bidding. Google also accepts adjustments, so you can restate a changed deal value or retract a junk lead.

Upload daily, and judge a new setup on a week of data, not the first morning.

Meta Conversions API for CRM events

For Meta, CRM stages go through the Conversions API as server events. Each event carries:

  • event_name: the stage, such as a custom QualifiedLead or the standard Purchase for closed revenue
  • event_time: when the stage changed, as a Unix timestamp
  • action_source: system_generated, the value Meta’s CRM integration specifies for stage events
  • user_data: hashed email and phone, plus fbc, fbp and the lead ID when you have them
  • custom_data: value and currency

Hash with the same normalization as Google. Events Manager shows an Event Match Quality score per event, and more identifiers generally mean better matching. For Meta instant form leads, the lead ID is your strongest identifier, and it lets Meta optimize lead campaigns toward leads that reach a chosen CRM stage.

Two practical constraints. Meta only accepts events with recent timestamps, so send stage changes daily rather than in a monthly batch. And Meta’s click attribution windows are measured in days, not months, so a deal that closes two months after the click usually won’t be credited. Meta learns best from stages leads reach soon after they submit.

CRM events come only from your server, so there’s no pixel event to deduplicate against. Sent flags guard against double counting, and a stable event_id per lead and stage makes repeats easy to spot.

Choosing which stages and values to send

Send two to four stages, not every lifecycle step. A typical B2B set:

StageGoogle Ads roleMeta roleValue sent
Lead (form fill)SecondaryWeb event, not from CRMNone or small
Qualified lead (MQL or SQL)Primary once volume allowsOptimization event for lead campaignsExpected value
Opportunity or meeting heldPrimary or secondaryCustom eventExpected value
Closed-wonSecondary, for reportingPurchaseActual first-year contract value

Pick the primary with a volume test: the deepest stage that still produces enough conversions for bidding to learn. Meta’s guidance is roughly 50 optimization events per ad set per week to exit the learning phase. For Google, a common working minimum is around 30 conversions a month per campaign. If the deep stage is too thin, bid on the stage above it and move down later.

Set values from your own funnel: expected value = stage-to-close rate × average first-year contract value. Hypothetically, with a $24,000 average first-year contract, a 20% SQL-to-close rate makes each SQL worth $4,800, and a 5% qualified-lead-to-close rate makes each qualified lead worth $1,200.

Value rules I hold every setup to:

  • One value logic for both platforms, computed in the CRM or pipeline, so Google and Meta compete on the same numbers.
  • One primary stage per campaign goal. If several stages are primary, bidding sums their values and counts the same deal twice.
  • Recalculate stage values quarterly from actual close rates, not once at setup.
  • First-year value, one currency. Skip lifetime value estimates you can’t verify yet.
  • Disqualified leads get nothing. Retract them in Google if they were already uploaded.

Validating the data loop

A loop that silently drops conversions teaches bidding a skewed picture. Check before changing bidding, then weekly:

  • Capture rate: the share of paid leads in the CRM with a click ID or contact data. Gaps point to broken form mapping, redirects stripping parameters or cookie issues.
  • Upload success: Google Ads diagnostics and Meta Events Manager show events received, with errors reviewed: unmatched click IDs, conversion times before the click, wrong action names, time zone offsets.
  • Match quality: Meta’s Event Match Quality and Google’s enhanced conversions diagnostics are stable or improving.
  • Reconciliation: CRM qualified leads from paid sources vs each platform’s reported conversions for the same period. Expect a stable gap; a sudden shift means something broke.
  • No duplicates: sent flags update after every successful upload, and a re-run uploads zero rows.
  • Test path: Meta’s test events tool and a small manual Google upload before any new stage goes live.
  • Observation period: a new stage runs as a secondary conversion for two to four weeks before bidding switches to it.

When the numbers hold, switch bidding one campaign at a time and expect a relearning period. It’s usually the first thing I build in marketing attribution work, since every later budget decision depends on it.

Get it built

If your ad platforms report cheap leads while sales complains about lead quality, a Growth Audit maps where the loop breaks and what to fix first. It’s $1,500 fixed and credited if we continue. See pricing or get in touch.

FAQ

Frequently Asked Questions

Do I need both GCLID imports and enhanced conversions for leads?

Send both identifiers when you have them. The GCLID gives Google an exact click match, and hashed email and phone recover conversions where the click ID was lost, such as a cleared cookie or a lead who came back on another device.

How long after the click can I upload an offline conversion to Google Ads?

Only within the conversion action's click-through window, which can be set to a maximum of 90 days. Deals that close later won't be credited to the click, so long sales cycles should bid on earlier stages and use closed-won for reporting.

Which CRM stage should be the primary conversion for bidding?

The deepest stage that still produces enough volume for the algorithm to learn, usually a sales-qualified lead or a held meeting. Keep raw leads and closed-won as secondary conversions until volume allows a deeper primary.

Can I send CRM stages back for Meta lead ads?

Yes. Store the lead ID Meta provides with each instant form lead, then send stage changes through the Conversions API with that ID. Meta can then optimize lead campaigns toward leads that progress in your CRM, not just completed forms.

How does consent affect offline conversion tracking?

Capture and send identifiers only for people who consented where the law requires it. Record consent status in the CRM next to the click IDs and filter on it before every upload.

Work with me

Let’s find your biggest growth lever

Tell me about your growth challenge. I’ll tell you honestly if I can help — and if I can’t, who can.

  • ✓ No obligation
  • ✓ No sales script
  • ✓ Honest feedback
  • ✓ Clear next steps