# Eventos y API JavaScript del widget Findalo

> Documentación para desarrolladores de Findalo (buscador SaaS para tiendas online). Versión HTML: https://findalo.io/devs/eventos/
> Contrato estable: los tokens, clases, variables y eventos documentados solo se amplían, nunca se renombran ni eliminan. Todo lo NO documentado es interno del widget y puede cambiar sin aviso.

`window.findalo` expone un bus de eventos y métodos de control. El JS puede vivir en la tienda o en el editor del panel (Apariencia → Avanzado). Los nombres de eventos y las claves de payload son contrato estable.

## Eventos — findalo.on(nombre, callback)

| Evento | Payload | Cuándo |
|---|---|---|
| `search` | `{ query, total, took_ms, match_mode, lang }` | Cada búsqueda ejecutada (query de 2+ caracteres). match_mode indica si los resultados son directos o sugeridos («fallback»). |
| `zero` | `{ query, total: 0, took_ms, match_mode, lang }` | Búsqueda con 0 resultados. Raro: el buscador nunca deja la pantalla vacía — la señal real de «sin resultados» es search con match_mode «fallback». |
| `click` | `{ product_id, product_name, product_url, price, currency, query, position }` | Click en un producto de los resultados. |
| `add-to-cart` | `{ product_id, product_name, price, currency, quantity, cart_count }` | Producto añadido al carrito desde el buscador. |
| `quick-view` | `{ product_id, product_name, product_url, price, currency, query, position }` | Apertura de la vista rápida de un producto. |
| `cart-open` | `{ cart_count }` | Apertura del panel de la cesta desde la cabecera del buscador. |
| `express-purchase` | `{ payment_intent, order_id, reference }` | Compra completada vía checkout exprés (si está activo). |
| `open` | `{ prefill }` | Apertura del buscador. prefill lleva la query inicial si la hay. |
| `close` | `{}` | Cierre del buscador. |
| `context` | `el objeto window.FINDALO_CTX completo` | El contexto de navegación ya resuelto, con la parte privada (carrito y cliente) incluida. Dispara una vez por carga de página. Ver /devs/contexto. |

## Métodos y propiedades

| Método / propiedad | Qué hace |
|---|---|
| `findalo.on(evento, callback)` | Se suscribe a un evento del bus. Devuelve una función para desuscribirse. |
| `findalo.open(query?)` | Abre el buscador, opcionalmente con una query inicial. |
| `findalo.search(query)` | Abre el buscador y ejecuta la query. |
| `findalo.close()` | Cierra el buscador. |
| `findalo.tenant` | Slug del buscador (solo lectura). |
| `findalo.lang` | Idioma activo del widget (solo lectura). |
| `findalo.version` | Versión del API JS (solo lectura). |
| `findalo.context()` | Contexto de navegación de la página: la misma variable window.FINDALO_CTX (tipo de página, ids, idioma, divisa, carrito, cliente). Ver /devs/contexto. |
| `findalo.onContext(callback)` | Ejecuta el callback con el contexto COMPLETO (carrito y cliente ya resueltos); si ya lo está, en el acto. Es la vía correcta si dependes del carrito. |

## Ejemplos

```js
// Búsquedas a GA4 (hay integración sin código en el panel; esto es la vía manual)
findalo.on('search', (e) => {
  gtag?.('event', 'site_search', { search_term: e.query, results: e.total });
});

// «Sin resultados reales»: el buscador nunca deja la pantalla vacía; si nada
// casa muestra sugeridos con match_mode 'fallback' — esa es la señal, no 'zero'.
findalo.on('search', (e) => {
  if (e.match_mode === 'fallback') { /* ej. abrir chat de soporte */ }
});

// Abrir desde tus propios elementos
document.querySelector('#hero-buscar')?.addEventListener('click', () => findalo.open());
```
