13 — Pixel & Tracking
Índice de la página
- 01Cliente: Martín Rieznik / LevantArte
- Área: Tracking / Attribution / Server-side Events
- 020. Definición de "done" para esta checklist
- 031. Pre-requisitos
- 042. Tareas
- 2.1 Meta Pixel — browser-side
- 2.2 Conversions API server-side — /api/capi-meta
- 2.3 TikTok Pixel
- 2.4 Google Ads Pixel
- 2.5 ProveSource notificaciones flotantes
- 2.6 UTMs propias persistentes
- 2.7 Supabase event logging
- 2.8 Hyros — call tracking unificado (ACTIVO en MVP)
- 2.9 Validación end-to-end
- 053. Variables y posibilidades a anticipar
- 064. Multi-tenant: cómo se replica al cliente #2
- 075. Recursos y archivos relacionados
- 086. Notas y aprendizajes (post-mortem)
- 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
LeadyPurchaseconfirmados. - Supabase tabla
eventosrecibe 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 deleads.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.tsxcon Pixel ID dinámico desde config (NO hardcodear). R: Eric. Done cuando: ver pixel dispararPageViewen Pixel Helper extension visitando/martin/. - Disparar
PageViewautomático en cada page (incluido en base code). R: Eric. Done cuando: Events Manager registra PageView en tiempo real. - Disparar
ViewContenten/martin/tallery/martin/membresiaconcontent_name,content_category,value,currency. R: Eric. Done cuando: 2 eventos visibles en Events Manager con metadata. - Disparar
Leaden/martin/gracias-calificado(browser) conevent_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
InitiateCheckouten 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 conpasarela,sku,value. - Disparar
CompleteRegistrationen bot WhatsApp confirmando lead (delegado al bot via API si aplica, sino solo browser). R: Eric. Done cuando: aparece en Events Manager. - Disparar
Purchaseen/martin/taller/graciasy/martin/membresia/graciasconvalue,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 varMETA_CAPI_TOKEN. - Crear API route
src/app/api/capi-meta/route.tsPOST que recibe{event_name, event_id, user_data, custom_data, event_source_url}y forwarda a Meta Conversions API endpointhttps://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 porevent_idcuando 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),fbpyfbccookies enuser_datapara mejorar match rate. R: Eric. Done cuando: Diagnostics > Event Match Quality verde para CAPI events. - Test mode: usar
test_event_codeen 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
eventoscontipo='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.mdcon 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.tsxcon Pixel ID dinámico (NO hardcodear). R: Eric. Done cuando: TikTok Pixel Helper extension valida instalación. - Disparar eventos:
ViewContenten sales pages,CompleteRegistrationpost-quiz calificado,InitiateCheckouten click pasarela,CompletePaymenten 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 siab_source=youtube(para no contaminar conversion data de Meta). R: Eric. Done cuando: cookieab_sourcecontrola 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
ViewContentevents. 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: cookieta_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 conutm_source='test'. - Propagar UTMs a
compras(FK aleads, hereda atribución) para reportes de ROAS por canal. R: Eric. Done cuando: queryselect utm_source, sum(precio) from compras join leads on ... group by 1retorna 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/trackque escribe eneventoscontipo∈ enum (los 13 valores). R: Eric. Done cuando: smoke test 100 leads cubre los 13 tipos. - Helper
trackEvent(tipo, lead_id?, data?)ensrc/lib/tracking/index.ts— wrapper unificado para todos los componentes. R: Eric. Done cuando: cualquier componente puedetrackEvent('quiz_started', leadId)sin boilerplate. -
eventos.data_jsondebe 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.comapuntado 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.tsxconaccount_iddinámico desdeclients.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=testllega 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
LeadyPurchaseconevent_idconsistente 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 conevent_idconsistente - Supabase
leads: 1 fila conutm_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 clientepixel_ids.tiktok— Pixel ID TikTokpixel_ids.google_ads— Conversion ID + Labelpixel_ids.provesource_site_idtracking.hyros_account_id— Account ID Hyros del cliente (puede ser sub-cuenta del paraguas TooAudience)tracking.hyros_tracking_domain— dominio CNAME para Hyros (eji.deacademia.comcon 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/stagingtracking.utm_naming_convention— defaults por cliente si difieretracking.events_to_capi[]— qué eventos se envían server-side (default: Lead, Purchase, IC)-
tracking.advanced_matching_fields[]— qué fields deuser_datase hashean -
Templates a guardar en
sop/lanzar-cliente/templates/tracking/: meta-pixel.template.tsx— componente con placeholder{{PIXEL_ID}}tiktok-pixel.template.tsxgoogle-ads.template.tsxprovesource.template.tsxhyros.template.tsx— script Hyros con{{HYROS_ACCOUNT_ID}}+{{HYROS_TRACKING_DOMAIN}}capi-meta-route.template.ts— route handler genéricotrack-helper.template.ts— wrappertrackEvent()utm-helper.template.ts— incluye mapeo UTM → hy_* params-
CAPI_META_PAYLOAD.template.md— doc de payload -
Sustituciones automáticas (
clone_client.pyextiende): - 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_jsondel 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 CAPI02_LANDINGS_Y_PAGES.md— pages que disparan eventos14_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_idal multi-tenant.