> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scanova.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Referencia del modelo de eventos

> Referencia completa de campos para los eventos de navegador y de servidor: qué enviar, qué hace cada campo y cómo se guardan y enriquecen los eventos.

Todos los eventos que envías al seguimiento de conversiones de Scanova, vengan del navegador o de tu servidor, comparten la misma estructura. Esta página documenta todos los campos que puedes incluir y explica qué hace con ellos el sistema de seguimiento.

## Eventos del navegador (`POST /ct`)

Los eventos del navegador los envía el SDK automáticamente, o tú a mano con `scanova('track', ...)`. Representan acciones que ocurren en el navegador del visitante.

### Campos que puedes enviar

| Campo             | Tipo            | Obligatorio | Descripción                                                                                                                                                                                                                                                                                                                                                                                                 |
| ----------------- | --------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `event_id`        | Cadena UUID     | No          | Identificador único de este evento. Si lo omites, lo genera el SDK. Envía un ID estable desde tu código si quieres reintentar sin riesgo.                                                                                                                                                                                                                                                                   |
| `site_id`         | Cadena          | Sí          | El ID de tu sitio de seguimiento, disponible en el panel.                                                                                                                                                                                                                                                                                                                                                   |
| `event_type`      | Cadena          | Sí          | El tipo de evento. Usa snake\_case (por ejemplo `page_view`, `cta_click` o `signup_completed`).                                                                                                                                                                                                                                                                                                             |
| `scan_session_id` | Cadena UUID     | No          | El SDK lo toma automáticamente del parámetro `scnv` de la URL. Imprescindible para atribuir al código QR.                                                                                                                                                                                                                                                                                                   |
| `web_session_id`  | Cadena UUID     | No          | Lo asigna el SDK automáticamente en cada sesión del navegador (con un límite de 30 minutos).                                                                                                                                                                                                                                                                                                                |
| `visitor_id`      | Cadena UUID     | No          | Lo asigna el SDK automáticamente. Se conserva un año en una cookie.                                                                                                                                                                                                                                                                                                                                         |
| `page_url`        | Cadena          | No          | URL completa de la página actual, incluida la cadena de consulta.                                                                                                                                                                                                                                                                                                                                           |
| `page_title`      | Cadena          | No          | Título de la página. El SDK del navegador no lo envía; solo es útil en integraciones propias directas con la API.                                                                                                                                                                                                                                                                                           |
| `referrer`        | Cadena          | No          | La URL de procedencia.                                                                                                                                                                                                                                                                                                                                                                                      |
| `event_time`      | Cadena ISO 8601 | No          | Hora del evento en UTC. Si lo omites, se usa la hora de recepción en el servidor. Un valor explícito se respeta y no se sustituye por la hora de recepción, así que un evento con fecha anterior cae en el periodo que indica, algo útil al cargar o migrar datos. Ojo: el SDK del navegador envía una clave `timestamp` que es un campo interno aparte; si llamas a la API directamente, usa `event_time`. |
| `device`          | Objeto          | No          | Contexto del navegador y del dispositivo: ver más abajo.                                                                                                                                                                                                                                                                                                                                                    |
| `metadata`        | Objeto          | No          | Datos propios de clave-valor. Máximo 10 KB y 5 niveles de profundidad. Sin direcciones de correo en texto plano.                                                                                                                                                                                                                                                                                            |

**Campos del objeto `device`:**

| Campo           | Descripción                                |
| --------------- | ------------------------------------------ |
| `user_agent`    | Cadena user-agent del navegador            |
| `screen_width`  | Ancho de pantalla en píxeles               |
| `screen_height` | Alto de pantalla en píxeles                |
| `language`      | Idioma del navegador (por ejemplo `en-US`) |

### Ejemplo de contenido de un evento del navegador

```json theme={null}
{
  "event_id": "f9ac7db6-f900-4d8e-8918-c846834195a8",
  "site_id": "N74rwgykxCwUe7SDFb2BMVN8Kc0aCQvKajiUKz9MSk3Bldn70jw8uLE3dUTgeS6r",
  "event_type": "cta_click",
  "scan_session_id": "7ad26d4f-3181-4ef8-b6ca-b8f59499dd43",
  "page_url": "https://yoursite.com/?scnv=7ad26d4f-3181-4ef8-b6ca-b8f59499dd43",
  "referrer": "",
  "timestamp": "2026-05-13T10:00:00.000Z",
  "device": {
    "user_agent": "Mozilla/5.0 ...",
    "screen_width": 1680,
    "screen_height": 1050,
    "language": "en-US"
  },
  "metadata": {
    "button_text": "Start Free Trial",
    "section": "pricing"
  }
}
```

***

## Eventos de servidor (`POST /server-events`)

Los eventos de servidor se envían desde tu backend con una clave de API. Representan acciones que ocurren en tu servidor, como compras completadas, registros confirmados o leads creados en tu CRM.

### Campos que puedes enviar

