All integrations

Integration · Google Ads & GA4

Give Google back the conversions the browser lost

RoasProof captures the gclid on landing, keeps it through the whole customer journey, and reports the conversion straight to Google Ads with hashed identifiers attached, plus a matching GA4 event over the Measurement Protocol.

RoasProof reports conversions to Google Ads through click conversion uploads: the gclid (or wbraid/gbraid) captured on landing is stored in first-party storage, attached to the eventual order, and uploaded with hashed identifiers for Enhanced Conversions. The same conversion is also sent to GA4 via the Measurement Protocol, so ads and analytics agree.

gclid · wbraid · gbraidEnhanced Conversionsoffline click uploadsGA4 Measurement Protocol

A click conversion upload, as Google Ads receives it

Orders are reported through the Google Ads API as click conversions. That's the same mechanism Google recommends when the browser can't be trusted to fire a tag.

google ads api · uploadClickConversions
POST /v20/customers/{customer_id}:uploadClickConversions

{
  "conversions": [{
    "gclid":              "Cj0KCQjwm5e5BhCCARIsA…",
    "conversionAction":   "customers/8613…/conversionActions/9145…",
    "conversionDateTime": "2026-06-21 09:40:17+00:00",
    "conversionValue":    184.50,
    "currencyCode":       "EUR",
    "orderId":            "84213",
    "userIdentifiers": [
      { "hashedEmail":       "9f3d0c52ab…" },
      { "hashedPhoneNumber": "1b6e21c84f…" }
    ],
    "consent": {
      "adUserData":        "GRANTED",
      "adPersonalization": "GRANTED"
    }
  }],
  "partialFailure": true
}
  • The gclid was saved a week earlier

    Captured on the landing page, stored first-party against the visitor, and attached to the order at purchase, days or weeks after the URL parameter disappeared.

  • Timestamps land in the right column

    conversionDateTime carries the actual order time with timezone offset, so conversions appear on the correct day in your reports instead of whenever an upload batch ran.

  • orderId keeps uploads idempotent

    Retries and re-uploads of the same order carry the same orderId, so a delivery hiccup on our side can never become a duplicate conversion on yours.

  • Consent signals included

    Consent status recorded at capture time is forwarded with each conversion, as required for uploads covering EEA traffic.

gclid, wbraid, gbraid: captured and persisted first-party

Google splits its click IDs across three parameters depending on platform and privacy state. We capture whichever one arrives and keep it for the whole conversion window.

stored click record
gclid
Cj0KCQjwm5e5BhCCARIsA…
wbraid
-
gbraid
-
utm_campaign
brand-search-us
landing
/products/trail-jacket
captured
2026-06-14 09:41:22 UTC
attached_to
order #84213
  • All three parameters, one record

    gclid for standard web clicks, wbraid and gbraid for iOS traffic where Google withholds the full click ID. Whichever arrives is stored against the visitor identity.

  • Persistence beats cookie lifetimes

    The click ID lives in first-party storage on your domain, tied to the visitor rather than to a cookie Safari deletes after seven days. A purchase three weeks later still uploads with its click attached.

  • Usable for the full click window

    Click conversions can be reported well after the click. Because the ID never gets lost, late conversions (subscriptions, B2B deals, considered purchases) still land in Google Ads.

What exactly is a gclid and how long does it stay usable? See the gclid glossary entry, and how server-side tracking keeps it alive past browser limits.

Hashed identifiers, for when the click ID alone isn't enough

Enhanced Conversions let Google match conversions using hashed first-party data. We support both flavors, populated from the same identity graph that resolved the order.

Enhanced Conversions for web

Hashed email and phone ride along with conversions your tag already measures, recovering matches that third-party cookies used to provide. Your existing conversion actions keep working. They just match more often.

Enhanced Conversions for leads

For lead-gen funnels where the sale closes offline, Google matches the hashed email or phone from the original lead back to the ad click on its side, so you don't need a gclid at conversion time.

identifiernormalizationwhere we get it
hashedEmailTrimmed, lowercased, then SHA-256 hashedOrder or lead email from your store, form, or API event
hashedPhoneNumberE.164 format, then SHA-256 hashedCheckout or lead-form phone, country-normalized
address info (optional)Hashed first/last name with plain city, region, and postal codeBilling or shipping address on the order, when you enable it

Keep GA4 telling the same story as Google Ads

The same resolved conversion is also sent to GA4 server-side, so your analytics, your ad platform, and your bank account finally agree.

  • client_id recovered from the session

    The _ga client ID is captured on-site and stored with the visitor, so the server-sent purchase attaches to the same GA4 user and session as their browsing did.

  • transaction_id prevents double counting

    GA4 deduplicates purchases by transaction ID. The server event carries the order ID, so it merges cleanly with anything your gtag already reported.

  • Session attribution preserved

    session_id is included with each event, so source/medium attribution stays intact and server conversions don't get dumped into (not set).

ga4 measurement protocol · purchase
POST https://www.google-analytics.com/mp/collect
     ?measurement_id=G-8K2P4XQ&api_secret=•••

{
  "client_id": "1191633108.1780828882",
  "events": [{
    "name": "purchase",
    "params": {
      "transaction_id": "84213",
      "value":          184.50,
      "currency":       "EUR",
      "session_id":     "1781429900"
    }
  }]
}

Uploads you can audit, row by row

Google Ads uploads are batched and partially failable: one bad row shouldn't sink the batch, and no failure should be invisible.

Continuous batched uploads

Conversions upload on a rolling schedule, well inside the click window. New orders typically reach Google Ads within minutes of the order webhook arriving.

Partial failures, surfaced

Uploads run with partialFailure enabled, and per-row errors are shown next to the exact conversion they affected: an unparseable gclid, a click older than the window, a mismapped conversion action.

Per-conversion status & replay

Every conversion shows its upload status, request, and response. Fix the cause (a wrong conversion action, a revoked OAuth grant) and replay failed rows with one click.

Stop letting Google guess which clicks converted.

Connect your Google Ads account, map a conversion action, and your next order uploads with its gclid attached, verified end to end before you go live.