13 — Pixel & Tracking

Índice de la página
  1. 01Cliente: Martín Rieznik / LevantArte
  2. Área: Tracking / Attribution / Server-side Events
  3. 020. Definición de "done" para esta checklist
  4. 031. Pre-requisitos
  5. 042. Tareas
  6. 2.1 Meta Pixel — browser-side
  7. 2.2 Conversions API server-side — /api/capi-meta
  8. 2.3 TikTok Pixel
  9. 2.4 Google Ads Pixel
  10. 2.5 ProveSource notificaciones flotantes
  11. 2.6 UTMs propias persistentes
  12. 2.7 Supabase event logging
  13. 2.8 Hyros — call tracking unificado (ACTIVO en MVP)
  14. 2.9 Validación end-to-end
  15. 053. Variables y posibilidades a anticipar
  16. 064. Multi-tenant: cómo se replica al cliente #2
  17. 075. Recursos y archivos relacionados
  18. 086. Notas y aprendizajes (post-mortem)
  19. 09CHANGELOG

Cliente: Martín Rieznik / LevantArte

Área: Tracking / Attribution / Server-side Events

Setup completo de tracking: Meta Pixel + TikTok Pixel + Google Ads Pixel + ProveSource (notificaciones flotantes) + Hyros (call tracking unificado, antes referido como "Jairo's pixel") + Conversions API server-side (/api/capi-meta) + UTMs propias persistentes + Supabase event logging usando los 13 tipos de evento del schema. Match rate Meta > 70% requerido.

Última actualización: 2026-05-05
Responsable principal (R): Eric
Aprobador (A): Jesús
Deadline: 2026-05-31
Depende de: 01 (infra), 02 (landings donde corren los pixels)
Bloquea a: 14 (campañas Meta no se pueden optimizar bien sin pixel + CAPI)


0. Definición de "done" para esta checklist

  • Meta Events Manager muestra los 6 eventos críticos llegando con frecuencia esperada y match rate ≥ 70% (browser + server reconciliados via event_id).
  • TikTok Events Manager + Google Ads Conversions muestran eventos Lead y Purchase confirmados.
  • Supabase tabla eventos recibe los 13 tipos del enum sin pérdida (smoke test 100 leads de prueba: 100 filas).
  • UTMs (source, medium, campaign, content) persisten desde click ad → quiz → registro → compra (verificable en compras.utm_* derivado de leads.utm_*).
  • CAPI server-side dedup_key (event_id) presente en cada evento → Meta no contabiliza duplicados.
  • Hyros instalado, dominio i.deacademia.com (o equivalente) configurado, primer evento de tracking llegando a Hyros desde landing /martin/.

1. Pre-requisitos

# Pre-requisito Provisto por Estado
1 Acceso Meta Business Manager Martín (admin del Business + del Ad Account) Martín ⚠️
2 Pixel ID Meta de Martín creado (o crear uno nuevo en su Business) Martín + Eric ⚠️
3 Conversions API access token (System User token Meta, expira raramente) Eric (genera con acceso de Martín) ⚠️
4 Pixel ID TikTok de Martín (cuenta TikTok Ads — confirmar si tiene) Martín ⚠️
5 Google Ads conversion ID + label de Martín (si tiene cuenta Google Ads) Martín ⚠️
6 Cuenta ProveSource creada (o usar trial) + site_id Eric ⚠️
7 Acceso a cuenta Hyros de TooAudience + permiso para crear nuevo tracking domain para Martín Jesús + Eric ⚠️
8 Infra técnica (checklist 01) verde, Supabase + tabla eventos + Vercel API routes funcionando Eric ⚠️
9 Landings deployadas (al menos /martin/ quiz + thank you) para testear eventos Eric (checklist 02) ⚠️

2. Tareas

