> ## Documentation Index
> Fetch the complete documentation index at: https://docs.northbeam.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 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

1. **Lowercasing**: Convert the entire email address to lowercase.
2. **Trimming**: Remove any spaces from the beginning or end of the email address.
3. **Validation**:
   * The email must contain exactly one `@` symbol.
   * If not, use the trimmed and lowercased email as-is.

### 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`)

* Remove everything after and including the first `+` character.
* Remove all periods (`.`).

#### Yahoo / Ymail (`yahoo.com`, `ymail.com`)

* Remove everything after and including the first `-` character.
* Remove all periods (`.`).

#### Outlook (`outlook.com`)

* Remove everything after and including the first `+` character.

#### ProtonMail (`protonmail.com`, `protonmail.ch`, `pm.me`)

* Remove everything after and including the first `+` character.

#### Apple Domains (`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) |
| - | - | - |
| [John.Doe+newsletters@gmail.com](mailto:John.Doe+newsletters@gmail.com) | [johndoe@gmail.com](mailto:johndoe@gmail.com) | 06a240d11cc201676da976f7b49341181fd180da37cbe40a77432c0a366c80c3 |
| [Jane-Doe+promo@ymail.com](mailto:Jane-Doe+promo@ymail.com) | [jane@ymail.com](mailto:jane@ymail.com) | 4a5206b6c57519e9ad41b5358b80f7e6e33dff21a263914f343454ab0fbbb4cb |
| [User.Name@outlook.com](mailto:User.Name@outlook.com) | [user.name@outlook.com](mailto:user.name@outlook.com) | 121a30e5c931fc09bbfcdbd9586976e764c76ac3687ba9afcde1fb7b92c077ce |
| [User+notes@pm.me](mailto:User+notes@pm.me) | [user@pm.me](mailto:user@pm.me) | d5080076cd5eb196ad2ed4d15dd93113fa810c17b51813d0bb5acc2b3f266ffc |
| [Test+spam@icloud.com](mailto:Test+spam@icloud.com) | [test@icloud.com](mailto:test@icloud.com) | 528dfe1c042ae276513bd1f3b662faaee6ef3ce8b9bea03181aa94ea4592683b |

### Reference Implementation (JavaScript)

```javascript theme={null}
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 `null` if the phone number is not valid.

### Reference Implementation (JavaScript)

```javascript theme={null}
// 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 |

***

## Using Hashed Emails for Attribution & CDV

Northbeam supports passing hashed emails through both the Pixel `identify` call and the Orders API. This allows hashed emails to be used for attribution and Customer Data Vault (CDV) matching workflows.

### Pixel Identify Call

If you are already using the standard `identify` call, replace `"email"` with `"hashed_email"` and pass the normalized and SHA-256-hashed value instead (apply the same normalization rules above before hashing).

#### Example

```javascript theme={null}
// SHA-256 of the normalized email "johndoe@gmail.com"
window.Northbeam.identify(
  "hashed_email",
  "06a240d11cc201676da976f7b49341181fd180da37cbe40a77432c0a366c80c3"
);
```

### Orders API

If sending hashed customer data through the Orders API, populate the `hashed_customer_email` field with the same SHA-256 hashed email value.

### Important

To enable hashed email attribution and CDV matching end-to-end:

* Pass the hashed email through the Pixel `identify` call using `hashed_email`
* Pass the same hashed value through the Orders API using `hashed_customer_email`

Both values must:

* Be normalized prior to hashing
* Use SHA-256 hashing
* Match consistently between the Pixel and Orders API

***

## Complete Workflow Example

Here's a complete example showing normalization → hashing for both email and phone:

```javascript theme={null}
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 = 'John.Doe+newsletters@gmail.com';
const phone = '(555) 123-4567';

const normalizedEmail = emailNormalize(email);  // "johndoe@gmail.com"
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
