How to Set Up Offline Conversion Tracking (Google Ads, GA4 & Meta)

A step-by-step implementation guide: capturing click IDs, three ways to build the pipeline, handling refunds, and the eight ways offline tracking silently breaks.

Your Google Ads account looks fine. Clicks are steady, forms are coming in, cost per lead is where you want it. Then sales tells you most of those leads went nowhere — and the handful that actually closed came from a campaign the algorithm had quietly stopped funding.

Nothing is broken. The platform simply cannot see what happened after the click. Offline conversion tracking is how you show it.

What offline conversion tracking does

Offline conversion tracking (OCT) sends conversions that happen away from your website — phone sales, in-store purchases, closed CRM deals — back to Google Ads, GA4 and Meta, matched to the ad click that produced the lead.

If you want the plain-English version first, start with what offline conversion tracking is and why it matters. This guide is the implementation side: how to actually build it, and everything that tends to go wrong.

Without it, the platforms optimise toward the cheapest early signal — a form fill. Two hundred unqualified enquiries at four pounds each will always look better in the interface than twelve at sixty that close at 40%. Feed real sales back in and bidding starts chasing revenue instead of volume.

Everything depends on the click ID

Almost every failed setup fails in the same place, and it is not the tag configuration.

Google Ads cannot recognise an offline sale on its own. When you upload a conversion you are saying: this specific click, which you already know about, eventually produced this much revenue. The only thing that makes that connection possible is the click identifier.

There are three, depending on how the visitor arrived:

  • gclid — a standard web ad click with auto-tagging enabled. The majority of desktop and Android traffic.

  • gbraid — app-based interactions on iOS 14 and later.

  • wbraid — web-based interactions on iOS 14 and later, where gclid is unavailable.

The problem is timing. B2B sales cycles run 30, 60, 90 days. Cookie lifetimes do not. By the time someone marks a deal Closed Won, the session that carried the click ID is long gone — and if you did not write that value onto the lead record at form submission, it no longer exists anywhere in your stack.

The rule that prevents most of the pain: capture the click ID at the first touch and store it on the lead in the same request. Do not plan to reconstruct it later from a cold CRM record. There is no reliable way to do that after the fact.

If you have inherited a setup where click IDs are already missing, no amount of tag fixing recovers them. That is an architecture gap, not a bug. The practical route is to match on a different key — email or an external customer ID — and let a matching layer restore the identifier before upload. Stape’s Enricher power-up does this, and the Google Ads Data Manager API supports user-identifier matching natively.

Three ways to build the pipeline

The right method depends less on budget than on what already exists: whether you have a real CRM, whether it can fire a webhook, and how fast the business needs the data to land.

  • Google Sheets pipeline — for no CRM, or a CRM with no Google Ads integration. Imports every 24 hours or weekly. Costs nothing.

  • Server-side GTM offline tag — when your backend or CRM can fire a webhook on a stage change. Near real time.

  • Data Manager API — Google’s current recommended path for new builds. Near real time, more developer involvement.

The direct server-GTM tag is now treated as a legacy approach next to the Data Manager API. Plenty of live accounts still run on it and there is no urgency to replace a working one — but for a fresh build, look at the API path first.

There is a fourth mechanism that does not create conversions at all: conversion adjustments, for correcting sales you already reported. If you have refunds or cancellations, you need it alongside whichever method you choose.

Method 1 — Google Sheets, no CRM needed

For businesses whose CRM is a spreadsheet and a sales team that keeps it updated. More capable than it sounds.

How the data moves

  • The lead submits a form, and web GTM captures the user data plus the click ID.

  • The web container forwards it to the server container using a Data Tag and Data Client pair, which gives field-level control over what crosses the boundary.

  • Server GTM writes one row per lead into a master All Leads sheet with a status of Inquiry.

  • Sales updates the status manually — the one habit the whole system depends on.

  • Stage sheets for MQL, SQL and Closed Won filter themselves from the master sheet.

  • Google Ads imports each stage as its own conversion action every 24 hours.

The columns that matter

Order matters, because the scheduled upload maps by column. A workable schema: Status, Email, Phone, GCLID, Conversion Name, Conversion Time, Conversion Value, Currency, and — for EU, EEA, UK and Swiss traffic — Ad Storage and Ad Personalization consent states.

The GCLID column is not the raw cookie. The gcl_aw cookie holds a prefixed, dotted string, so extract the identifier from it with a RegEx Table variable in the server container before writing the row. The exact pattern, plus the sheet templates, are in my free offline conversion tracking guide.

Timestamps: use UTC

Build a Custom JavaScript variable that emits an ISO 8601 timestamp, reading a timestamp URL parameter when present and falling back to the current time. It can convert to a named timezone, but leave it empty so it emits UTC unless you have a specific reason not to. Daylight-saving transitions are a real source of rejected uploads and UTC sidesteps them.

Worth knowing: the conversion time must be later than the original click. A timezone mismatch between your sheet and the Google Ads account can make a valid sale look like it happened before the click that produced it, and Google Ads rejects it without much explanation.