2.1 Meta Pixel — browser-side

  • Confirmar que Martín tiene Pixel creado en Meta Business; si no, crear uno nuevo "LevantArte Martín — Master Pixel" en Business de Martín. R: Eric + Martín. Done cuando: Pixel ID copiado a clients.config_json.pixel_ids.meta.
  • Instalar Meta Pixel base code en app/[client_slug]/layout.tsx con Pixel ID dinámico desde config (NO hardcodear). R: Eric. Done cuando: ver pixel disparar PageView en Pixel Helper extension visitando /martin/.
  • Disparar PageView automático en cada page (incluido en base code). R: Eric. Done cuando: Events Manager registra PageView en tiempo real.
  • Disparar ViewContent en /martin/taller y /martin/membresia con content_name, content_category, value, currency. R: Eric. Done cuando: 2 eventos visibles en Events Manager con metadata.
  • Disparar Lead en /martin/gracias-calificado (browser) con event_id único (UUID v4) — el mismo que se usará en CAPI para dedup. R: Eric. Done cuando: evento en Events Manager + event_id presente.
  • Disparar InitiateCheckout en click de cualquier botón de pasarela en sales pages (5 botones × 2 páginas = 10 hooks). R: Eric. Done cuando: cada click → 1 evento en Pixel Helper + cuerpo con pasarela, sku, value.
  • Disparar CompleteRegistration en bot WhatsApp confirmando lead (delegado al bot via API si aplica, sino solo browser). R: Eric. Done cuando: aparece en Events Manager.
  • Disparar Purchase en /martin/taller/gracias y /martin/membresia/gracias con value, currency, content_ids, content_type='product'. R: Eric. Done cuando: evento dispara con monto correcto.
  • Pasar Advanced Matching parameters (em, ph, fn, ln, ct, country) hasheados con SHA256 en cada evento donde haya identidad (Lead, Purchase). R: Eric. Done cuando: Events Manager Diagnostics muestra "User Data Match Quality" verde.

2.2 Conversions API server-side — /api/capi-meta

  • Crear System User en Meta Business + generar System User Access Token (sin expiración) con permisos ads_management + business_management. R: Eric. Done cuando: token guardado en 1Password + Vercel env var META_CAPI_TOKEN.
  • Crear API route src/app/api/capi-meta/route.ts POST que recibe {event_name, event_id, user_data, custom_data, event_source_url} y forwarda a Meta Conversions API endpoint https://graph.facebook.com/v22.0/<PIXEL_ID>/events. R: Eric. Done cuando: POST de prueba retorna {events_received: 1}.
  • Hash SHA256 de email, phone, first_name, last_name antes de enviar (Meta lo requiere). R: Eric. Done cuando: payload enviado tiene em: "<sha256>" y similares.
  • Generar event_id único en frontend (UUID v4), pasarlo a CAPI Y a Pixel browser → Meta dedupea por event_id cuando ambas fuentes envían el mismo. R: Eric. Done cuando: Events Manager > Overlap muestra eventos deduplicados.
  • Eventos críticos a enviar via CAPI (los que pagan ads): Lead (post-quiz), Purchase (post-pasarela), InitiateCheckout (click pasarela). R: Eric. Done cuando: 3 eventos visibles como server-side en Events Manager.
  • Incluir client_user_agent (UA del browser), client_ip_address (IP del request), fbp y fbc cookies en user_data para mejorar match rate. R: Eric. Done cuando: Diagnostics > Event Match Quality verde para CAPI events.
  • Test mode: usar test_event_code en payload mientras se desarrolla, sacar antes de producción. R: Eric. Done cuando: test events visibles en Events Manager > Test Events sin afectar producción.
  • Validar match rate ≥ 70% en Events Manager > Diagnostics > Event Match Quality. Si está bajo, iterar agregando más datos (zip, dob, country). R: Eric. Done cuando: 3 eventos críticos con match quality "Good" o "Great".
  • Retry logic: si Meta API retorna error 5xx, reintentar 3 veces con backoff exponencial. Si falla las 3, log a Supabase eventos con tipo='capi_failed' para reprocesar. R: Eric. Done cuando: simulando outage Meta, eventos quedan en cola y se reenvían cuando vuelve.
  • Documentar payload schema en docs/CAPI_META_PAYLOAD.md con ejemplo completo de cada evento. R: Eric. Done cuando: doc en repo + Cortex puede generar payloads correctos.

