> For the complete documentation index, see [llms.txt](https://docs.neonblue.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.neonblue.ai/data/identifiers-and-mapping.md).

# Identifiers, Users, and Mapping Tables

#### 1. What this page is about

This page explains **how Neon Blue identifies users** across your systems and which mapping tables we expect in your data warehouse.

It is written for:

* Data / analytics engineers who maintain your warehouse
* Marketing ops / lifecycle teams who care about experiments being measured correctly

You do **not** need prior knowledge of Neon Blue to understand this page.

***

#### 2. Quick overview: what Neon Blue is and why IDs matter

Neon Blue is an **AI-driven experimentation and personalization platform**. It:

* Generates and tests different creative variants (emails, on-site banners, etc.)
* Learns which variants work best for which users
* Continuously optimizes performance over time

To do that, we have to answer a basic question reliably:

> “Are we looking at the same person in your ecommerce system, your email platform, and your analytics tools?”

That is why the **identifier model** is one of the first things we align on. If user identities are messy, experiments are hard to trust. If they are clean, everything else becomes much easier.

***

#### 3. The canonical `user_id`

We ask each customer to choose **one canonical identifier** that represents a “user” (often a customer account or household) across the integration. We call this `user_id`.

This `user_id`:

* Is stable over time
* Is unique per user
* Exists in your warehouse on key tables (profiles, orders, events)

**Common choices:**

* `shopify_customer_id` (for Shopify brands)
* A `customer_id` primary key from your internal customer table
* Another ecommerce platform’s customer identifier

**How Neon Blue uses `user_id`:**

* All experiments and gate assignments are keyed by `user_id`
* All persona tags we send back are keyed by `user_id`
* When we join events, orders, and assignments, `user_id` is the common key

If you remember only one thing from this page, it’s:

> “Pick a clear, stable `user_id` and use it everywhere.”

***

#### 4. Other identifiers you probably have

Most teams also have other IDs floating around. That’s normal. We just want to **separate their roles clearly**.

**4.1 Messaging / ESP IDs**

These are IDs from tools like Klaviyo, Braze, Iterable, or your CRM.

Examples:

* `klaviyo_person_id`
* `braze_user_id`
* `salesforce_contact_id`

These IDs are usually **intended to map 1:1** to your canonical `user_id`, but sometimes you’ll discover oddities (e.g., duplicate contact records).

We recommend keeping this mapping in its own table:

**Table: `user_messaging_id_map`**

* `user_id` – your canonical user id
* `messaging_platform` – e.g., `'klaviyo'`, `'braze'`
* `messaging_person_id` – the ID in that system

This table is useful when:

* You want to upload Neon Blue personas to your ESP
* You want to join ESP-level performance data to Neon Blue assignments

***

**4.2 Analytics / device IDs (pseudo IDs)**

Analytics tools often use **device- or browser-level IDs**:

* GA4 `user_pseudo_id`
* A first-party cookie ID
* Mobile app device IDs

These are almost **never 1:1** with real people:

* One household can use multiple devices and browsers
* A single device might be used by several people

We suggest a separate mapping table that acknowledges this reality:

**Table: `user_device_id_map`**

* `user_id` – canonical user id (if known)
* `device_id` – e.g., GA4 `user_pseudo_id`
* `first_seen_at` – when this mapping was first observed
* `last_seen_at` – last time we saw this combination

How this is used:

* You log pageviews and other web events by `device_id`
* When `device_id ↔ user_id` becomes known (e.g., login), that mapping is stored here
* Neon Blue can then connect browsing behavior to a user when possible

Anonymous traffic will still exist, and that’s okay. We work with what can be reliably tied back.

***

#### 5. The `user_profiles` table

`user_profiles` is the main table that describes **who your users are**.

Think of it as:

> “One row per user, with their core attributes.”

It should include **everyone you want Neon Blue to learn about**, not just paying customers.

**Recommended shape:**

**Table: `user_profiles`**

Required columns:

* `user_id` – canonical user id (primary key)
* `email` – latest known email (nullable if not known)
* `created_at` – when this user first joined your universe

What does “joined your universe” mean?

* For ecommerce: usually when they first gave you an email (newsletter signup, account creation, checkout start)
* Not just when they placed their first order

Optional but very helpful:

* Basic traits: `country`, `language`, `marketing_opt_in`, `is_subscriber`
* Lifecycle markers: `first_order_at`, `last_order_at`, `total_orders`, `total_revenue`
* Internal segments: `segment_lifecycle`, `segment_value_tier`, etc.

Why include non-purchasers?

* Neon Blue also optimizes **early-funnel** experiences like welcome flows and lead-nurture journeys
* If we never see those users in `user_profiles`, we can’t learn anything about them or personalize for them

***

#### 6. Recommended minimal ID architecture

We recommend you maintain **three simple tables**:

1. **`user_profiles`**
   * One row per user
   * Canonical `user_id`, `email`, `created_at`, basic traits
2. **`user_messaging_id_map`**
   * Mapping between `user_id` and each messaging platform ID
   * Typically 1:1 per platform, with occasional exceptions
3. **`user_device_id_map`**
   * Mapping between `user_id` and device or pseudo IDs
   * 1:many expected

This gives you:

* Clean joins for experimentation and reporting
* Flexibility to change ESPs or analytics tools in the future
* A clear place to debug identity issues (“Why does this user appear twice?”)

***

#### 7. Practical example: measuring a welcome flow

Imagine you want Neon Blue to optimize your **Welcome email flow**:

1. A new user signs up with an email.
2. Your system assigns them a new `user_id` and stores it in `user_profiles`.
3. Your ESP creates a profile for them and writes that ID to `user_messaging_id_map`.
4. As they browse your site, your analytics tool logs pageviews by `device_id`.
5. When they log in or check out, you map that `device_id` to the `user_id` in `user_device_id_map`.

Now, when Neon Blue runs an experiment on the Welcome flow:

* We assign a variant per `user_id` (e.g., subject line A vs B).
* We see their events (opens, clicks, orders) keyed by `user_id`.
* We measure performance per variant, reliably, with all their cross-device behavior.

The entire chain works because `user_id` is consistent and the mapping tables are clean.
