Skip to main content
Concrete CMS → Google AdsIntegration guide

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

  1. 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.

  2. 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.

  3. 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.

  4. 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. 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. 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. 3

    The identifier is the bridge

    The GCLID, captured at the visit and carried into the Concrete CMS order.

  4. 4

    The event source decides reliability

    Fire server-side. Page caching means the confirmation template may not execute.

  5. 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

  1. 01

    Count orders carrying the GCLID

  2. 02

    Follow one real conversion end to end

  3. 03

    Identify which commerce add-on is in use

    That decides where the order is created and what events exist to hook.

  4. 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.

  5. 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.

Get my free conversion tracking audit

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.

Get my free conversion tracking audit

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.

Free · 30 min

Get Concrete CMS and Google Ads joined properly

Free30 minutesNo obligation