Enhanced Conversions works by sending customer data alongside the conversion so Google can match it to a signed-in user whose click was not otherwise attributable. The whole mechanism rests on one requirement: that data is hashed with SHA-256 before it leaves the browser. Google never receives the address; it receives a digest and compares digests.
When that requirement is not met, two things happen at once. The match rate quietly fails to improve, and a customer email address has been transmitted in the clear to an advertising endpoint. The first is a measurement problem. The second is the kind of problem that involves other departments.
What a correct field looks like on the wire
There are two legitimate shapes, and it is worth knowing both because implementations differ:
- A bare digest.
emcarries 64 hexadecimal characters and nothing else. This is what you get when your own code hashes the value before handing it to the tag. - The Google tag’s envelope.
tv.1~em.<sha256>~ph.<sha256>— the tag collected the values itself and wrapped several of them into one parameter. Each segment after the prefix is still a digest; the wrapper is not an excuse to stop checking.
Everything else is a defect, and the four you will actually meet are these.
Tag Master validates the fields on every Google Ads conversion it sees and says which shape each one
is in: SHA-256, MD5, or plaintext with a warning attached. It reads the tv.1~ envelope
rather than treating it as an unhashed string, because a tool that cried wolf on the correct
implementation would be worse than no check at all.
The four ways it goes wrong
- Plaintext. The value in
emis still an email address, usually because a dataLayer variable was wired straight into the user-data field on the assumption that the tag would hash it. Sometimes it does; when the value arrives through a variable rather than page collection, it does not. - MD5. Thirty-two hex characters. An older internal hashing helper, reused. The request succeeds and matches nothing.
- Hashed without normalising. This is the expensive one, because everything looks
right.
[email protected]and the same address with a capital A, or with one trailing space, produce three completely different digests. Trim the whitespace, lowercase the address, strip dots and plus-tags only where Google says to, and put the phone in E.164 form before hashing — otherwise you are sending a valid hash of the wrong string. - Hashed twice. Code hashes the value and the tag hashes it again. Sixty-four hex characters, perfectly formed, matching nobody.
Only the first two are visible as shape. The last two look identical to success, which is why the check has to include reading the value you put in, not only the value that came out.
Why the interface will not tell you
Google Ads diagnostics reports on conversions it has already processed, days later, and what it reports is coverage: how many conversions carried user data. It cannot report that a digest was computed over an unnormalised string, because from Google’s side that is simply a hash that did not match. Two indistinguishable outcomes, one of them your bug.
The request is immediate and unambiguous by comparison. Do a test conversion, read the hit, confirm the shape of every field, and you have an answer in a minute rather than a week.
Two things to check while you are in there
First, the attribution half. Enhanced Conversions improves matching; it does not replace the click
chain. If the conversion carries no gclid and no linker cookie, there is a separate problem
underneath this one, and the campaign that brought the
visitor is where it starts.
Second, consent. User data leaving the browser while ad_user_data is denied is a worse
version of the same finding, and it is not something the Google Ads interface will surface either.
Reading the consent state carried on each hit is how you
tell whether the request should have been sent at all.
Questions
How do I check that Enhanced Conversions data is hashed?
Read the conversion request. A hashed field is 64 hexadecimal characters, or the Google tag’s envelope tv.1~em.<hash>~ph.<hash>. Anything that still looks like an email address is plaintext, and that is a policy problem as well as a broken setup.
Which fields have to be hashed?
em, ph, fn, ln, ct, st and zp. country is the exception — it travels as a plain ISO 3166-1 alpha-2 code and is meant to.
Is MD5 acceptable?
No. Google Ads takes SHA-256 only. An MD5 digest is 32 hex characters instead of 64, so it is recognisable on sight — and it will be accepted by the request and match nothing.
Why does the Google Ads diagnostics page say everything is fine?
Because it reports on data already processed, with a lag measured in days, and it reports coverage rather than correctness. A field hashed without normalising it first produces a valid-looking hash that matches nobody, and diagnostics has no way to say so.
The rest of this group: GA4, server-side and attribution
- Debugging GA4 when DebugView shows nothing
- GA4 counting everything twice
- How to debug server-side GTM
- Google Tag Gateway: checking that it actually works
- When GA4 says the traffic came from somewhere else
More in GA4, server-side and attribution
Try it on your own site
Tag Master is free, needs no account, and collects no data.
Add to Chrome — Free