Offline Conversion Import Setup
The problem: conversions that happen outside the click session
Google Ads can only see what happens in or immediately after an ad click session unless you tell it otherwise. For B2B sales cycles, car dealerships, insurance quotes, or anything with a sales-assisted close, the actual revenue event happens in a CRM, days or months after the click, with no browser context left to report back to. Offline Conversion Import (OCI) is the mechanism for feeding that later-stage conversion back to the original click, so Smart Bidding can optimize toward actual revenue instead of just lead form submissions.
The join key: GCLID, GBRAID, or WBRAID
OCI works by matching a conversion record back to the click that originated it, using a click identifier captured at lead time. On the web, this is the gclid URL parameter — it must be captured into a hidden form field (or CRM field) at the moment the lead converts, since it isn't available anywhere later in the funnel unless you stored it. For iOS app conversions post-ATT, gbraid (for non-SKAdNetwork opted-in tracking) and wbraid (web-to-app) are the respective equivalents. Without a captured click ID on every lead record, offline import for that lead simply isn't possible — there's nothing to match against.
// On form render: capture gclid from the URL and persist it in a cookie
// so it survives multi-page funnels before being written to a hidden form field.
function captureGclid() {
var params = new URLSearchParams(window.location.search);
var gclid = params.get('gclid');
if (gclid) {
document.cookie = 'stored_gclid=' + gclid + '; max-age=7776000; path=/'; // 90 days
}
var stored = document.cookie.split('; ').find(function(row) {
return row.startsWith('stored_gclid=');
});
var hiddenField = document.querySelector('input[name="gclid"]');
if (hiddenField && stored) {
hiddenField.value = stored.split('=')[1];
}
}Import paths: bulk upload, API, or Zapier-style connectors
Three practical paths exist to get offline conversions into Google Ads. The Google Ads UI's manual CSV upload (Tools > Conversions > Uploads) works for low-volume, manual processes but doesn't scale. The Google Ads API's OfflineUserDataJobService (and the newer click conversion upload endpoints) is the production path for any CRM with engineering resources to build the integration — typically a scheduled job that queries 'newly closed-won deals with a stored gclid' and POSTs them on a cron. Salesforce, HubSpot, and most major CRMs also support this via native Google Ads integrations or third-party connectors (e.g. Supermetrics, Zapier) when a custom API integration isn't justified.
Conversion value and conversion time both matter for Smart Bidding
conversion_date_time (the actual click timestamp, not the upload timestamp) and ideally a conversion_value. Smart Bidding uses the value signal to optimize toward higher-value leads specifically — uploading every closed deal with a flat value of 1 throws away the single biggest advantage of offline conversion data over simple lead-form conversion counting.Import method comparison
| Method | Best for | Scaling limit |
|---|---|---|
| Manual CSV upload | Occasional, low-volume manual reconciliation | Not automated; breaks at scale |
| Google Ads API integration | Any CRM with engineering capacity | Scales fully; requires OAuth + API maintenance |
| Native CRM connector (HubSpot, Salesforce) | Teams without engineering bandwidth | Limited to connector's supported fields/frequency |
Conversion window and attribution lag
What's Next?
Offline conversion data is only as good as the bidding strategy consuming it — once value-based conversions are flowing reliably, the next question is whether and how Smart Bidding should be configured to actually optimize toward that signal rather than toward volume alone.
I build these systems professionally.
Whether it's a RAG pipeline, analytics migration, or AI workflow — let's talk.