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.
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.
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.
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.
{{ config(materialized = 'incremental',unique_key = 'edge_id',incremental_strategy = 'merge') }}WITH raw_events AS (SELECTanonymous_id,LOWER(TRIM(user_email)) AS user_email,crm_contact_id,received_atFROM {{ ref('raw_web_events') }}WHERE anonymous_id IS NOT NULLAND (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 (SELECTMD5(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_atFROM raw_eventsGROUP BY 1, 2, 3, 4)SELECT * FROM deduped_edges;
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.
-- Asignación del canonical_user_id a partir de la tabla de aristasWITH ranked_identities AS (SELECTanonymous_id,user_email,crm_contact_id,FIRST_VALUE(COALESCE(crm_contact_id, user_email, anonymous_id)) OVER (PARTITION BY anonymous_idORDER BY first_seen_at ASCROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS canonical_user_idFROM {{ ref('stg_identity_edges') }})SELECT DISTINCTcanonical_user_id,anonymous_id,user_email,crm_contact_idFROM ranked_identities;
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étrica de Negocio | Sin Resolución (Silos) | Con Identity Graph en SQL |
|---|---|---|
| Eventos Atribuidos a Cuentas | 32% (solo tras completar formulario) | 84% (incluye sesiones anónimas previas) |
| Longitud Media del Recorrido | 1.2 sesiones registradas | 5.8 sesiones reconstruidas |
| Cuentas Duplicadas en CRM | Alta dispersión por variación de emails | Unificada bajo dominio raíz de la empresa |
Controles Técnicos
Muestra telemetría y especificaciones de verificación en producción.