Setting it up in Google Ads

Create one offline conversion action per stage under Goals, choosing the offline option and skipping the data source setup. Categorise honestly — Qualified lead for an MQL, Purchase for a closed deal — because the category affects how Smart Bidding treats the signal.

Then schedule the upload under Goals, Uploads, Schedules. Google Ads gives you an email address; share the spreadsheet with it, link the sheet, set a frequency, and repeat for each conversion action.

Set expectations: the first sync takes 24 to 48 hours. Do not judge the pipeline before that window closes, and do not start changing settings in hour six — you will only make it harder to diagnose.

Method 2 — The server-side GTM offline tag

When your backend can fire a webhook the moment a deal closes, you can skip the spreadsheet and hit the Google Ads API directly. Import the offline conversion template into your server container and create a tag from it.

The fields that are not optional:

  • Conversion Action ID — the ctId parameter from the conversion action’s URL.

  • Customer ID — the account ID, no dashes.

  • Conversion Environment — set to UNSPECIFIED.

  • Conversion DateTime — formatted with a UTC offset, and later than the click.

  • Click identifier — one of gclid, gbraid or wbraid.

The copy-paste trap: the Conversion Action ID (ctId) is not the same value as the conversion reporting ID shown elsewhere in the interface. They look similar enough that people paste the wrong one and lose an afternoon debugging a tag that was never going to work.

On Stape, authenticate through a Google Ads connection in the admin OAuth flow. Off Stape you need the Google Ads API enabled in Google Cloud Console, a service account with the right permissions, and a developer token entered manually.

If the tag fires cleanly but Google Ads reports nothing, check the payload for the click identifier before touching anything else. That is the cause far more often than the tag configuration.

Refunds, cancellations and the ROAS you actually earned

Reporting the sale is half the job. If a meaningful share of those sales later evaporate, your ROAS is fiction — and Smart Bidding is optimising against fiction.

Conversion adjustments retroactively correct something you already reported. There are three types:

  • Retraction — cancels the conversion entirely. Cancelled bookings, failed payments, fraudulent orders.

  • Restatement — changes the value or currency. Partial refunds, downgraded contracts, revised deal sizes.

  • Enhancement — adds user identifiers without changing the value, to improve matching after the fact.

Identify the conversion by Order ID wherever possible. Falling back to the click ID only works if you stored it in the backend at the time of the original conversion — which brings you back to the discipline from the top of this article.

An HTTP 200 does not mean it worked. This is the most misleading behaviour in the whole workflow: the endpoint returns a 200 with the error inside the response body. The usual culprit is an Order ID in the webhook that does not match the one used in the original upload, so Google Ads cannot find the conversion to adjust — and says so, quietly, in a body nobody read. Run server GTM Preview, inspect the request, and read the response body rather than trusting the status code.

If you sell anything with a real cancellation rate — hotels, high-ticket services, subscriptions, anything with a cooling-off period — build adjustments in from day one. Retrofitting them after the numbers start looking implausible means months of poisoned bidding data.

Notes by CRM

The mechanism is identical everywhere: persist the click ID, push the closed deal back. What changes is where the identifier lives and how much the CRM does for you.

  • HubSpot — the native Google Ads integration handles much of it. Store the click ID as a custom contact property on submission and map deal stages to conversion actions.

  • Salesforce — lead field plus a Closed Won milestone. Watch for sandbox and production field mismatches.

  • Zoho — custom field on the lead, pushed via API on stage change. Currency handling needs attention on multi-market accounts.

  • GoHighLevel — capture into a custom field and fire a webhook on pipeline stage change.

  • Pipedrive — deal-level custom field, triggered on stage transition rather than deal creation.

  • Odoo — ERP-side mapping, where field discipline matters more than the tag configuration.

  • No CRM — use the Google Sheets pipeline above.

It is not only a Google Ads feature

The same closed loop applies across the stack, with different identifiers and endpoints:

  • GA4 — offline events arrive through the Measurement Protocol or data import, so the offline stage shows up in the same funnel and attribution reports as the online steps.

  • Meta — the Conversions API accepts offline events matched on the click ID or hashed customer data, which is what lifts Event Match Quality on lead-gen accounts.

  • Microsoft, TikTok and LinkedIn — each has an equivalent offline import. The identifier differs, the architecture does not.

Build the capture layer once. If the lead record carries every identifier you were given, adding a second or third platform later is a mapping exercise rather than a new project.

Eight ways it silently breaks

