Hashing Customer Data
Normalization and hashing guidelines for customer email and phone numbers
NB Orders API Guide: Normalization for Hashed Email & Phone
This document specifies normalization rules for emails and phone numbers prior to hashing for the hashed_customer_email and hashed_customer_phone_number fields in the NB Orders API. These rules are identical to the normalization used by integrated advertising platforms so that hashes generated by customers match 1:1 with platform-provided hashes.
Important:
• If you are sending raw emails/phone you should not send these hashed fields
• The emails and phone numbers should be first normalized and then hashed. The hashed versions should be sent via the NB API.
Hashing Output Format
- Algorithm: SHA-256
- Input: Normalized email or phone number
- Output: Lowercase hexadecimal (64 characters), no prefix
- Email: Hash the normalized email string
- Phone: Hash the E.164 string returned by normalization (include the leading
+)
Email Normalization
Purpose
Normalize email addresses to a consistent format so that variations of the same email are treated as equivalent. This is useful for deduplication, simplified email handling and creating consistent SHA-256 hashes from emails.
General Rules
- Lowercasing: Convert the entire email address to lowercase.
- Trimming: Remove any spaces from the beginning or end of the email address.
- Validation:
- The email must contain exactly one
@symbol. - If not, use the trimmed and lowercased email as-is.
- The email must contain exactly one
Domain-Specific Normalization Rules
Apply the following rules to the local part (the portion before the @) based on the email's domain:
Gmail (gmail.com)
gmail.com)- Remove everything after and including the first
+character. - Remove all periods (
.).
Yahoo / Ymail (yahoo.com, ymail.com)
yahoo.com, ymail.com)- Remove everything after and including the first
-character. - Remove all periods (
.).
Outlook (outlook.com)
outlook.com)- Remove everything after and including the first
+character.
ProtonMail (protonmail.com, protonmail.ch, pm.me)
protonmail.com, protonmail.ch, pm.me)- Remove everything after and including the first
+character.
Apple Domains (icloud.com, me.com, mac.com)
icloud.com, me.com, mac.com)- Remove everything after and including the first
+character.
Final Step
Recombine the cleaned local part with the domain part using @. Use the resulting normalized email address.
Examples
| Input Email | Normalized Email | Hashed Email (SHA-256) |
|---|---|---|
| [email protected] | [email protected] | 06a240d11cc201676da976f7b49341181fd180da37cbe40a77432c0a366c80c3 |
| [email protected] | [email protected] | 4a5206b6c57519e9ad41b5358b80f7e6e33dff21a263914f343454ab0fbbb4cb |
| [email protected] | [email protected] | 121a30e5c931fc09bbfcdbd9586976e764c76ac3687ba9afcde1fb7b92c077ce |
| [email protected] | [email protected] | d5080076cd5eb196ad2ed4d15dd93113fa810c17b51813d0bb5acc2b3f266ffc |
| [email protected] | [email protected] | 528dfe1c042ae276513bd1f3b662faaee6ef3ce8b9bea03181aa94ea4592683b |
Reference Implementation (JavaScript)
function emailNormalize(email) {
if (!email) {
return null;
}
// Utility functions
const stripPeriods = (value) => value.replace(/\./g, '');
const plusAddressing = (value) => value.split('+')[0];
const dashAddressing = (value) => value.split('-')[0];
// Normalize format
const normalized = email.trim().toLowerCase();
const parts = normalized.split('@');
// Invalid email format, return as-is
if (parts.length !== 2) {
return normalized;
}
let [localPart, domainPart] = parts;
let localPartRules = [];
// Domain-specific rules
switch (domainPart) {
case 'gmail.com':
localPartRules = [plusAddressing, stripPeriods];
break;
case 'yahoo.com':
case 'ymail.com':
localPartRules = [dashAddressing, stripPeriods];
break;
case 'outlook.com':
case 'protonmail.com':
case 'protonmail.ch':
case 'pm.me':
case 'icloud.com':
case 'me.com':
case 'mac.com':
localPartRules = [plusAddressing];
break;
}
// Apply all relevant rules
for (const rule of localPartRules) {
localPart = rule(localPart);
}
return `${localPart}@${domainPart}`;
}Phone Normalization
Purpose
Format a phone number into a consistent style using the libphonenumber-js library. This library:
- Removes any non-digit characters (like spaces, dashes, parentheses).
- Makes sure it starts with a
+country code. If there's no country code, it adds+1(for the US/Canada). - Returns
nullif the phone number is not valid.
Reference Implementation (JavaScript)
// Uses the libphonenumber-js library; import as follows:
// For ES6 modules (Node.js or modern bundlers)
import { parsePhoneNumber } from 'libphonenumber-js';
// OR for CommonJS (Node.js)
// const { parsePhoneNumber } = require('libphonenumber-js');
function normalizePhoneNumber(phone) {
try {
const parsed_phone = parsePhoneNumber(phone, 'US');
if (!parsed_phone || !parsed_phone.isValid()) return null;
return parsed_phone.number;
} catch (e) {
return null;
}
}Examples
| Raw Phone Number | Normalized Phone (E.164) | Hashed Phone (SHA-256) |
|---|---|---|
| (212) 555-1234 | +12125551234 | b7532e84c87df1f9f6bc4097cea3fa27db1b990bdc8d1211e59586349e5cce82 |
| 415.555.2368 | +14155552368 | 5efe6d2b35a8b1cd9395c2f451ff4d4eb6dd9ddc6761cdefea0653d62ac24011 |
| 3105551234 | +13105551234 | a2f7381cd9b4a70cbbbe1113afa0770eed79adfba525c33b69a11f87790850e1 |
| 1-718-555-7890 | +17185557890 | d7c5b36eb18b782d398fd7e3eec015189c801b2c24d226c3689198bb5ef952d2 |
Complete Workflow Example
Here's a complete example showing normalization → hashing for both email and phone:
import crypto from 'crypto';
import { parsePhoneNumber } from 'libphonenumber-js';
// Hash a normalized string using SHA-256
function sha256Hash(input) {
return crypto.createHash('sha256').update(input, 'utf8').digest('hex');
}
// Example usage
const email = '[email protected]';
const phone = '(555) 123-4567';
const normalizedEmail = emailNormalize(email); // "[email protected]"
const hashedEmail = sha256Hash(normalizedEmail);
const normalizedPhone = normalizePhoneNumber(phone); // "+15551234567"
const hashedPhone = sha256Hash(normalizedPhone);
console.log('Hashed Email:', hashedEmail);
console.log('Hashed Phone:', hashedPhone);Important Notes
- Always normalize before hashing
- Use SHA-256 with lowercase hexadecimal output
- Phone numbers should include the
+when hashing - Invalid phone numbers return
null- handle these gracefully in your implementation - These normalization rules match advertising platform standards for consistent matching
Updated 19 days ago
