# API JavaScript del Widget

> Controla el widget desde tu sitio web con window.PlzWidget

Fuente: https://developers.plazbot.com/sdk/widget-api/

### Introducción

Cuando el script del widget se carga en tu página, expone el objeto global **`window.PlzWidget`**. Con el puedes abrir o cerrar el chat desde tus propios botones, enviar mensajes, identificar al usuario que inicio sesión en tu sitio y reaccionar a lo que ocurre en la conversación.

> **Nota:** La API es compatible con versiones anteriores: `open()`, `close()` y `toggle()` funcionan igual que siempre. El resto de métodos son adicionales.

### Esperar a que el widget cargue

El script del widget se instala con `defer`, así que `window.PlzWidget` no existe hasta que el script se ejecuta. Para usar la API apenas este disponible, define `window.PlzWidgetOnLoad` **antes** del script del widget:

```html
<script>
window.PlzWidgetOnLoad = function (PlzWidget) {
  PlzWidget.on('ready', function () {
    console.log('Widget listo');
  });
};
</script>

<script id="id-widget-agent-plz" type="module" defer
src="https://storagelaplazbot.z13.web.core.windows.net/widget.js?Id={ID_AGENT}&zone={ZONE}&workspaceId={WORKSPACE_ID}">
</script>
```

- `PlzWidgetOnLoad` se ejecuta en cuanto `window.PlzWidget` existe.
- El evento `ready` se dispara cuando la configuración del agente término de cargar. Si te suscribes a `ready` cuando el widget ya estaba listo, el callback se ejecuta de inmediato.
- Los métodos `sendMessage` e `identify` se pueden llamar antes de `ready`: quedan en cola y se ejecutan al cargar la configuración.

### Métodos

| Método | Descripción |
|--------|-------------|
| `open()` | Abre el widget |
| `close()` | Cierra el widget |
| `toggle()` | Abre o cierra el widget según su estado actual |
| `isOpen()` | Devuelve `true` si el widget esta abierto |
| `sendMessage(text)` | Abre el chat y envía `text` como si lo hubiera escrito el usuario |
| `identify(data)` | Registra los datos del usuario en el contacto (ver abajo) |
| `hideLauncher()` | Oculta el botón flotante del widget |
| `showLauncher()` | Vuelve a mostrar el botón flotante |
| `getUnreadCount()` | Devuelve la cantidad de mensajes sin leer |
| `on(evento, callback)` | Suscribe un callback a un evento. Devuelve una función para cancelar la suscripción |

#### Abrir el chat desde tu propio botón

```html
<button onclick="PlzWidget.open()">Hablar con soporte</button>
```

Si prefieres usar solo tu botón, oculta el botón flotante del widget:

```js
PlzWidget.hideLauncher();
```

#### Enviar un mensaje

Útil para iniciar una conversación con contexto, por ejemplo desde la página de un producto:

```js
PlzWidget.sendMessage('Quiero información sobre el Plan Pro');
```

> **Importante:** Si el agente tiene activo el formulario de registro (`formWidget`) y el usuario aun no lo completo, `sendMessage` abre el widget en el formulario y no envía el mensaje. Usa `identify` antes para omitir el formulario.

#### Identificar al usuario

Si el usuario ya inicio sesión en tu sitio, envía sus datos para que el contacto en el CRM quede con nombre, email y teléfono:

```js
PlzWidget.identify({
name: 'Maria',
lastname: 'Lopez',
email: 'maria@empresa.com',
phone: '+51 999 888 777',
isoCountryCode: 'PE'
});
```

| Campo | Tipo | Descripción |
|-------|------|-------------|
| `name` | `string` | Nombre del usuario |
| `lastname` | `string` | Apellido |
| `email` | `string` | Email. Si no tiene un formato válido se ignora |
| `phone` | `string` | Teléfono con código de país. Se guardan solo los digitos |
| `isoCountryCode` | `string` | Código ISO del país (`PE`, `MX`, `CO`, ...) |

- Solo se **completan datos vacios**: si el contacto ya tiene nombre, email o teléfono, no se sobrescriben.
- Si envías `name` o `email`, el widget omite el formulario de registro (`formWidget`).
- Tener el email del contacto permite enviarle el **resumen de la conversación por correo** al solucionar el chat (ver [Widget IA](https://developers.plazbot.com/sdk/widget)).

> **Nota:** `identify` no autentica al usuario: solo completa los datos del contacto asociado a la sesión del navegador. No envies información sensible.

### Eventos

Suscribete con `PlzWidget.on(evento, callback)`. El método devuelve una función para cancelar la suscripción.

| Evento | Datos del callback | Cuando se dispara |
|--------|--------------------|-------------------|
| `ready` | — | La configuración del agente término de cargar |
| `open` | — | El widget se abre |
| `close` | — | El widget se cierra |
| `message` | `{ id, text, type, fromHuman, senderName }` | Llega un mensaje del agente IA o de un asesor |
| `unreadCountChange` | `{ count }` | Cambia la cantidad de mensajes sin leer |

En el evento `message`, `fromHuman` es `true` cuando el mensaje lo escribio un asesor de tu equipo desde el CRM, y `senderName` trae su nombre.

#### Ejemplo: contador de no leidos en tu propio botón

```js
window.PlzWidgetOnLoad = function (PlzWidget) {
PlzWidget.hideLauncher();

var badge = document.getElementById('chat-badge');
PlzWidget.on('unreadCountChange', function (data) {
  badge.textContent = data.count > 0 ? data.count : '';
});

document.getElementById('chat-button').addEventListener('click', function () {
  PlzWidget.toggle();
});
};
```

#### Ejemplo: enviar eventos a tu analitica

```js
window.PlzWidgetOnLoad = function (PlzWidget) {
PlzWidget.on('open', function () {
  gtag('event', 'chat_open');
});

var unsubscribe = PlzWidget.on('message', function (msg) {
  if (msg.fromHuman) gtag('event', 'chat_human_reply');
});

// Mas adelante, para dejar de escuchar:
// unsubscribe();
};
```

### Tipos TypeScript

Si tu sitio usa TypeScript, puedes declarar la API así:

```ts
interface PlzWidgetIdentifyData {
name?: string;
lastname?: string;
email?: string;
phone?: string;
isoCountryCode?: string;
}

interface PlzWidgetMessage {
id: string;
text: string;
type: string;
fromHuman: boolean;
senderName: string | null;
}

interface PlzWidgetApi {
open(): void;
close(): void;
toggle(): void;
isOpen(): boolean;
sendMessage(text: string): void;
identify(data: PlzWidgetIdentifyData): void;
hideLauncher(): void;
showLauncher(): void;
getUnreadCount(): number;
on(event: 'ready' | 'open' | 'close', cb: () => void): () => void;
on(event: 'message', cb: (msg: PlzWidgetMessage) => void): () => void;
on(event: 'unreadCountChange', cb: (data: { count: number }) => void): () => void;
}

declare global {
interface Window {
  PlzWidget?: PlzWidgetApi;
  PlzWidgetOnLoad?: (api: PlzWidgetApi) => void;
}
}
```
