Connecting Concrete CMS to Google Ads
Concrete CMS is a self-hosted PHP CMS used by small organisations and agencies, typically with commerce added through an add-on rather than built in. Google Ads knows what you spent and which click it came from, and nothing at all about what happened afterwards. The join between them succeeds or fails on one thing: whether the GCLID reaches the Concrete CMS order before the conversion happens, because Google Ads can only match a conversion it can tie back to a click it recognizes.
Free30 minutesNo obligation
Specific to this pair
Concrete CMS to Google Ads: gclid saved as an order attribute
On cached Concrete CMS pages, capture gclid, gbraid or wbraid in the browser into a 90-day first-party cookie, then save it as an order attribute at order creation. A scheduled job can upload paid orders through the Google Ads API to an import-type action with total, currency and order ID within 90 days, with retractions for refunds.
For Google Ads the identifier is the gclid, and on a Concrete CMS site it has to be caught before the page cache gets involved. A cached landing page is served without your PHP running for that request, so a server-side read of ?gclid= silently fails for any visitor who hits a cached URL. Capture it in the browser instead, with a small script that writes gclid, gbraid or wbraid to a first-party cookie with a 90-day expiry, then read that cookie in PHP when the commerce add-on creates the order and save it as an order attribute.
From there you have two routes. Enhanced conversions on the website tag works if the confirmation page is excluded from caching and can output the order email for hashing. Offline import is sturdier on Concrete because the orders sit in your own database: a scheduled job queries paid orders that carry a gclid and uploads them through the Google Ads API to an import-type conversion action, with order total, currency and order ID, within 90 days of the click.
The common double count is the old website-tag purchase action left as primary while the new import action is added; make one primary and the other secondary. Orders the add-on marks refunded or cancelled can be sent as retraction adjustments against the same order ID. On lead-gen Concrete sites, the gclid goes into a hidden field on the Express form, and the upload happens when the enquiry becomes a paying customer.
Concrete CMS → Google Ads · what breaks
Why this join usually fails — Concrete CMS → Google Ads
- 01
The GCLID never reaches Concrete CMS
Full page caching and the add-on ecosystem both interfere. Because commerce is an add-on rather than core, where the order is created differs by which add-on is installed.
- 02
Commerce as an add-on, not a core feature
Which add-on is installed determines the entire integration surface, so nothing transfers between two Concrete sites without checking first.
- 03
The conversion action is the wrong type
Uploads against a standard website conversion action fail. The action has to be created as 'Import' — and existing actions cannot be converted, so this is discovered late and requires starting a new action with no history.
- 04
Nothing reconciles afterwards
Google Ads reports uploads in Goals → Conversions → Uploads, with rows accepted and rows failed. A green result means the file parsed, not that the clicks matched. The number to watch is how many conversions actually appear against campaigns afterwards.
Concrete CMS → Google Ads · the fix
What working looks like — Concrete CMS → Google Ads
The GCLID on every order
Conversions arriving in Google Ads
Conversions appear against the campaign, ad group and keyword that produced the click, with the value you sent — which is what lets Smart Bidding optimize toward revenue instead of toward form fills.
Reconciled against the source
Concrete CMS → Google Ads · architecture
How Concrete CMS and Google Ads actually connect
- 1
Concrete CMS holds the truth
Self-hosted means you own and can query the data directly, which makes reconciliation straightforward once the identifier is present.
- 2
Google Ads needs a click to match
Google Ads matches an uploaded conversion back to a click using the GCLID. The conversion action must be created as an import type — an upload against a website-tag conversion action is rejected. Uploads must also land inside Google's window: the click has to be within the last 90 days.
- 3
The identifier is the bridge
The GCLID, captured at the visit and carried into the Concrete CMS order.
- 4
The event source decides reliability
Fire server-side. Page caching means the confirmation template may not execute.
- 5
Deduplication at the destination
Google deduplicates on the combination of GCLID, conversion action and conversion time. Uploading the same click twice against the same action at the same timestamp is rejected rather than double-counted, but uploading it against a second conversion action counts twice — which is how most double-counting here actually happens.
Concrete CMS → Google Ads · normal or broken
Working vs. broken, side by side — Concrete CMS → Google Ads
Normal, not a fault
The GCLID present on the order
Sent from the order-completed event from your commerce add-on
Deduplicated correctly
Google deduplicates on the combination of GCLID, conversion action and conversion time. Uploading the same click twice against the same action at the same timestamp is rejected rather than double-counted, but uploading it against a second conversion action counts twice — which is how most double-counting here actually happens.
Reconciles with the source
Actually broken
The GCLID missing on most records
Full page caching and the add-on ecosystem both interfere. Because commerce is an add-on rather than core, where the order is created differs by which add-on is installed.
Sent from the browser
Which add-on is installed determines the entire integration surface, so nothing transfers between two Concrete sites without checking first.
Counted twice, or not at all
Uploads against a standard website conversion action fail. The action has to be created as 'Import' — and existing actions cannot be converted, so this is discovered late and requires starting a new action with no history.
Nobody has reconciled it
Concrete CMS → Google Ads · diagnose
Diagnostic order — Concrete CMS → Google Ads
- 01
Count orders carrying the GCLID
- 02
Follow one real conversion end to end
- 03
Identify which commerce add-on is in use
That decides where the order is created and what events exist to hook.
- 04
Check the conversion action type and the upload diagnostics
In Google Ads, Goals → Conversions → Uploads shows every upload with its error rows. Read the errors rather than the success count; a file can import successfully with most rows rejected.
- 05
Read the match rate, not the success message
Google Ads reports uploads in Goals → Conversions → Uploads, with rows accepted and rows failed. A green result means the file parsed, not that the clicks matched. The number to watch is how many conversions actually appear against campaigns afterwards.
Concrete CMS → Google Ads · prove
How it gets proven — Concrete CMS → Google Ads
Source of truth
Your own database's order records, at agreed states.
- The GCLID confirmed present on a live order.
- The Uploads diagnostics read row by row, with the accepted count reconciled against conversions appearing in campaign reporting.
- Order attribute confirmed populated on a purchase through a cached page.
Concrete CMS → Google Ads · free audit
What we check in the free audit
- Count orders carrying the GCLID
- Follow one real conversion end to end
- Identify which commerce add-on is in use
- Check the conversion action type and the upload diagnostics
- Read the match rate, not the success message
Checked against
Your own database's order records, at agreed states.
Free30 minutesNo obligation
Concrete CMS → Google Ads · when not to buy
When you don't need this — Concrete CMS → Google Ads
- Measure identifier coverage yourself first — pull your last hundred orders and count how many carry the GCLID.
- If your Concrete site is brochure-only with enquiries by form, treat it as a lead-gen site rather than a commerce one.
- If your sales close inside a few days and your website tag already reports accurately, you may not need offline import at all. It exists to solve the delay between click and revenue.
Concrete CMS → Google Ads · what we deliver
What gets built — Concrete CMS → Google Ads
Identifier capture into Concrete CMS
Capture the identifier and persist it as order attribute data through an event listener, server-side.
Event source: the order-completed event from your commerce add-on
Fire server-side. Page caching means the confirmation template may not execute.
Dispatch to Google Ads
Offline Conversion Import through the Google Ads API, or a scheduled upload. Enhanced conversions for leads where GCLID coverage is poor and you have consented email addresses.
Reversals where they exist
Order state changes recorded by the add-on.
Written guarantee
95%+ tracking accuracy
Measured against Your own database's order records, at agreed states.. Miss it and we keep working at no cost.
From $400 · See packages
FAQ
Concrete CMS → Google Ads questions, answered
Capture it into a first-party cookie in the browser, since cached pages skip PHP, then read the cookie when the commerce add-on creates the order and save it as an order attribute.
Yes. Because the orders are in your own database, a scheduled job can query paid orders with a stored gclid and upload them through the Google Ads API to an import-type conversion action.
Almost always because the GCLID never reached the Concrete CMS order. Full page caching and the add-on ecosystem both interfere. Because commerce is an add-on rather than core, where the order is created differs by which add-on is installed. Measure coverage before debugging the dispatch.
The GCLID — the click ID Google appends to your landing page URL when auto-tagging is on. For iOS App campaigns and some Shopping traffic you will see GBRAID or WBRAID instead, and those behave differently: WBRAID cannot be used with user-provided data in the same way, and neither joins to an individual user. Enhanced conversions for leads is the alternative path, matching on hashed email or phone rather than a click ID, and it is the right choice when GCLID coverage is poor.
The order-completed event from your commerce add-on. Fire server-side. Page caching means the confirmation template may not execute.
Google Ads reports uploads in Goals → Conversions → Uploads, with rows accepted and rows failed. A green result means the file parsed, not that the clicks matched. The number to watch is how many conversions actually appear against campaigns afterwards.
More on Concrete CMS → Google Ads
- Craft → Google AdsConnecting Craft CMS to Google Ads
- Concrete CMS → Microsoft AdsConnecting Concrete CMS to Microsoft Ads
- Concrete CMS → Apple Search AdsConnecting Concrete CMS to Apple Search Ads
RELATED GUIDES
Where Concrete CMS → Google Ads fits in the rest of your tracking
- Google Ads · Local servicesGoogle Ads conversion tracking for local service businesses
- Google Ads · B2BGoogle Ads conversion tracking for B2B companies
- Google Ads × Ecommerce OrdersHow to reconcile Google Ads against your store's order table
- Google Ads · Comparison page → demoHow to track comparison page visit to demo request for Google Ads
- Duda → Google AdsConnecting Duda to Google Ads
- Concrete CMS → TikTokConnecting Concrete CMS to TikTok Events API
- Local servicesConversion tracking for local businesses, where most conversions bypass the website
- Webflow → Google AdsConnecting Webflow to Google Ads
Free · 30 min
Get Concrete CMS and Google Ads joined properly
Free30 minutesNo obligation
