Why send CRM stages at all
Automated bidding, such as Google’s Smart Bidding or Meta’s delivery optimisation, learns from the conversions you report. In B2B the first conversion, usually a form fill or a demo request, predicts revenue poorly. Cheap leads often come from people who will never buy, and a bidder rewarded for leads will keep buying more of them.
An offline conversion is an event that happened outside the platform’s view, in your CRM, sent back and matched to the original click or person. Once the platform sees which clicks became sales-qualified leads or opportunities, and what they were worth, it can bid for more people like them. For most B2B advertisers this is the biggest lever on lead quality they have.
Which stages to send
| Stage | When it fires | Value to send | What it teaches the bidder |
|---|---|---|---|
| Lead | Form fill, sign-up or booking | None, or a small fixed amount | Volume to learn from, weak on quality |
| SQL | Sales accepts the lead | An expected value, if you use one | The first signal that separates real buyers from the rest |
| Opportunity | Opportunity created in the CRM | The pipeline amount | Quality with a value, within weeks of the click |
| Closed-won | Deal won | Revenue, first-year or contract value | The truest signal, but slow and rare |
Create one conversion action per stage on each platform and choose which one bidding optimises toward. A common set-up bids toward SQLs or opportunities and records the other stages for reporting.
How each platform matches an offline conversion
A conversion only helps if the platform can tie it to someone it showed an ad to. That takes a click id stored at the visit, a hashed e-mail address, or both.
| Platform | Click id | Hashed identifier | Where Demander sends it |
|---|---|---|---|
| Google Ads | gclid, gbraid or wbraid | SHA-256 e-mail | Data Manager API (events:ingest); the older click-conversion upload for accounts that already use it |
| Microsoft Advertising | msclkid | Not used in Demander’s upload, which matches on the click id | Offline conversions (OfflineConversions/Apply), one goal name per stage |
| Meta | fbclid, sent as fbc | SHA-256 e-mail | Conversions API, with an event id for deduplication |
| li_fat_id | SHA-256 e-mail | Conversions API (/conversionEvents), one conversion rule per stage | |
| TikTok | ttclid | SHA-256 e-mail | Events API, into a CRM event set |
| rdt_cid | SHA-256 e-mail | Conversions API |
X and Sklik are not part of Demander’s offline uploads. LinkedIn’s Conversions API needs a separate approval from LinkedIn.
Platform notes
Google. Server-side conversion imports moved to the Data Manager API, which accounts starting to upload since 15 June 2026 have to use; existing users of the Google Ads API click-conversion upload can stay on it for now. Each event goes to a conversion action by id, carries a transaction id for deduplication, and can carry the person’s consent state for ad user data and ad personalisation.
Microsoft Advertising. Offline conversions match on the msclkid, so auto-tagging of the Microsoft Click ID has to be on and the id has to survive from the landing page to your CRM. Each stage needs an offline conversion goal, referenced by its name.
Meta. The Conversions API takes an event name, a Unix timestamp, an action source and user data. A stored fbclid becomes the fbc parameter, in the form fb.1 followed by the click time in milliseconds and the fbclid. If the browser pixel also reported the same event, send the same event id so Meta counts it once.
LinkedIn. Matching uses LinkedIn’s first-party click id, li_fat_id, and the SHA-256 e-mail. Each stage is a conversion rule in Campaign Manager, referenced by id, and values go as an amount with a currency code.
Timing windows
Platforms limit how old a click or an event may be, and they change those limits. Check the current documentation before you depend on a number; the patterns below hold either way.
-
01
The clock usually starts at the click
Google and Microsoft attach an offline conversion to the original click, and it only counts if it lands inside the conversion action’s click window, which tops out at 90 days. A deal that closes six months after the click cannot be credited to it.
-
02
Some platforms want events soon after they happen
Meta expects events close to the time they occurred and refuses web events older than seven days. Send each stage when it changes instead of saving them for a monthly batch.
-
03
Long cycles favour early stages
If your sales cycle is longer than the window, most closed-won deals arrive too late to count. SQL and opportunity creation usually fall inside it, which is one more reason to bid on an earlier stage.
-
04
Send the time the stage changed
Use the moment the opportunity was created as the event time. The platform compares that timestamp with the click, so an upload date in its place distorts both the window and the delay it learns from.
-
05
Upload often
Hourly or daily uploads keep the bidder current. Demander uploads every hour and moves its watermark only after a successful upload, so an outage skips nothing, and switching a workspace from sandbox to live sends the backlog.
Hashing done right
When no click id is available, most platforms can match on a hashed e-mail address. The standard is SHA-256 of the address after trimming spaces and converting it to lower case, sent as a hexadecimal string. Hash once, on your server, and never send the raw address.
Avoid extra normalisation. Removing dots or plus tags from Gmail addresses helps on some platforms and loses matches on others, so Demander leaves them alone.
Hashing is pseudonymisation, and the GDPR still treats the result as personal data: the platform hashes its own users’ addresses the same way precisely so it can match them. A hashed e-mail needs the same lawful basis as the address itself.
import { createHash } from 'node:crypto';
export function sha256Email(email: string): string {
const normalised = email.trim().toLowerCase();
return createHash('sha256').update(normalised).digest('hex');
}
The normalisation and hash Demander applies. Addresses are hashed before they reach the upload code, and only for contacts with a basis for ad measurement.
Consent in the EU and the UK
A click id is an advertising identifier. Storing it at the visit and later sending it back to the ad platform needs the visitor’s consent to marketing. Demander’s tracker keeps gclid, fbclid, li_fat_id and the other click ids only after marketing consent, and treats Global Privacy Control or Do Not Track as no consent, whatever the banner says. An upload carries only the identifiers of the person who converted, never those of a colleague at the same company: a CRM stage (SQL, opportunity, won deal) carries those of the lead it came from. That is the most recent form, sign-up, booking or other lead conversion at that company in the 90 days before, with one from a known contact preferred.
Hashed e-mails follow the same logic. For people in the EU, the EEA, the UK or Switzerland, Demander includes one only when the person agreed to ad measurement (the ad_user_data flag in the server events API, or a tool you marked as collecting that consent). Consent to marketing e-mail is not consent to ad measurement, so it does not count there; elsewhere it still does. People who used the ads opt-out page or sent Global Privacy Control are left out of uploads entirely. Google’s Consent Mode v2, required in the EEA since March 2024, has signals for ad user data and ad personalisation, and Data Manager events can carry them per event; Demander adds them when it knows the person’s choice.
Booking and form tools need the same care. If a tool collects consent for ad measurement, mark it as such in Demander; otherwise its click ids and e-mails stay out of the upload.
Setting it up with Demander
-
Install the tracker with your consent banner
The snippet keeps click ids from consented visits and ties each visit to its campaign and ad through UTM parameters.
-
Connect the CRM
HubSpot, Pipedrive or Salesforce. Stage changes become events: SQL, opportunity created and closed-won, each with its value.
-
Map stages to conversion actions
In each ad platform integration, give the conversion action, rule or goal for each stage. Conversions you defined yourself, such as demo_booked, can map to their own action by event name.
-
Check the match preview
Before anything is sent, a preview shows how many events each platform would match and why the others would be skipped, for example no click id and no consented e-mail.
-
Switch to live
Nothing is uploaded in sandbox. In live mode the upload runs every hour, under a stable id per opportunity and stage so retries never double count.
Questions people ask
Do offline conversions work without click ids?
Partly. Google, Meta, LinkedIn, TikTok and Reddit can match on a hashed e-mail, which needs the person’s consent to ad measurement. Demander’s Microsoft upload needs the msclkid. Expect lower match rates on e-mail alone, since people often see ads while signed in with a personal address and fill in forms with a work one.
Which stage should bidding optimise toward?
The latest stage that still happens often enough and soon enough after the click. For most B2B accounts that is SQL or opportunity created. Closed-won deals are usually too few and too late for a bidder to learn from.
Will the same conversion be counted twice?
Not if every event carries a stable id. Demander uses the opportunity id with the stage, so a retried upload is deduplicated, and an event the browser pixel also reported is counted once when both carry the same event id.
Does this replace the platform’s pixel or tag?
No. The pixel records what happens on your site; offline conversions add what happens afterwards in the CRM. Run both, with consent, and send the same event id from both sides where an event is reported twice.