Sincronización y retención de datos
Descripción general
Sección titulada «Descripción general»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
Instalación
Sección titulada «Instalación»1. Obtener una clave de licencia
Sección titulada «1. Obtener una clave de licencia»Regístrate en dashboard.presage-kit.dev, crea un proyecto y copia tu clave de licencia.
2. Configurar tu cliente
Sección titulada «2. Configurar tu cliente»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 ],})3. Configurar los dominios autorizados
Sección titulada «3. Configurar los dominios autorizados»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.
Cómo funciona la sincronización
Sección titulada «Cómo funciona la sincronización»Presage utiliza una estrategia batch-and-flush para minimizar el tráfico de red:
- 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.
- Intervalo de flush — cada 10 segundos (configurable mediante
batchIntervalMs), la cola se vacía en una única petición HTTP ahttps://api.presage-kit.dev/api/v1/ingest. - Flush por tamaño — si la cola alcanza
maxBatchSize(100 por defecto) antes del temporizador, se vacía inmediatamente. - 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
maxRetriesintentos. - 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.
- Flush de destrucción — cuando se llama a
client.destroy(), se intenta un último flush para no perder datos al descargar la página.
Estado de sincronización
Sección titulada «Estado de sincronización»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).
Seguridad
Sección titulada «Seguridad»Presage usa una lista de dominios autorizados para prevenir el abuso de licencia:
- Cada petición de sincronización incluye un encabezado
X-Origincon elwindow.location.originactual. - 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.
localhosty127.0.0.1siempre 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.