2.3 TikTok Pixel

  • Confirmar con Martín si tiene cuenta TikTok Ads. Si no, crear cuenta en TikTok Business Center. R: Martín + Eric. Done cuando: cuenta activa + Pixel ID copiado a clients.config_json.pixel_ids.tiktok.
  • Instalar TikTok Pixel base code en app/[client_slug]/layout.tsx con Pixel ID dinámico (NO hardcodear). R: Eric. Done cuando: TikTok Pixel Helper extension valida instalación.
  • Disparar eventos: ViewContent en sales pages, CompleteRegistration post-quiz calificado, InitiateCheckout en click pasarela, CompletePayment en gracias post-compra. R: Eric. Done cuando: 4 eventos visibles en TikTok Events Manager.
  • TikTok Events API server-side (equivalente a CAPI Meta) — opcional pero recomendado: mismo pattern, endpoint https://business-api.tiktok.com/open_api/v1.3/event/track/. R: Eric. Done cuando: server events visibles + match rate aceptable.

2.4 Google Ads Pixel

  • Confirmar con Martín si tiene cuenta Google Ads. Si no, decidir si se crea en Fase 1 o se posterga (si no se invierte en YouTube/Search en piloto, postergar). R: Jesús + Martín. Done cuando: decisión documentada.
  • Si decisión = activar: crear conversion action "Lead Quiz" + "Purchase Taller" + "Purchase Membresía" en Google Ads. R: Eric. Done cuando: 3 conversion IDs + labels copiados a clients.config_json.pixel_ids.google_ads.
  • Instalar Google tag (gtag.js) en layout con conversion ID dinámico, disparar SOLO si ab_source=youtube (para no contaminar conversion data de Meta). R: Eric. Done cuando: cookie ab_source controla disparo + verificable en network tab.
  • Configurar Enhanced Conversions (envía email hasheado para mejor match). R: Eric. Done cuando: Google Ads dashboard muestra Enhanced Conversions activo + verificado.

2.5 ProveSource notificaciones flotantes

  • Crear cuenta ProveSource (free trial 14 días → upgrade $24/mes si validamos lift). R: Eric. Done cuando: dashboard accesible + site_id copiado a config.
  • Configurar notificaciones tipo "Juan de Buenos Aires acaba de registrarse" via webhook desde Supabase eventos registered_calificado → ProveSource API. R: Eric. Done cuando: notificación aparece en /martin/ cuando hay un nuevo lead real.
  • Notificación tipo "X personas vieron esta oferta en las últimas 24hs" en sales pages, alimentada por count de ViewContent events. R: Eric. Done cuando: badge con número actualizado cada 6h via cron.
  • Anti-fake: que las notificaciones sean reales (no inventar leads). Si volumen es bajo en piloto, ocultar notificaciones hasta tener > 20/día. R: Eric + Jesús. Done cuando: regla de visibilidad documentada + implementada.

