Hashed Email (HEM) format
When you upload hashed-email identifiers via Upload a batch, the format has to match exactly what Vibe's matcher expects. Mismatches don't produce errors — they produce audiences that ingest cleanly but match a much smaller share of CTV profiles than expected.
Specification
Algorithm: SHA-256.
Normalization, in order, before hashing:
- Lowercase the entire address.
- Trim leading and trailing whitespace.
- Do not strip
mailto:prefixes — reject those rows client-side instead. - Keep Gmail dots and
+suffixes as-is. Vibe matches the literal lowercased form. [verify with audiences owner]
Encoding: Lowercase hexadecimal. No salt.
Example
| Step | Value |
|---|---|
| Raw | [email protected] |
| Normalized | [email protected] |
| SHA-256 (hex) | c0ffeec0ffeec0ffeec0ffeec0ffeec0ffeec0ffeec0ffeec0ffeec0ffeec0ffe |
Reference implementations
Python
import hashlib
def to_hem(raw: str) -> str:
normalized = raw.strip().lower()
return hashlib.sha256(normalized.encode("utf-8")).hexdigest()
# to_hem(" [email protected] ")
# -> "c0ffee..."JavaScript / Node
import { createHash } from "crypto";
function toHem(raw) {
return createHash("sha256")
.update(raw.trim().toLowerCase())
.digest("hex");
}Validating before you upload
Vibe does not return an error on malformed hashes — they silently fail to match. Before sending production data, check three things:
- Every output is exactly 64 lowercase hex characters (
/^[0-9a-f]{64}$/). - Running your hasher against
[email protected]produces the value in the table above. - Hash a known address that exists in your test audience and confirm Vibe registers a match in the dashboard before scaling up.
Updated 6 days ago