Bitrix24 is a solid CRM for the mid-market — Russian/CIS lead-gen agencies and service businesses run their entire pipeline through it. The default Google Ads integration captures a lead from a web form and inserts it as a Bitrix Lead entity. What almost nobody sets up is the return path: when the Lead becomes a Deal, when the Deal moves to Qualified, when the Deal is Won — none of those events flow back to Google Ads or GA4 by default. The advertising platform sees only the top of the funnel and optimises accordingly.
For any service business with a sales cycle longer than a day, this is a much bigger attribution gap than Consent Mode or iOS 14.5. If your average customer is worth 3 000 € and only 8% of form-fills become customers, the “450 ₽ lead” Google Ads reports has an effective per-customer cost of 70 000 ₽ that neither your ad account nor your CRM connects to the right campaigns. Smart Bidding is guessing.
The Loop, End to End
| Stage | What must happen | Where it usually breaks |
|---|---|---|
| 1. Ad click | gclid lands in URL, captured to cookie/localStorage | Missing capture script or SPA that strips the query string |
| 2. Form submit | gclid + _ga stored as hidden fields on the form | Marketer added form via Bitrix builder without hidden fields |
| 3. Lead created in B24 | Custom fields UF_GCLID, UF_GA_CID populated | Fields don't exist or aren't mapped in Lead form |
| 4. Lead → Deal | Custom fields copied to Deal entity via workflow | Default Bitrix migration drops most custom fields |
| 5. Deal stage change (Qualified / Won) | Webhook triggers Google Ads OCI + GA4 MP upload | No webhook or no upload script listening |
| 6. Google Ads offline conversion | Upload with gclid + conversion action + value | Conversion action not created; upload fails silently |
| 7. GA4 Measurement Protocol | Server event with client_id and CRM stage | Session source lost — see the MP trap piece |
Each stage is a small piece of glue. Together they close the loop. Miss any one and the whole chain fails silently — the deal Won stage happens, nothing goes back to Google Ads, and your bidding stays blind.
Stage 1–2 — Capturing gclid at Form Submit
The gclid arrives as a query parameter on the landing page. On any SPA or multi-step funnel, that gclid disappears the moment the user navigates. The reliable pattern:
gclid, gbraid, wbraid, and _gcl_aw from the URL and document.cookie. Store all four in localStorage with a 90-day expiry timestamp. On form submit, hydrate hidden fields from localStorage. Do not rely on the Bitrix form builder's “auto-capture UTM” feature — it only reads the current URL, not stored values.Alongside the click IDs, capture GA4's _ga cookie value and pass it as a hidden ga_client_id. This is the cross-key that lets you send GA4 Measurement Protocol events later with the same client identity as the browser session, keeping the user unified across CRM stages.
For Bitrix24's native form widget, add the hidden fields in the form designer under “Additional fields — Hidden.” Bind them to the CRM custom fields (see next section). For custom forms, POST directly to the crm.lead.add REST endpoint with the hidden field values in the payload.
Stage 3 — Custom Fields in Bitrix24
You'll need these custom fields, at minimum. Create them once on both Lead and Deal entities (Bitrix has separate custom-field namespaces per entity type — this is the mistake that eats most implementations).
UF_GCLID— string, max 255UF_GBRAID— string, for iOS trafficUF_WBRAID— string, for web-to-app iOSUF_GCL_AW— string, Google Ads cookieUF_GA_CID— string, GA4 client IDUF_UTM_SOURCE,UF_UTM_MEDIUM,UF_UTM_CAMPAIGN— as stringsUF_FIRST_TOUCH_TS— datetime, first form submit
Bitrix's default Lead→Deal migration only copies the standard fields. Custom fields need an explicit workflow rule: “When Lead moves to Deal, copy UF_* fields from Lead to Deal.” Set this up under Automation → Workflows → Lead entity → conversion trigger.
UF_GCLID populated. Every Deal had the field empty. Reason: workflow never wrote it during conversion. 100% of deals — 30–50 per month at 200 000 ₽ average value — were running without click-ID attribution. Google Ads Smart Bidding had zero signal beyond form-fills for 18 months. Adding one workflow rule (2 hours of setup) plus wiring the deal-stage webhook (6 hours) recovered per-campaign ROAS visibility. Best-performing campaign turned out to be a small remarketing group — historically capped at 200 ₽/day — that had been generating a third of all won revenue.Stage 5 — Deal-Stage Webhooks
Bitrix24 supports outgoing webhooks per entity event. The two you need are:
Fires on every stage transition. Filter server-side to the stages you care about — usually “Qualified” (SQL — high-value soft signal for Smart Bidding) and “Won” (primary conversion). The payload includes the deal ID; your handler fetches the full deal via crm.deal.get to read the custom fields.
Some Bitrix deployments have stage.change disabled or delayed by up to 24 hours. Deal.update fires reliably on any edit; check the stage inside your handler and dedupe on deal_id + stage_id to avoid double-uploads if a sales rep re-saves the record.
Register the webhook via Bitrix REST: event.bind with event=OnCrmDealUpdate and your handler URL. The handler should be a small server (Cloud Run, VPS, Vercel Function) that receives the payload, validates it against a shared secret, and enqueues the upload to Google Ads and GA4.
Stage 6 — Google Ads Offline Conversion Import (OCI)
For each stage you care about, create a Google Ads conversion action of type “Import → Other data sources or CRM → Import from clicks (ClickConversion).” Two actions minimum:
- Deal Qualified: secondary conversion, count = one per, include_in_conversions_metric = false, value = 0 (or lifetime-adjusted weighting)
- Deal Won: primary conversion, count = one per, include_in_conversions_metric = true, value = actual deal amount
Upload via the Google Ads API UploadClickConversions endpoint. The payload keys on gclid (or gbraid/wbraid for iOS) and requires a conversion timestamp within the click's look-back window (default 90 days). Set conversion_value to the actual deal value and currency_code to the account currency.
Stage 7 — GA4 Measurement Protocol
Google Ads OCI covers the ad-side attribution but not the analytics side. For GA4 to see the same deal stages (and for you to be able to segment users in Explore reports by SQL/Won status), fire GA4 Measurement Protocol events from the same webhook handler.
Use the client_id stored in UF_GA_CID. The event should have a specific name (deal_qualified, deal_won) and include the deal value as value. Watch the classic MP trap — the session source will be missing unless you handle it. See the MP session-source piece for the Custom Channel Group workaround.
Do not use MP for the primary Ads conversion — GA4 Ads-linked conversion actions won't import MP-triggered events reliably. Keep OCI as the authoritative bid signal; MP as the reporting mirror.
Common Failure Modes
The single most common failure. Lead→Deal workflow never copies the UF fields. Fix: workflow rule with explicit field copies.
User clicks the ad Monday, submits the form Wednesday. Without localStorage persistence, the Wednesday session has no gclid. Fix: 90-day localStorage store, hydrate on form load.
Google Ads OCI rejects clicks older than the account's look-back window (default 90 days, extendable to 540). B2B sales cycles > 3 months routinely blow past this. Extend the click look-back window in the conversion action settings before you start uploading.
If the form submit already fires an online Google Ads conversion, the OCI upload on stage change will create a second conversion for the same deal. Fix: give them distinct conversion actions with distinct goal categories, so bidding uses each without double-counting.
What Success Looks Like
| Metric | Before OCI loop | After OCI loop |
|---|---|---|
| Google Ads conversion signal | Form submits only | Form + SQL (secondary) + Won (primary) |
| Smart Bidding optimises for | Lead volume, indifferent to quality | Revenue-weighted qualified leads |
| Per-campaign ROAS visibility | None — every campaign looks similar | Full — bad campaigns visible within 60 days |
| Budget reallocation confidence | Gut-based, monthly | Data-driven, weekly |
We measure the loop's value not in a single number but in the decisions it makes possible. On a typical B2B services account, closing the loop reveals that 60–80% of new revenue is driven by 20–30% of the campaigns. Without the loop, every campaign gets equal budget consideration; with it, the actual winners get scaled and the losers get paused within one quarter.
Audit Checklist
event.get. Should list your handler URL bound to the event.Why Now
Google Ads has been quietly deprecating anything that looks like inference-based conversion tracking in favour of explicit signals — data-driven attribution needs deal-stage data to differentiate signal weight, Smart Bidding relies on primary/secondary flags (see the Smart Bidding lever piece) that only mean something when the underlying data is CRM-truth. A Bitrix24 account without OCI wired to Google Ads in 2026 is running blind in a way it wasn't in 2022.
The loop is 20–40 hours of setup depending on your existing state. On any services or B2B account with a sales cycle longer than a week, it's the highest-ROI piece of tracking work available. See how we approach it inside conversion tracking audits.