Ir al contenido

Tracking entre subdominios

Tu sitio de marketing vive en example.com, tu app en app.example.com. localStorage es por origin: si la identidad viviera solo ahí, el visitante que leyó tu página de precios y el visitante que se registra en tu app recibirían dos ids anónimos distintos, y el historial previo al registro — con la campaña que lo trajo — moriría en la frontera antes de que identify() tuviera oportunidad de conectarlo.

La persistencia por defecto es 'localStorage+cookie' con cookieDomain: 'auto', así que el snippet pelado cruza subdominios sin configuración alguna:

kilden.init('YOUR_WRITE_KEY');

El paquete de identidad vive en una cookie first-party con scope en el dominio registrable — el único storage que todos los subdominios pueden leer —, espejada en localStorage. Instala el snippet en ambos sitios con el mismo write key y el visitante conserva el mismo id anónimo al cruzar; identify() en el registro conecta todo el historial de navegación previo con el usuario nuevo.

Solo identidad: el id anónimo, el distinct id, la sesión, el estado de opt-out y el registro de first touch (más abajo). Las super properties, caches y colas se quedan en localStorage — las cookies viajan en el header de cada request a tu dominio, así que a la cookie solo va lo que debe sobrevivir el cruce.

cookieDomain: 'auto' prueba dominios candidatos del más amplio al más estrecho y se queda con el primero que el navegador acepta. Los sufijos públicos (io, co.uk) rebotan en el cookie jar, así que auto aterriza en el dominio registrable (eTLD+1): en app.example.co.uk la cookie queda con scope .example.co.uk. Los hosts sin dominio (localhost, IPs) reciben una cookie host-only.

Si prefieres no depender de la detección en producción, fija el scope — es una suposición menos:

kilden.init('YOUR_WRITE_KEY', {
cookieDomain: '.example.com',
});

Si el navegador rechaza el scope pedido (un dominio que no calza con el host, un sufijo público), el SDK no funciona a medias con una cookie que nunca se pega — cae al comportamiento de solo localStorage.

Y para desactivar las cookies por completo:

kilden.init('YOUR_WRITE_KEY', {
persistence: 'localStorage',
});

Esto mantiene todo en el localStorage por origin — nunca se escribe una cookie, y la identidad deja de cruzar subdominios.

El default escribe una cookie first-party. Si tu setup necesita quedar libre de cookies, desactívalas con persistence: 'localStorage' — pero no asumas que eso por sí solo zanja la pregunta de compliance: regulaciones como las reglas ePrivacy de la UE son en general tecnológicamente neutrales, y almacenar información en el dispositivo del visitante puede requerir consentimiento sin importar el mecanismo, así que revisa tu propia asesoría de privacidad sobre lo que te aplica. Lo que sí cambia con las cookies es que los escáneres de consentimiento las detectan — espera que la cookie de Kilden aparezca en las auditorías automatizadas, y asegúrate de que tu banner de consentimiento la declare.

Migración: los visitantes existentes conservan su historial

Sección titulada «Migración: los visitantes existentes conservan su historial»

El default es seguro para sitios con tráfico existente:

  • Adopción antes que frescura. Una identidad previa en localStorage se adopta dentro de la cookie, no se reemplaza — los visitantes existentes conservan su id y su historial en vez de bifurcarse en un desconocido.
  • La cookie gana la divergencia. Cuando dos subdominios tenían ids previos distintos, la primera página que carga escribe la cookie compartida y la otra se alinea — determinístico, sin peleas. Los eventos ya enviados bajo el otro id siguen atribuidos a él; si ese visitante se identifica, la resolución de identidad une los rastros.

Activada por defecto, sin configuración. El SDK congela como traits de la persona dos hechos con vidas distintas:

  • Cómo llegaron por primera vez — se escribe en la primerísima visita, incluso una directa: $initial_referrer ($direct cuando no hay), $initial_referring_domain, $initial_landing_page.
  • Qué campaña los alcanzó primero$initial_utm_source, $initial_utm_medium, $initial_utm_campaign, $initial_utm_term, $initial_utm_content, escritos la primera vez que alguna vez aparece un parámetro utm_*, que puede ser visitas después.

Una primera visita directa no deja los campos de campaña bloqueados en nada — una diferencia deliberada con PostHog, que congela ambos en la visita uno. Así se responden las dos preguntas en vez de una.

Todo viaja como $set_once, que el pipeline aplica por clave: lo tardío nunca sobreescribe lo temprano, y reenviar es inofensivo. Las properties de contexto $utm_* por evento no cambian — cada evento sigue llevando la campaña de su propia visita (mira Eventos y properties).

El registro de first touch es parte del paquete de identidad, así que con la persistencia por defecto el sitio de marketing y la app coinciden en lo que ya quedó registrado — la campaña capturada en example.com no se vuelve a congelar distinta en app.example.com.

Ambas opciones están documentadas en la referencia de configuración del SDK.