Referencia del SDK
@askdialog/dialog-sdk es el SDK core para embedder Dialog en stacks custom. Maneja la comunicación con la API Dialog, el ciclo de vida del asistente, el tracking, y expone todo lo que necesitas para construir una UI alrededor.
Install
Sección titulada «Install»Desde npm:
npm install @askdialog/dialog-sdk# opnpm add @askdialog/dialog-sdk# oyarn add @askdialog/dialog-sdkDesde CDN (sin bundler):
<script src="https://d2m6yt8rnm4dos.cloudfront.net/dialog-sdk.X.Y.Z.min.js"></script>Cargado vía CDN, el SDK se expone como window.DialogSDK.
Instanciar
Sección titulada «Instanciar»import { Dialog, type SimplifiedProduct } from "@askdialog/dialog-sdk";
const client = new Dialog({ apiKey: "YOUR_PUBLIC_API_KEY", locale: "es", currency: "EUR", callbacks: { addToCart: async ({ productId, quantity, variantId, currency }) => { // Añade el producto al carrito y refresca tu UI }, changeCartQuantity: async ({ productId, variantId, quantity }) => { // Opcional: pon esa línea del carrito en `quantity` y actualiza tu UI }, getProduct: async (productId, variantId): Promise<SimplifiedProduct> => { // Obtén el producto de tu backend y devuélvelo con el formato SimplifiedProduct }, },});Opciones del constructor
Sección titulada «Opciones del constructor»| Opción | Tipo | Requerida | Descripción |
|---|---|---|---|
apiKey |
string |
Sí | Tu API key pública de Dialog. |
locale |
string |
Sí | Locale activa (ej. 'en', 'fr', 'es'). |
callbacks.addToCart |
(params) => Promise<void> |
Sí | Llamada cuando el usuario clica add-to-cart dentro del asistente. Tú manejas la mutación del carrito y el refresh de UI. |
callbacks.getProduct |
(productId, variantId?) => Promise<SimplifiedProduct> |
Sí | Llamada para renderizar las cards de producto dentro del asistente. Devuelve tu producto con el formato SimplifiedProduct. |
callbacks.changeCartQuantity |
(params) => Promise<void> |
No | Se llama cuando el visitante ajusta la cantidad de una línea que el asistente acaba de añadir. quantity es la nueva cantidad absoluta de la línea. Si se omite, el asistente oculta su selector de cantidad. |
currency |
string |
Sí | Divisa de la tienda, ISO 4217 (ej. 'USD', 'EUR'), independiente del locale. Se lee con client.currency; Search la usa para elegir el índice. |
callbacks.addToCart |
(params) => Promise<void> |
No | Llamada cuando el usuario clica add-to-cart dentro del asistente. Tú manejas la mutación del carrito y el refresh de UI. |
callbacks.getProduct |
(productId, variantId?) => Promise<SimplifiedProduct> |
No | Llamada para renderizar las cards de producto dentro del asistente. Devuelve tu producto con el formato SimplifiedProduct. |
theme |
Theme |
No | Override del theme visual (colores, fuentes, forma de los CTA). |
userId |
string |
No | ID estable del visitante. Si se omite, Dialog auto-genera uno y lo persiste. |
product |
{ id: string; variantId?: string } |
No | El producto de la página actual. Ancla las preguntas sin producto propio (bookmark flotante, reanudación, campo libre) en el producto consultado. Ver Declarar el producto actual. |
disableAddToCart |
boolean |
No | Oculta el add-to-cart de Dialog para esta instancia/sesión del widget (por defecto false). Ver «Desactivar el add-to-cart» más abajo. |
analyticsConsent |
'granted' |
No | Declara el consentimiento de analítica como concedido, para los sitios sin banner de cookies. Omitido por defecto. Ver Declarar el consentimiento de analítica. |
callbacks se puede omitir en una integración solo de Search (ver Search): solo el asistente los necesita, y los métodos getProduct() y addToCart() del cliente lanzan un error de configuración cuando falta su callback.
Desactivar el add-to-cart
Sección titulada «Desactivar el add-to-cart»Pon disableAddToCart: true para desactivar el add-to-cart de Dialog en una sesión concreta, por ejemplo una tienda B2B que oculta las acciones de compra cuando un cliente B2B está conectado. Evalúa tu propia condición en la inicialización:
const client = new Dialog({ apiKey: "YOUR_PUBLIC_API_KEY", locale: "es", currency: "EUR", disableAddToCart: isB2BCustomerLoggedIn, // por sesión callbacks: { /* ... */ },});Cuando está activado:
- el asistente oculta el CTA add-to-cart en las cards de recomendación y las cards de producto conversacionales;
callbacks.addToCartnunca se llama y no se trackea ningún evento add-to-cart;- los enlaces de producto y la navegación de recomendaciones siguen disponibles.
Omítelo (o pon false) para mantener el comportamiento actual. El flag se lee en la inicialización, así que se aplica durante toda la vida de la instancia del widget (un cambio de estado de sesión surte efecto en la siguiente carga de página).
Declarar el consentimiento de analítica
Sección titulada «Declarar el consentimiento de analítica»Por defecto, el asistente solo envía los eventos de analítica (add-to-cart, checkout, uso del asistente) después de detectar una señal de consentimiento en la página: Google Consent Mode, TCF v2 u OneTrust. Un sitio sin banner de cookies no emite ninguna señal: no se envía ningún evento para sus visitantes y el dashboard queda vacío.
En esos sitios, pon analyticsConsent: 'granted':
const client = new Dialog({ apiKey: "YOUR_PUBLIC_API_KEY", locale: "es", currency: "EUR", analyticsConsent: "granted", // sin banner de cookies en este sitio callbacks: { /* ... */ },});La opción funciona como un estado default de Google Consent Mode:
- la analítica está activa desde la primera página vista, para todos los visitantes;
- un rechazo emitido por una plataforma de consentimiento presente en la página sigue teniendo prioridad: un
updatede Google Consent Mode adenied, u OneTrust cargado sin el grupo de rendimiento (C0002), desactiva la analítica para ese visitante; window.dialog.audit.consentindicadetectedCmp: 'declared'cuando es la opción la que activó la analítica.
Considerar el consentimiento como concedido es tu decisión de cumplimiento. Omite la opción para mantener la detección por defecto.
Declarar el producto actual
Sección titulada «Declarar el producto actual»Pasa product en las páginas de producto para que el asistente sepa siempre qué producto está viendo el visitante. Las preguntas hechas sin producto explícito (desde el bookmark flotante, la reanudación de conversación o el campo libre) se responden entonces en el contexto de ese producto, incluso después de navegar de una página de producto a otra:
const client = new Dialog({ apiKey: "YOUR_PUBLIC_API_KEY", locale: "es", currency: "EUR", product: { id: "product-123", variantId: "variant-456" }, // variantId opcional callbacks: { /* ... */ },});En tiendas single-page, actualiza la declaración en cada navegación del lado del cliente:
client.setCurrentProduct("product-456", "variant-789"); // variantId opcionalclient.clearCurrentProduct(); // salida hacia una página sin productoEl id debe coincidir con el ID de producto de tu feed de catálogo Dialog. Sin producto declarado, las preguntas hechas fuera de un clic de producto se responden sin contexto de producto.
Cargar Dialog en todas las páginas
Sección titulada «Cargar Dialog en todas las páginas»Como tu código es el que inicializa Dialog, tiene que ejecutarse en todas las rutas de tu tienda, no solo en páginas de producto, listado e inicio. Dos cosas dependen de que Dialog esté presente en la página:
- Las surfaces proactivas (el modal y la AI bar de Smart Discovery) solo aparecen donde Dialog está cargado, así que una configuración dirigida a páginas de contenido nunca se dispara si el SDK no está inicializado ahí, aunque su patrón de URL coincida.
- El tracking (sesiones, add-to-cart, checkout) solo se captura en las páginas donde Dialog corre: las rutas sin Dialog pierden analytics de forma silenciosa.
Un error común es conectar la inicialización solo en los flujos de producto, listado e inicio. Inicializa Dialog de forma global (por ejemplo en un layout compartido o una plantilla raíz), para que corra en todos los tipos de página.
Enviar mensajes
Sección titulada «Enviar mensajes»Con contexto de producto
Sección titulada «Con contexto de producto»client.sendProductMessage({ question: "¿Esta camiseta talla pequeña?", productId: "product-123", productTitle: "Camiseta de lino cuello V", selectedVariantId: "variant-456", // opcional});Sin contexto de producto
Sección titulada «Sin contexto de producto»client.sendGenericMessage({ question: "¿Cuál es vuestra política de devoluciones?",});Obtener sugerencias
Sección titulada «Obtener sugerencias»Obtén la lista de sugerencias generadas por IA para un producto dado. Útil si construyes una UI custom de sugerencias en tu PDP en lugar de usar nuestro componente DialogProductBlock.
const suggestions = await client.getSuggestions("product-123");// {// questions: [{ question: '...' }, ...],// assistantName: 'Tu experto',// inputPlaceholder: 'Haz una pregunta...',// description: 'Haz cualquier pregunta sobre este producto'// }Información de locale
Sección titulada «Información de locale»const info = client.getLocalizationInformations();// { countryCode: 'ES', formatted: 'es-ES', language: 'Spanish', locale: 'es' }El SDK ejecuta Search de Dialog, la búsqueda por palabras clave en tu catálogo. Los componentes de React y Vue y el endpoint REST se cubren en la guía de integración de Search.
Nombres de índice
Sección titulada «Nombres de índice»Search lee un índice por idioma y divisa. Construye los nombres con searchIndexName(index, language, currency):
import { searchIndexName } from "@askdialog/dialog-sdk";
searchIndexName("products", "es", "EUR"); // 'products_es_eur'index:'products','collections','articles'o'pages'.language: código ISO 639-1 en minúsculas ('es'). Un locale regional como'es-ES'lanza un error.currency: código ISO 4217 ('EUR'), en minúsculas en el nombre.
client.search()
Sección titulada «client.search()»client.search(request, options?) envía una petición a la API de búsqueda, tal cual: sin debounce, sin cancelar las peticiones obsoletas, sin analítica. Úsala para una búsqueda puntual; para un campo de búsqueda, usa createSearchController.
const response = await client.search({ requests: [ { indexName: searchIndexName("products", "es", client.currency), query: "zapatillas de running", page: 0, // opcional, empieza en 0 (por defecto 0) hitsPerPage: 20, // opcional, de 1 a 100 (por defecto 20) }, ],});// response.results[0].hits: [{ objectID, title?, url?, handle?, imageUrl?, priceRange? }]options.signal (un AbortSignal) cancela la petición, que se rechaza entonces con el AbortError nativo. Un error HTTP rechaza con DialogSearchError (status y message). Los campos de la petición y de la respuesta se detallan en la referencia del endpoint REST.
createSearchController
Sección titulada «createSearchController»createSearchController(options) ejecuta una búsqueda interactiva: aplica un debounce al tecleo, cancela las peticiones obsoletas e ignora sus respuestas tardías, pagina, reintenta y registra la analítica de búsqueda (impresiones y clics en los resultados). No pinta nada: te suscribes a su estado y pintas los resultados.
import { createSearchController, Dialog, SearchStatus,} from "@askdialog/dialog-sdk";
const client = new Dialog({ apiKey: "YOUR_PUBLIC_API_KEY", locale: "es-ES", currency: "EUR",});
const controller = createSearchController({ search: (request, options) => client.search(request, options), language: "es", currency: client.currency, analytics: { surface: "search_page", trackViewSearchResults: (params) => client.trackViewSearchResults(params), trackSelectSearchResult: (params) => client.trackSelectSearchResult(params), }, navigate: (url) => router.push(url), // opcional sections: [{ index: "collections", hitsPerPage: 5 }], // opcional});
const unsubscribe = controller.subscribe((state) => { if (state.status === SearchStatus.SUCCESS) { renderCards(state.response.hits).forEach((card, index) => { controller.observeResult(card, index); card.onclick = (event) => { if (controller.selectResult(index)) event.preventDefault(); }; }); }});
input.oninput = () => controller.setQuery(input.value);form.onsubmit = (event) => { event.preventDefault(); controller.submit(input.value);};nextButton.onclick = () => controller.setPage(controller.getState().page + 1);
// Al desmontarcontroller.dispose();language es la parte ISO 639-1 del locale del cliente ('es' para 'es-ES'): pásala de forma explícita, un locale regional se rechaza.
Opciones
Sección titulada «Opciones»Las opciones se fijan al crear el controller: crea un controller nuevo para cambiar de idioma o de divisa.
| Opción | Tipo | Requerido | Por defecto | Descripción |
|---|---|---|---|---|
search |
(request, options?) => Promise<SearchResponse> |
Sí | - | Envía una petición. Pasa client.search, ligado al cliente, o tu propio transporte. |
language |
string |
Sí | - | Código ISO 639-1 en minúsculas, por ejemplo 'es'. |
currency |
string |
Sí | - | Código ISO 4217, por ejemplo client.currency. |
analytics |
SearchControllerAnalytics |
Sí | - | { surface, trackViewSearchResults, trackSelectSearchResult }. surface indica dónde se muestran los resultados: 'search_page', 'autocomplete', 'smart_discovery' o 'ai_bar'. Pasa los métodos trackViewSearchResults y trackSelectSearchResult del cliente. |
navigate |
(url, hit) => void |
No | - | Adaptador de router, llamado después de registrar una selección. Omítelo para que tus enlaces de resultados naveguen de forma nativa. |
debounceMs |
number |
No | 250 |
Debounce de tecleo, en milisegundos. |
hitsPerPage |
number |
No | 12 |
Productos por página. |
sections |
SearchSection[] o () => SearchSection[] |
No | [] |
Índices extra buscados junto a los productos, por ejemplo [{ index: 'collections', hitsPerPage: 5 }]. Pide solo un índice que tenga tu catálogo: uno ausente hace fallar toda la búsqueda. |
Métodos
Sección titulada «Métodos»| Método | Descripción |
|---|---|
setQuery(query) |
Busca tras el retardo de debounce. Una consulta de menos de 2 caracteres (tras el trim) devuelve el estado a idle. |
submit(query) |
Busca de inmediato. |
setPage(page) |
Carga una página (empezando en 0) de la consulta actual. Una consulta nueva siempre empieza en la página 0. |
retry() |
Repite la última petición, cuando el estado es error. |
observeResult(element, index) |
Registra la impresión de state.response.hits[index] en cuanto element es visible. |
selectResult(index, options?) |
Registra el clic en state.response.hits[index] y luego llama a navigate. Devuelve true cuando se llamó a navigate: llama entonces a preventDefault() en el clic. Pasa { navigate: false } para los clics con la rueda y los clics con modificador. |
subscribe(listener) |
Llama a listener(state) en cada cambio de estado. Devuelve la función para cancelar la suscripción. |
getState() |
Devuelve el estado actual. |
dispose() |
Cancela las peticiones pendientes y quita listeners y observers. |
| Campo | Tipo | Descripción |
|---|---|---|
status |
'idle' | 'loading' | 'success' | 'empty' | 'error' |
empty es una búsqueda correcta sin resultados. Compara con las constantes SearchStatus. |
query |
string |
Última consulta buscada. |
page |
number |
Página (empezando en 0) de la última petición. |
response |
SearchResult |
Opcional. Resultado de productos: hits, nbHits, page, nbPages, hitsPerPage, query, queryID. Se conserva mientras carga y se vacía en caso de error. |
sections |
object |
Opcional. Resultados de los índices extra, por índice (state.sections?.collections). |
error |
unknown |
Opcional. El error de la última petición, cuando status es error. |
Tracking
Sección titulada «Tracking»El SDK auto-trackea las interacciones con el asistente (open / close / message / add-to-cart desde el asistente). Usa los métodos abajo para los eventos que pasan fuera del asistente.
Add-to-cart y checkout manuales
Sección titulada «Add-to-cart y checkout manuales»client.registerAddToCartEvent({ productId: "product-123", quantity: 1, currency: "EUR", variantId: "variant-456", price: 29.99,});
client.registerSubmitCheckoutEvent({ productId: "product-123", quantity: 1, currency: "EUR", variantId: "variant-456",});Llama estos métodos cada vez que el cliente añade al carrito o completa el checkout sin pasar por el asistente Dialog, para que el dashboard pueda atribuir la conversión correctamente. Ver Tracking: SDK custom para detalles.
Escuchar eventos del asistente
Sección titulada «Escuchar eventos del asistente»const unsubscribe = client.onAssistantEvent((event) => { // event.type, event.payload});
// Más tardeunsubscribe();Tipos de eventos disponibles (guía completa en Tracking SDK personalizado):
userOpenedAssistantuserClosedAssistantuserSentMessageuserClickedOnProductCarduserOpenedRecommendationuserAddedToCartuserSendPositiveFeedbackuserSendNegativeFeedback
Pasa un objeto theme en la construcción:
const client = new Dialog({ apiKey: "YOUR_PUBLIC_API_KEY", locale: "es", currency: "EUR", theme: { backgroundColor: "#ffffff", primaryColor: "#000000", ctaTextColor: "#ffffff", ctaBorderType: "rounded", // 'straight' | 'rounded' capitalizeCtas: false, fontFamily: "Inter, sans-serif", highlightProductName: true, }, callbacks: { /* ... */ },});Las claves title, description y content del theme solo aplican a los componentes Vue / React. El SDK vanilla no renderiza esas zonas, eres tú quien lo hace.
Formato SimplifiedProduct
Sección titulada «Formato SimplifiedProduct»Tu callback getProduct debe devolver este formato:
interface SimplifiedProduct { id: string; title: string; handle: string; descriptionHtml?: string; url?: string; totalInventory: number; featuredImage?: { url?: string } | null; variants: SimplifiedProductVariant[]; options?: SimplifiedProductOption[];}
interface SimplifiedProductVariant { id: string; displayName?: string; inventoryQuantity?: number; price: string; // string, ej. '29.99' currencyCode: string; // código ISO, ej. 'EUR' compareAtPrice?: string | null; url?: string; selectedOptions?: { name: string; value: string }[]; image?: { url?: string } | null;}
interface SimplifiedProductOption { id: string; name: string; position: number; values: string[];}Siguientes pasos
Sección titulada «Siguientes pasos»- Componentes React: UI drop-in con el SDK.
- Componentes Vue: lo mismo, para Vue 3.
- Instalar Search en una storefront headless: Search con el SDK, los componentes o el endpoint REST.
- Tracking SDK custom: guía completa de tracking desde el SDK.
- Problemas al añadir al carrito: patterns comunes de sync de UI.
