Ir al contenido

Pregunta a la doc

Las respuestas vienen solo de esta documentación, con fuentes. Para temas específicos de tu cuenta, la doc te dirige al responsable correcto.

¿Qué estás buscando?

Estás hablando con un asistente de IA. Puede equivocarse, así que verifica la información importante.

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.

Desde npm:

Ventana de terminal
npm install @askdialog/dialog-sdk
# o
pnpm add @askdialog/dialog-sdk
# o
yarn add @askdialog/dialog-sdk

Desde 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.

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
},
},
});
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.

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.addToCart nunca 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).

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 update de Google Consent Mode a denied, u OneTrust cargado sin el grupo de rendimiento (C0002), desactiva la analítica para ese visitante;
  • window.dialog.audit.consent indica detectedCmp: '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.

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 opcional
client.clearCurrentProduct(); // salida hacia una página sin producto

El 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.

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.

client.sendProductMessage({
question: "¿Esta camiseta talla pequeña?",
productId: "product-123",
productTitle: "Camiseta de lino cuello V",
selectedVariantId: "variant-456", // opcional
});
client.sendGenericMessage({
question: "¿Cuál es vuestra política de devoluciones?",
});

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'
// }
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.

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(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(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 desmontar
controller.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.

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é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.

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.

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.

const unsubscribe = client.onAssistantEvent((event) => {
// event.type, event.payload
});
// Más tarde
unsubscribe();

Tipos de eventos disponibles (guía completa en Tracking SDK personalizado):

  • userOpenedAssistant
  • userClosedAssistant
  • userSentMessage
  • userClickedOnProductCard
  • userOpenedRecommendation
  • userAddedToCart
  • userSendPositiveFeedback
  • userSendNegativeFeedback

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.

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[];
}