None of these throw an obvious error, which is exactly why they cost people months of bad data.

  • The click ID was never stored. Everything is configured correctly and nothing imports, because the payload has no identifier. Open one real lead record and look before touching the tag.

  • Conversion action name mismatch. A trailing space, different capitalisation, or a suffix in one place only. Compare the two strings character by character, not by eye.

  • A container was not published. It works in Preview and does nothing live, because only one of the two containers went out. Publish web and server after every change.

  • Timezone drift. The timestamp resolves to a moment before the click and the upload is rejected. Emit UTC and confirm the account timezone.

  • Judging it too early. Nothing appears after six hours, settings get changed, and now two variables have moved at once. Let the full window close.

  • Sheet permissions were never granted. Stage sheets show a reference error, stay empty, and the scheduled upload dutifully imports nothing.

  • The wrong ID in the tag. The conversion reporting ID was pasted where ctId belongs.

  • Adjustments returning a quiet 200. They look successful and change nothing, because the Order ID does not match the original upload.

Pre-launch checklist

  • Auto-tagging is enabled in Google Ads.

  • The click ID is captured on form submit and written to the lead record.

  • Conversion action names match exactly between source and Google Ads.

  • Timestamps emit UTC and post-date the click.

  • Both GTM containers are published after the final change.

  • Consent variables are built for EU, EEA, UK and Swiss traffic.

  • One real lead has been pushed end to end — a genuine status change, not a Preview event.

  • Conversion adjustments are configured if refunds or cancellations exist.

  • 24 to 48 hours have passed before the first verdict.

The test that actually proves it: take one real lead, change its status the way a salesperson would, and follow it into the Google Ads interface. Preview confirms a tag fires. It does not confirm the conversion landed, matched and reported.

Frequently asked questions

Do I need a CRM for offline conversion tracking?

No. A Google Sheet works as both the sales team’s status board and the data source for scheduled uploads. It is a viable production setup for small teams, with a 24-hour cadence rather than real time.

How long until offline conversions appear in Google Ads?

The first scheduled sync usually takes 24 to 48 hours. After that, sheet-based uploads run every 24 hours or weekly, and API or server-side methods are close to real time. Adjustments typically apply within a few hours and up to 24.

What happens if the GCLID is missing?

The conversion cannot be matched and will not import. Fix it at the source by capturing the identifier at form submission. For leads where it is already lost, match on email or an external customer ID using a matching layer such as Stape’s Enricher, or the Data Manager API.

Is offline conversion tracking GDPR-compliant?

It can be, and it is often more controlled than client-side tracking because you decide exactly which fields leave your systems. Pass consent state explicitly for EU, EEA, UK and Swiss traffic, and hash personal identifiers before transmission. Treat the specifics as a question for your own legal advisor.

Does it require server-side tracking?

Not strictly — Google Ads accepts manual uploads. But server-side GTM is what makes it reliable and automatic, and it lets the same captured data feed Meta and GA4 without rebuilding the capture layer each time.

Will it affect Smart Bidding?

Yes, and that is the point. Once real sales flow back in, bidding optimises toward the traffic that historically produces revenue. Expect a learning period while the signal accumulates, and avoid restructuring campaigns in the same window.

How is this different from enhanced conversions?

Enhanced conversions improve the matching of conversions that already happen online. Offline conversion tracking reports conversions that never happened online at all. They are complementary, and when you have both a click ID and an email, matching improves on both fronts.

Which businesses benefit most?

Any business where the sale finishes away from the website: B2B and high-ticket services, real estate, clinics, education, car dealerships, showroom retail, and anyone selling by phone, WhatsApp or invoice.

The short version

Offline conversion tracking is not a difficult build. It is an unforgiving one. Almost every failure traces back to a click ID that was never stored, or a name that did not match. Get those two right and the rest is configuration.

If you would rather not build it yourself, I set this up for businesses with and without a CRM — see offline conversion tracking services, or work through the free video guide and templates.

Need accurate tracking?

Its Free

500+ Happy Clients ⭐️

Keep Reading

See exactly where you’re wasting ad spend and how better tracking can double your sales.

See exactly where you’re wasting ad spend and how better tracking can double your sales.

Tracking in 3 Hours

Tracking in 3 Hours

I Manage Everything

I Manage Everything

24/7 Expert Support

24/7 Expert Support

TESTIMONIALS

Trusted by 500+ satisfied clients

Discover how we’ve driven growth and innovation.

500+ Tracking

500+ Tracking

Adélaïde De Vos

3,922 followers

I had the pleasure to work with Abdul and I can say that he exceeded my expectations. He was professional, patient, and clear in his explanations and committed to client satisfaction. If you're looking for someone who is not only highly skilled but also reliable and committed to client satisfaction, I highly recommend Kayium!

Dean Watson

1,030 followers

Kayium setup our tracking for Google Ads and Meta Ads, which helped us get 20%+ more conversions on the same ad spend. He didn’t just handle the technical setup,he also took the time to explain why it works and how it improves results. If you’re looking for someone skilled, reliable, and committed to delivering real results, I highly recommend him!

David Friend

CEO: Profitable Sites

Kayium set up accurate tracking that helped us scale ads fast and boost conversions by over 25%. He gave us clear insight into which ads drive revenue.

Lalita Sundari

7,924 followers

I've worked with Kayium; his strategic mindset and expertise in GTM, GA4, Pixel & Server Side Tracking, are invaluable! I highly recommend Kayium!