Ir al contenido

Sincronización y retención de datos

Por defecto, Presage almacena todos los datos localmente en el navegador (localStorage). Esto funciona muy bien para la adaptación en un solo dispositivo, pero los datos se pierden cuando el usuario limpia su navegador.

Con una licencia Presage Pro ($19/mes), puedes sincronizar eventos, traits y señales con un backend para:

  • Persistencia entre dispositivos — el contexto del usuario lo sigue entre navegadores
  • Retención a largo plazo — los eventos se conservan más allá del límite de 30 días del navegador
  • Panel de análisis — visualiza el comportamiento del usuario, la distribución de madurez y el uso de funcionalidades
  • Seguridad por dominio — restringe tu licencia solo a dominios autorizados

Regístrate en dashboard.presage-kit.dev, crea un proyecto y copia tu clave de licencia.

Pasa un objeto sync a createAdaptiveClient con tu clave de licencia:

import {
createAdaptiveClient,
createLocalStorageDriver,
} from '@presage-kit/core'
const client = createAdaptiveClient({
persistence: {
driver: createLocalStorageDriver('my-app'),
},
sync: {
license: 'pk_live_abc123…',
// Opciones opcionales (valores por defecto):
// batchIntervalMs: 10_000,
// maxBatchSize: 100,
// maxRetries: 3,
onSyncError: (error) => {
console.warn('[presage sync]', error.type, error.message)
},
},
rules: [
// …tus reglas de adaptación
],
})

En el panel, ve a la configuración de tu proyecto y añade tus dominios de producción. Localhost siempre está permitido para desarrollo.

Presage utiliza una estrategia batch-and-flush para minimizar el tráfico de red:

  1. Agrupación por lotes — los eventos, cambios de traits y actualizaciones de señales se ponen en cola en memoria en lugar de enviarse individualmente.
  2. Intervalo de flush — cada 10 segundos (configurable mediante batchIntervalMs), la cola se vacía en una única petición HTTP a https://api.presage-kit.dev/api/v1/ingest.
  3. Flush por tamaño — si la cola alcanza maxBatchSize (100 por defecto) antes del temporizador, se vacía inmediatamente.
  4. Resiliencia offline — si un flush falla por un error de red, los eventos se devuelven a la cola y se reintentan en el siguiente intervalo. Presage usa backoff exponencial (1s, 2s, 4s) hasta maxRetries intentos.
  5. Degradación elegante — si la licencia es inválida o el dominio no está autorizado, la sincronización se desactiva permanentemente para la sesión. El motor principal sigue funcionando localmente sin interrupción.
  6. Flush de destrucción — cuando se llama a client.destroy(), se intenta un último flush para no perder datos al descargar la página.

El cliente expone un átomo reactivo syncStatus para reflejar el estado de la sincronización en tu interfaz:

import type { SyncStatus } from '@presage-kit/core'
// SyncStatus = 'idle' | 'validating' | 'active' | 'degraded' | 'disabled'
if (client.syncStatus) {
client.syncStatus.subscribe((status: SyncStatus) => {
switch (status) {
case 'idle':
// Sync configurado pero aún no validado
break
case 'validating':
// Verificación de licencia en progreso
break
case 'active':
// Licencia válida — los eventos se están sincronizando
break
case 'degraded':
// Error de red durante la validación — se reintentará
break
case 'disabled':
// Licencia inválida o dominio no autorizado
break
}
})
}

Cuando syncStatus es null, la sincronización no está configurada (plan Gratis).

Presage usa una lista de dominios autorizados para prevenir el abuso de licencia:

  • Cada petición de sincronización incluye un encabezado X-Origin con el window.location.origin actual.
  • El backend compara este origen con los dominios que configuraste en el panel.
  • Si el origen no coincide, el backend devuelve un 403 Forbidden y el cliente desactiva la sincronización durante el resto de la sesión.
  • localhost y 127.0.0.1 siempre están permitidos para no bloquear nunca el desarrollo.

El callback onSyncError recibe un objeto de error tipado que distingue entre errores auth (licencia inválida), forbidden (dominio no coincidente), rate_limit, network y server — permitiéndote manejar cada caso de forma apropiada.