2.6 UTMs propias persistentes

  • Capturar UTMs desde query string (utm_source, utm_medium, utm_campaign, utm_content, utm_term) al primer hit en /martin/. R: Eric. Done cuando: cookie ta_utms (90 días, json stringified) creada.
  • Capturar también fbclid, gclid, ttclid (click IDs nativos de cada plataforma) para CAPI. R: Eric. Done cuando: cookies separadas + persisten 90 días.
  • First-touch attribution: NO sobreescribir UTMs si ya existen (usuario que vuelve mantiene su atribución original). R: Eric. Done cuando: usuario que entra desde meta hoy y desde tiktok mañana mantiene utm_source=meta en cookie.
  • Persistir UTMs en leads.utm_* al crear el lead. R: Eric. Done cuando: smoke test con ?utm_source=test → fila en Supabase con utm_source='test'.
  • Propagar UTMs a compras (FK a leads, hereda atribución) para reportes de ROAS por canal. R: Eric. Done cuando: query select utm_source, sum(precio) from compras join leads on ... group by 1 retorna breakdown por canal.
  • Naming convention de UTMs documentada en docs/UTM_CONVENTION.md: utm_source ∈ {meta, tiktok, youtube, instagram, organic, email, wa, referral} / utm_medium ∈ {cpc, organic, email, social} / utm_campaign = nombre de la campaña en plataforma / utm_content = nombre del ad o variante. R: Eric + Cortex. Done cuando: doc commiteada + Cortex usa convención al crear UTMs en ads.

2.7 Supabase event logging

  • Cada evento del usuario dispara llamada a /api/track que escribe en eventos con tipo ∈ enum (los 13 valores). R: Eric. Done cuando: smoke test 100 leads cubre los 13 tipos.
  • Helper trackEvent(tipo, lead_id?, data?) en src/lib/tracking/index.ts — wrapper unificado para todos los componentes. R: Eric. Done cuando: cualquier componente puede trackEvent('quiz_started', leadId) sin boilerplate.
  • eventos.data_json debe contener: event_id (para dedup con CAPI), url, referrer, ua, ip (server-set), utms, ab_variant, extra (custom). R: Eric. Done cuando: query a Supabase muestra schema consistente en data_json.
  • Dashboard rápido en Supabase Studio: queries pre-guardadas para "leads de hoy", "conversion rate quiz→registered", "purchases por pasarela", "match rate CAPI". R: Eric. Done cuando: 4 queries guardadas + Jesús puede correrlas.
  • Retention policy: eventos > 180 días se mueven a tabla archive (cron mensual). R: Eric. Done cuando: cron registrado + primera ejecución exitosa.

2.8 Hyros — call tracking unificado (ACTIVO en MVP)

Confirmado 2026-05-05: Hyros (antes referido internamente como "Jairo's pixel") es el sistema de tracking unificado activo desde el MVP. Provee unified attribution, deduplica leads, atribuye llamadas (si hay), e integra con Meta/TikTok/Google Ads para cerrar el loop. Cuenta es de TooAudience (multi-tenant interno).

  • Crear tracking domain en Hyros: i.deacademia.com apuntado a Hyros vía CNAME (o subdomain equivalente del paraguas). R: Eric. Done cuando: DNS propagado + Hyros marca el tracking domain como verified.
  • Instalar Hyros tracking script en app/[client_slug]/layout.tsx con account_id dinámico desde clients.config_json.tracking.hyros_account_id. NO hardcodear. R: Eric. Done cuando: script aparece en <head> de /martin/... + Hyros recibe primer hit.
  • Mapear UTMs a Hyros parameters (hy_source, hy_medium, hy_campaign) desde el helper de UTMs (§ 2.6). R: Eric. Done cuando: query con ?utm_source=meta&utm_campaign=test llega a Hyros con esos parámetros nombrados correctamente.
  • Configurar Hyros call tracking si Martín tiene reservas telefónicas (probablemente NO en este caso — confirmar con Jesús). R: Eric + Jesús. Done cuando: decisión documentada (activado o N/A explícito).
  • Validar que Hyros recibe Lead y Purchase con event_id consistente para dedup contra Meta Pixel + CAPI. R: Eric. Done cuando: dashboard Hyros muestra los eventos + sin doble conteo verificable contra Meta Events Manager.
  • Documentar tracking domain + account ID en _CONFIG.md > infra.hyros (ver § 4 multi-tenant). R: Eric. Done cuando: campos llenados + commiteados.
  • Reconciliación Hyros vs Meta semanal: report comparando atribución Hyros vs Meta Last-Click vs CAPI server. Permite detectar gaps de atribución antes de escalar ads. R: Cortex. Done cuando: cron semanal sábado AM dispara report a grupo interno.