| Campo              | Tipo            | Obligatorio | Descripción                                                                                                 |
| ------------------ | --------------- | ----------- | ----------------------------------------------------------------------------------------------------------- |
| `event_id`         | Cadena UUID     | Recomendado | ID único del evento para reintentar sin riesgo. Genéralo una vez, guárdalo y reutilízalo en cada reintento. |
| `site_id`          | Cadena          | Sí          | El ID de tu sitio de seguimiento. Debe corresponder al sitio autorizado de la clave de API.                 |
| `event_name`       | Cadena          | Sí          | Nombre descriptivo del evento (por ejemplo `purchase`, `signup` o `lead`).                                  |
| `scan_session_id`  | Cadena UUID     | Sí          | Enlaza este evento de servidor con el escaneo que lo originó. Pásalo del navegador a tu servidor.           |
| `web_session_id`   | Cadena UUID     | No          | El ID de sesión web del navegador: pásalo si lo tienes, para enlazar mejor las sesiones.                    |
| `visitor_id`       | Cadena UUID     | No          | El ID de visitante persistente del navegador: pásalo si lo tienes.                                          |
| `event_time`       | Cadena ISO 8601 | No          | Cuándo ocurrió el evento. Por defecto, la hora de recepción.                                                |
| `conversion_value` | Objeto          | No          | `{ "amount": 99.99, "currency": "USD" }`. La moneda debe ser un código ISO 4217 de tres letras.             |
| `user_identifiers` | Objeto          | No          | Identificadores de usuario con hash: ver más abajo. Nunca envíes el correo ni el teléfono en texto plano.   |
| `properties`       | Objeto          | No          | Metadatos propios de clave-valor. Máximo 10 KB. Sin correos en texto plano.                                 |
| `consent`          | Cadena          | No          | `granted`, `denied` o `pending`.                                                                            |

**Campos del objeto `user_identifiers` (todos con hash):**

| Campo         | Descripción                                            |
| ------------- | ------------------------------------------------------ |
| `email_hash`  | Hash SHA-256 del correo del usuario en minúsculas      |
| `phone_hash`  | Hash SHA-256 del teléfono del usuario en formato E.164 |
| `external_id` | Tu ID interno de usuario o cliente                     |

### Ejemplo de contenido de un evento de servidor

```json theme={null}
{
  "event_id": "550e8400-e29b-41d4-a716-446655440000",
  "site_id": "N74rwgykxCwUe7SDFb2BMVN8Kc0aCQvKajiUKz9MSk3Bldn70jw8uLE3dUTgeS6r",
  "event_name": "purchase",
  "scan_session_id": "7ad26d4f-3181-4ef8-b6ca-b8f59499dd43",
  "conversion_value": { "amount": 49.99, "currency": "USD" },
  "user_identifiers": {
    "email_hash": "b94d27b9934d3e08a52e52d7da7dabfac484efe04294e576fc583c381f2d9c5d",
    "external_id": "usr_1234"
  },
  "properties": {
    "order_id": "ord_9876",
    "plan": "pro"
  }
}
```

***

## Convenciones para nombrar eventos

Usa nombres coherentes y descriptivos en `snake_case`. Un esquema claro hace que los informes se lean mejor.

| Bien               | Evita                        |
| ------------------ | ---------------------------- |
| `page_view`        | `pageView`, `PageView`, `pv` |
| `cta_click`        | `click1`, `btnClick`         |
| `signup_completed` | `signup`, `reg`              |
| `purchase`         | `buy`, `order_placed_final`  |

## Idempotencia

Tanto los eventos del navegador como los de servidor admiten un campo `event_id` para la deduplicación:

* Si el mismo `event_id` llega más de una vez, el duplicado se guarda pero se marca con `is_duplicate = 1`
* Los duplicados quedan fuera de las vistas analíticas de forma automática
* **Reutiliza siempre el mismo `event_id` al reintentar un evento de servidor fallido**

## Privacidad y RGPD

* **Nunca envíes direcciones de correo en texto plano** en `metadata` ni en `properties`. Usa `user_identifiers` con valores con hash.
* El campo `consent` controla el tratamiento de los datos personales en el sistema:
  * `granted`: todos los campos se guardan con normalidad
  * `denied` o `pending`: `page_url`, `referrer`, `city` y `metadata` se eliminan antes de guardar
  * El propio valor de `consent` se guarda siempre como registro de auditoría

### Enviar el consentimiento desde el navegador

El SDK del navegador no trae una API de consentimiento integrada. Lo recomendable es **cargar el SDK solo si procede**, según lo que decida tu plataforma de gestión del consentimiento:

```html theme={null}
<script>
  // Only load the SDK after the user grants consent
  if (userHasGrantedConsent()) {
    (function(w,d,s,o,f,js,fjs){
      w['ScanovaTrackingObject']=o;w[o]=w[o]||function(){(w[o].q=w[o].q||[]).push(arguments)};
      js=d.createElement(s),fjs=d.getElementsByTagName(s)[0];
      js.id=o;js.src=f;js.async=1;fjs.parentNode.insertBefore(js,fjs);
    })(window,document,'script','scanova','https://cdn.scanova.io/ct/js/qcg.min.js');
    scanova('init', 'YOUR_SITE_ID', { autoPageview: true });
  }
</script>
```

### Enviar el consentimiento desde el servidor

En los eventos de servidor, envía el valor de `consent` directamente en el contenido de cada petición, junto al resto de campos.
