[ ALMACÉN CENTRAL & CDP ]

Resolución de Identidad Determinística en Data Warehouse mediante dbt y SQL

Cómo unificar cookies anónimas, correos corporativos y registros de CRM en un único canonical_user_id sin software de caja negra, usando grafos de identidad en dbt.

3 Septiembre 2026
11 min de lectura
RESUMEN ESTRATÉGICO // ANSWER FIRST

En el marketing B2B, un mismo decisor corporativo puede visitar tu web desde un teléfono móvil, navegar anónimamente desde su portátil en la oficina, descargar un whitepaper con su correo de trabajo y finalmente ser registrado en el CRM con un ID de contacto diferente. La resolución de identidad determinística fusiona estos identificadores dispersos mediante enlaces exactos comprobables (email corporativo, hashed_user_id, token de autenticación), generando una clave única canónica (`canonical_id`) que une todo el historial de interacciones.

01.

1. Arquitectura de Datos: Nodos y Aristas de Identidad

Para modelar identidades en SQL, estructuramos la información en una tabla de enlaces (aristas) que conecta pares de identificadores: `anonymous_id` (cookie del navegador), `email` (correo normalizado en minúsculas) y `crm_contact_id` (identificador en Salesforce o HubSpot).

Regla Determinística Estricta

Evitamos aproximaciones probabilísticas (direcciones IP o huellas de navegador) que en entornos de oficinas corporativas mezclan erróneamente el tráfico de múltiples empleados de una misma empresa bajo una sola persona.

02.

2. Implementación de Modelo Incremental en dbt (SQL)

El siguiente modelo de dbt extrae pares de identificadores a partir de los eventos brutos de analítica web y genera un mapa de asignación canónica mediante funciones de ventana analítica.

stg_identity_edges.sql
{{ config(
materialized = 'incremental',
unique_key = 'edge_id',
incremental_strategy = 'merge'
) }}
WITH raw_events AS (
SELECT
anonymous_id,
LOWER(TRIM(user_email)) AS user_email,
crm_contact_id,
received_at
FROM {{ ref('raw_web_events') }}
WHERE anonymous_id IS NOT NULL
AND (user_email IS NOT NULL OR crm_contact_id IS NOT NULL)
{% if is_incremental() %}
AND received_at > (SELECT MAX(received_at) FROM {{ this }})
{% endif %}
),
deduped_edges AS (
SELECT
MD5(CONCAT(anonymous_id, COALESCE(user_email, ''), COALESCE(crm_contact_id, ''))) AS edge_id,
anonymous_id,
user_email,
crm_contact_id,
MIN(received_at) AS first_seen_at,
MAX(received_at) AS received_at
FROM raw_events
GROUP BY 1, 2, 3, 4
)
SELECT * FROM deduped_edges;
03.

3. Generación del Canonical ID Maestro

Una vez construida la red de identificadores, aplicamos una función analítica para elegir el identificador raíz más antiguo y estable. Esto garantiza que cualquier evento futuro de ese usuario se vincule retrospectivamente a su primera interacción anónima.

dim_users_unified.sql
-- Asignación del canonical_user_id a partir de la tabla de aristas
WITH ranked_identities AS (
SELECT
anonymous_id,
user_email,
crm_contact_id,
FIRST_VALUE(COALESCE(crm_contact_id, user_email, anonymous_id)) OVER (
PARTITION BY anonymous_id
ORDER BY first_seen_at ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
) AS canonical_user_id
FROM {{ ref('stg_identity_edges') }}
)
SELECT DISTINCT
canonical_user_id,
anonymous_id,
user_email,
crm_contact_id
FROM ranked_identities;
04.

4. Impacto en Atribución y Cobertura de Perfiles

Al unificar sesiones previas a la conversión con la cuenta de CRM, se descubren puntos de contacto que ocurrieron semanas antes de que el usuario completara el primer formulario.

Métricas de Resolución de Identidad Antes vs. Después de dbt
Métrica de NegocioSin Resolución (Silos)Con Identity Graph en SQL
Eventos Atribuidos a Cuentas32% (solo tras completar formulario)84% (incluye sesiones anónimas previas)
Longitud Media del Recorrido1.2 sesiones registradas5.8 sesiones reconstruidas
Cuentas Duplicadas en CRMAlta dispersión por variación de emailsUnificada bajo dominio raíz de la empresa

Controles Técnicos

Muestra telemetría y especificaciones de verificación en producción.