2.9 Validación end-to-end

  • Test manual: dispositivo limpio + IP nueva + abrir DevTools → entrar a /martin/?utm_source=test_meta&utm_campaign=smoke_test → completar quiz calificado → ir a WhatsApp → simular compra. Verificar: R: Eric + Jesús. Done cuando: log en cada destino:
  • Meta Pixel Helper: PageView, ViewContent (sales page), Lead, InitiateCheckout, Purchase
  • Meta Events Manager: mismos 5 eventos browser + 3 server (Lead, IC, Purchase) deduplicados
  • TikTok Pixel Helper: equivalentes
  • Supabase eventos: 5+ filas con event_id consistente
  • Supabase leads: 1 fila con utm_source='test_meta', utm_campaign='smoke_test'
  • Supabase compras: 1 fila con FK a lead correcto
  • ProveSource: notificación con el lead nuevo
  • Match rate Meta ≥ 70% medido en Events Manager > Diagnostics tras 100 eventos reales. R: Eric. Done cuando: screenshot con métrica archivada.

3. Variables y posibilidades a anticipar

Escenario Plan B
iOS 14+ ATT bloquea Pixel browser-side (opt-out de ~70% iOS users) CAPI server-side cubre el gap. Asegurar paridad de eventos: todo evento browser tiene su contraparte server.
Match rate CAPI < 70% Agregar más datos en user_data: zip, dob, country. Cookies fbp/fbc obligatorias. Hash SHA256 correcto (lowercase trim).
System User token Meta se revoca (poco frecuente pero pasa) Documentar proceso de regeneración en runbook. Alerta de Vercel si CAPI retorna 401 → notificar Eric.
Pixel Meta dispara duplicados (browser + CAPI sin event_id) Auditar todo evento tenga event_id consistente. Test con Events Manager > Overlap > debe mostrar "Deduplicated".
Martín no tiene cuenta TikTok Ads Postergar TikTok pixel a fase 2 (después del primer launch). Documentar como "no implementado en MVP".
Google Ads no decidido aún Prepar el código pero comentado, listo para activar agregando ID al config.
ProveSource muestra notificaciones falsas (bug de webhook) Disable temporal + investigar. Mejor sin notificaciones que con falsas.
UTMs sobreescritas por integración accidental (script third-party las modifica) Cookie HttpOnly + sameSite Lax + log de modificaciones para debug.
fbclid muy largo rompe URL en algunos browsers Encodear correctamente + truncar a 150 chars con warning si excede.
Supabase eventos se llena rápido (millones de PageView) Sample PageView a 10% (1 de cada 10 se loguea). Mantener 100% para eventos críticos (Lead, Purchase).
Vercel function timeout en /api/capi-meta (10s en hobby plan) Mover CAPI a Railway worker async (queue). Vercel solo encola, worker procesa.
Hyros + Meta Pixel reportan números muy distintos (gap de atribución > 30%) Reconciliación obligatoria semanal. Hyros suele ser source-of-truth para optimización (last-click + multi-touch). Ajustar criterio de optimización en agents/meta-ads/ si discrepancia es estructural.
Eventos no llegan a Meta por adblocker en cliente CAPI cubre porque corre server-side. Métrica de gap browser-vs-server visible en Diagnostics.
Test events Meta saturados con datos reales Sacar test_event_code del payload antes de pasar a producción + grep en código para asegurarlo.

4. Multi-tenant: cómo se replica al cliente #2

