Identifier normalization & hashing
Hashing is exact. Two values that differ by a single space, a capital letter or a leading zero produce completely unrelated hashes, and the platform has no way to tell they were the same person. Normalization is the step that makes both sides agree before the hash is taken.
This page matters more than any other in this section. Most poor match rates trace back to something here.
Hashing, not encryption
Section titled “Hashing, not encryption”Signals hashes personal identifiers with SHA-256. Hashing is one way: the output cannot be reversed to recover the original value. It is not encryption, and it should not be described as encryption.
Output is a lowercase hexadecimal string, 64 characters long.
Hash at source wherever you can
Section titled “Hash at source wherever you can”The right default is to hash personal data before it leaves your systems. It means raw identifiers never travel, and it puts normalization in the place that best understands the data.
On website and app sources this happens for you. The tag hashes in the browser and the app hashes before posting, so the raw value never leaves the device.
On CRM, file, database and warehouse sources, send values already hashed if your systems can do it. Where they cannot, Signals normalizes and hashes on the way through, in memory. The raw value is not written to disk and nothing downstream sees it.
Normalization rules
Section titled “Normalization rules”These are the rules Signals applies. Apply the same ones if you are hashing before you send.
| Field | Rule |
|---|---|
| Trim leading and trailing spaces. Convert to lowercase. | |
| Phone | E.164. A leading plus sign, then the country code and the number, up to fifteen digits, with whitespace, brackets, hyphens and any leading zero removed. |
| First name, last name | Letters only. Trim whitespace, lowercase, no punctuation or special characters, UTF-8. |
| City | Letters only. Trim whitespace, lowercase, no punctuation or special characters, UTF-8. |
| State | In the US, the two character ANSI abbreviation in lowercase. Outside the US, lowercase with no punctuation, special characters or whitespace. |
| Country | Lowercase two letter ISO 3166-1 alpha-2 code. |
| Postcode | Lowercase, no whitespace. In the US, the first five digits only. In the UK, Area/District/Sector format. |
| Gender | m for male, f for female. |
| Date of birth | DD/MM/YYYY. It can also be split into year YYYY, month 01 to 12, and day 01 to 31. |
Worked examples
Section titled “Worked examples”| Input | Normalized | Hashed |
|---|---|---|
Person@Example.com | person@example.com | 64 character lowercase hex |
+971 56 789 1234 | +971567891234 | 64 character lowercase hex |
Mumbai | mumbai | 64 character lowercase hex |
India | in | 64 character lowercase hex |
2 July 1999 | 02/07/1999 | 64 character lowercase hex |
The country code problem
Section titled “The country code problem”This is the single most common cause of a low phone match rate, and it is worth stating on its own.
Meta requires the country code on every phone number, and states that you should “always include the country code as part of your customers’ phone numbers, even if all of your data is from the same country”. A national format number will not match.
The failure is invisible. A UAE number stored as 05x xxx xxxx or an Indian number stored as 0 98xxx xxxxx hashes perfectly well. It just hashes to a value no platform has ever seen. Strip the leading zero, prefix 971 or 91, then hash.
What is never hashed
Section titled “What is never hashed”Three categories of value must be sent unhashed. Hashing them breaks them.
- Technical identifiers. Click IDs and platform cookies such as
fbcandfbp, plusclient_ip_addressandclient_user_agent. - Device advertising identifiers and external IDs. GAID, IDFA, IDFV and your own external ID are sent as they are.
- Meta’s per-channel messaging identifiers.
ctwa_clidfor Click to WhatsApp,ig_sidandig_account_idfor Click to Instagram, andpage_idandpage_scoped_user_idfor Click to Messenger. Meta flags all five do-not-hash. They are the strongest match key on Messaging CAPI, so a hash here costs more than it does on a contact field.
Meta states that its systems are designed not to accept unhashed contact information, so the split is enforced on the platform side as well.
The Google exception on location fields
Section titled “The Google exception on location fields”City, state, country and postcode are hashed for Meta and sent in plain text for Google. Email address and phone number are still hashed for every destination including Google, so this applies to the location fields only.
On a file source the template carries both versions of each location field for that reason. Use the _hashed columns for Meta and the plain city, state, country and zipcode columns for Google. Hashing the plain columns is a common cause of a Google match rate that is lower than the Meta one on the same file.
Normalize before you hash, because nobody can check afterwards
Section titled “Normalize before you hash, because nobody can check afterwards”A SHA-256 hash of an un-normalized value looks exactly like a hash of a normalized one. Both are 64 character hex strings, and there is no way to tell them apart.
That means Signals cannot detect that you skipped normalization, and neither can the destination. Nothing errors. The hash simply never matches anything, and your match rate degrades silently. If you hash at source, the normalization rules above are not optional advice, they are the difference between a value that matches and one that never will.
Multiple identifiers per record
Section titled “Multiple identifiers per record”The offline conversions interface accepts up to three email addresses and up to three phone numbers per event, with two format variants available per phone number. Send E.164 in the format_b column. Where you hold more than one contact detail for a person, send them all. Each is an additional matching opportunity.
Platform specifics
Section titled “Platform specifics”Datahash normalizes and hashes to the rules above. Individual platforms publish their own requirements, and where they differ the platform’s rule governs what it will accept.
- Meta requires
em,ph,fn,ln,db,ge,ct,st,zpand country to be hashed, and publishes normalization and SHA-256 test vectors per parameter. - Snapchat normalizes then SHA-256 hashes personal identifiers, and takes
client_ip_addressandclient_user_agentunhashed on web events. - TikTok requires email and phone hashed with SHA-256 before they reach TikTok, browser side for pixel Advanced Matching and server side for the Events API.

