# Google Ads Enhanced Conversions: Hashing, Leads & Offline Import

> Turn hashed email/phone into better bidding — with the hashing mistake that silently kills match rate. EC for Web, Leads and Offline Import via Zapier/GTM, no paid CRM.

**Category:** Google Ads | **Published:** 2026-07-10 | **Reading:** 4 min read | **URL:** https://jhasanr.top/blog/google-ads-enhanced-conversions/

## TL;DR

Send normalised first-party data at purchase or lead. Either pass plain values and let Google hash them, or pre-hash with SHA-256 and use the sha256_-prefixed keys — never a hash in a plain key, that produces zero matches. For offline sales, import via Zapier + Google Ads API.

## Key Takeaways

- Plain keys (email/phone) expect raw values — Google hashes them; sha256_ keys expect pre-hashed hex. Hashing twice zeroes match rate (diagnostics still shows Recording)
- EC for Leads: capture gclid in hidden field → store in Sheet/CRM → import offline when qualified via Zapier/GTM Server-Side → Google Ads API, no paid CRM needed
- Normalize before hashing: trim, lowercase, strip Gmail dots, E.164 phone, lowercase hex — not Base64

## Why Enhanced Conversions (EC) in 2026

                First, kill the premise you have probably read elsewhere: **Chrome did not deprecate third-party cookies.** Google reversed the plan in July 2024, dropped the standalone choice prompt in April 2025, and in October 2025 retired most of the Privacy Sandbox APIs. Third-party cookies are still there. What *is* true is narrower and still costs you money: Safari and Firefox block them by default, Safari caps script-written first-party cookies at 7 days, ad blockers stop the tag loading, and consent banners mean a share of conversions never get a cookie at all.


                EC works around all of that from a different angle. It uses **first-party user-provided data** you already collect at checkout or on the lead form, hashed, and matched against signed-in Google accounts. Google publishes uplift ranges for it, but they move and they are averages across wildly different advertisers — so treat any single number you see quoted (including in older versions of this post) as marketing, and measure your own before and after instead.


                The practical argument is simpler: without EC, Smart Bidding only learns from the conversions that survived cookie loss. Systematically missing conversions means systematically underbidding on the audiences that convert.


                
## EC for Web: Purchase / Add to Cart

                

                    - In Google Ads → Tools → Conversions → Edit → Check “Turn on Enhanced Conversions” → Method: Tag.

                    - Web GTM: on the Google Ads Conversion / GA4 tag, tick **“Include user-provided data from your website”** and select a User-Provided Data variable mapping `{{Email}}`, `{{Phone}}`, `{{Address}}`. GTM normalises and hashes those values in the browser for you — there is no checkbox literally called “Auto-hash”.

                

                
### If you hash it yourself, use the `sha256_` keys

                This is the mistake I find most often, and it fails silently. The plain keys (`email`, `phone_number`, `first_name`) expect **raw values** — Google hashes them itself. Hand a digest to a plain key and Google hashes the digest again, so nothing ever matches. Google Ads diagnostics will still report the tag as “Recording”, because that only tells you hits arrived, not that they matched.


                
```
// WRONG — a hash in a plain key gets hashed a second time. Match rate: zero.
gtag('set', 'user_data', { "email": sha256("user@example.com") });

// RIGHT, option A — send raw values, let Google normalise and hash
gtag('set', 'user_data', {
  "email": "user@example.com",
  "phone_number": "+8801830890229",
  "address": { "first_name": "Jahid", "last_name": "Hasan" }
});

// RIGHT, option B — pre-hash, and say so with the sha256_ prefix
gtag('set', 'user_data', {
  "sha256_email_address": hexSha256(normalizeEmail("User@Example.com")),
  "sha256_phone_number":  hexSha256("+8801830890229"),
  "address": {
    "sha256_first_name": hexSha256("jahid"),
    "sha256_last_name":  hexSha256("hasan")
  }
});
```

                Normalise *before* hashing or option B will underperform option A: trim whitespace, lowercase everything, strip periods from Gmail local-parts, put phone numbers in E.164 (`+` and country code), and output lowercase hex — not Base64.


                Shopify: Use Checkout extensibility → add GTM dataLayer with customer email at `checkout_completed`.


                
## EC for Leads: GCLID is king

                For B2B/lead forms: 1) Capture `gclid` from URL → store in hidden form field + CRM/GSheet. 2) When lead becomes qualified/sale, import offline.


                FieldExamplegclidCjwKCA...conversionNameQualified LeadconversionTime2026-07-11T10:00:00Zemail (hashed)sha256
                
## Offline Conversion Tracking (OCT) without paid CRM — my free Zapier trick

                This is my [€0 OCT service](../../pricing/). No HubSpot needed:


                

                    - Form (Tally/Typeform) → Zapier → Google Sheets (row: email, gclid, phone, lead_status).

                    - Google Sheets → Zapier → GTM Server-Side → Google Ads API (offline conversion). Or direct Zapier “Upload Offline Conversion to Google Ads”.

                    - Alternative: push from the sheet on a schedule — Apps Script trigger, or a cron job, calling the Google Ads API or your sGTM endpoint. A server-side GTM tag cannot poll a spreadsheet on its own; sGTM tags only run when a request arrives, so something has to send that request.

                

                Also works for call tracking: CallRail webhook → Zapier → Google Ads with `caller_id = sha256(phone)`.


                
> Result for one B2B lead-gen client: ROAS roughly tripled over 60 days after EC + OCT went live — because Google could finally see which keywords produced *qualified* leads instead of form spam. One account, one time window, and the account was actively managed over the same period. Treat it as an illustration of the mechanism, not a benchmark you should expect.

                
## FAQ

                
                    Is hashing required?The data has to reach Google hashed, but you do not have to hash it yourself. Tick “Include user-provided data from your website” on the GTM tag and GTM normalises and SHA-256 hashes the values in the browser. If you prefer to hash server-side or in your own code, you must switch to the sha256_ prefixed keys — sha256_email_address, sha256_phone_number, sha256_first_name, sha256_last_name — otherwise Google hashes your digest again and nothing matches.


                    EC vs Consent Mode?They solve different problems and you need both. Consent Mode v2 decides whether you may send anything at all, gating ad_storage, analytics_storage, ad_user_data and ad_personalization. EC improves matching for the conversions you are allowed to send. Without ad_user_data granted, do not send user-provided data.


                    How long to see lift?Expect 7-14 days after the tag goes live and offline conversions start importing, since Smart Bidding needs the new signal to accumulate. Check Google Ads → Diagnostics for Enhanced conversions status “Recording”, but read that as “hits are arriving”, not as proof of match quality.

## FAQ

### Is hashing required?

Data must reach Google hashed, but you don't have to hash yourself. GTM tick Include user-provided data normalises+SHA-256 in browser. If you pre-hash, use sha256_ prefixed keys or Google double-hashes.

### EC vs Consent Mode?

Consent Mode v2 decides if you may send at all (ad_storage/analytics_storage/ad_user_data). EC improves matching for allowed conversions. Without ad_user_data granted, don't send user data.

### How long to see lift?

7-14 days after tag live + offline imports, as Smart Bidding needs signal. Diagnostics Recording means hits arrived, not match quality.

---
*Author: Jahid Hasan — Web Analytics & Tracking Expert (https://jhasanr.top/) | 500+ implementations | Canonical: https://jhasanr.top/blog/google-ads-enhanced-conversions/ *