Esta sección alimenta sop/lanzar-cliente/13_TRACKING_NEW_CLIENT.md.

  • Variables a externalizar (todo en clients.config_json):
  • pixel_ids.meta — Pixel ID Meta del cliente
  • pixel_ids.tiktok — Pixel ID TikTok
  • pixel_ids.google_ads — Conversion ID + Label
  • pixel_ids.provesource_site_id
  • tracking.hyros_account_id — Account ID Hyros del cliente (puede ser sub-cuenta del paraguas TooAudience)
  • tracking.hyros_tracking_domain — dominio CNAME para Hyros (ej i.deacademia.com con cliente_slug en path)
  • tracking.hyros_call_id — ID si Hyros call tracking se usa (opcional)
  • capi.access_token — System User token Meta del cliente (en Vercel env var, NO config_json — es secreto)
  • capi.test_event_code — solo en dev/staging
  • tracking.utm_naming_convention — defaults por cliente si difiere
  • tracking.events_to_capi[] — qué eventos se envían server-side (default: Lead, Purchase, IC)
  • tracking.advanced_matching_fields[] — qué fields de user_data se hashean

  • Templates a guardar en sop/lanzar-cliente/templates/tracking/:

  • meta-pixel.template.tsx — componente con placeholder {{PIXEL_ID}}
  • tiktok-pixel.template.tsx
  • google-ads.template.tsx
  • provesource.template.tsx
  • hyros.template.tsx — script Hyros con {{HYROS_ACCOUNT_ID}} + {{HYROS_TRACKING_DOMAIN}}
  • capi-meta-route.template.ts — route handler genérico
  • track-helper.template.ts — wrapper trackEvent()
  • utm-helper.template.ts — incluye mapeo UTM → hy_* params
  • CAPI_META_PAYLOAD.template.md — doc de payload

  • Sustituciones automáticas (clone_client.py extiende):

  • Crear nuevos Pixel IDs en plataformas (manual paso por cliente — Meta no permite crear pixel via API en algunos casos)
  • Insertar IDs en clients.config_json del nuevo cliente
  • Generar nuevo System User Meta token + cargar en Vercel env var con prefijo ${CLIENT_SLUG}_META_CAPI_TOKEN
  • Crear cuenta ProveSource separada o site adicional en cuenta existente

  • Ítems que requieren acción manual del cliente nuevo (no automatizables):

  • Crear/aprobar Business Manager Meta del cliente
  • Crear cuenta TikTok Ads
  • Crear cuenta Google Ads (si aplica)
  • Provisionar sub-cuenta o tracking domain Hyros para el cliente nuevo (acción interna TooAudience, no requiere acción del cliente)

5. Recursos y archivos relacionados

  • 01_INFRA_TECNICA.md — Vercel API routes corren CAPI
  • 02_LANDINGS_Y_PAGES.md — pages que disparan eventos
  • 14_META_OPTIMIZACIONES.md — campañas que consumen los pixels
  • ../02_PLAN_INTERNO_EQUIPO.md — § 1.6 tracking pixels + § 1.7 CAPI server-side
  • Meta Conversions API: https://developers.facebook.com/docs/marketing-api/conversions-api
  • TikTok Events API: https://ads.tiktok.com/marketing_api/docs?id=1741601162187777
  • Google Enhanced Conversions: https://support.google.com/google-ads/answer/9888656
  • ProveSource: https://provesrc.com/
  • Hyros docs: https://hyros.com/docs (ver onboarding tracking domain + UTM mapping)

6. Notas y aprendizajes (post-mortem)

Llenar después del primer ciclo. Estos aprendizajes son los que se llevan al SOP.

  • (vacío hasta primera ejecución)

CHANGELOG

  • 2026-05-05 — Cortex (agente A) — Creación inicial. PENDIENTE: confirmar con Jesús qué es "Jairo's pixel" — slot reservado en config + componente placeholder hasta resolución.
  • 2026-05-05 — JT — Hyros confirmado como tracking activo (era "Jairo's pixel" placeholder), no postergado. Reemplazada § 2.8 con tareas concretas Hyros + sumadas variables hyros_account_id / hyros_tracking_domain / hyros_call_id al multi-tenant.