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.

App integrada

La app integrada es el asistente Dialog empaquetado para asesores de venta: una página que tu propia app de asesores carga en un iframe. El asesor conversa con el asistente, escanea o explora el catálogo, mantiene listas de favoritos y arma un pre-carrito que Dialog convierte en un pedido borrador de Shopify enviado al cliente por correo.

Esta página es para el equipo que desarrolla la app de asesores. No es una integración de tienda online: para tu sitio, mira el SDK y los componentes.

Tu app de asesores (página) Dialog
iframe ─────────────────────────────────▶ app asistente
◀── dialog:ready
──▶ dialog:auth { token } (firmado por tu backend)
──▶ dialog:shopper { email }
◀── dialog:pre-cart-sent (pedido borrador creado; invoiceSent indica si se envió por correo)

Tu backend guarda una clave privada. Para cada asesor con sesión iniciada, firma un token de corta duración que lo identifica; tu página se lo entrega al iframe. Dialog lo verifica con la mitad pública que registraste y asocia favoritos y pre-carrito a ese asesor.

En el panel de Dialog, ve a En tu tienda → App integrada.

  1. Dirección a integrar: la URL del iframe, con tu clave API pública ya incluida. Cópiala.
  2. Orígenes permitidos: añade el origen de la página que integra la app, por ejemplo https://asesores.example.com. Solo orígenes https://, más http://localhost para desarrollo. Hasta 20. La app ignora los mensajes de cualquier otro origen.
  3. Claves de firma: haz clic en Generar una clave. El par se crea en tu navegador; Dialog guarda la mitad pública y muestra la clave privada una sola vez. Guárdala con los secretos de tu backend, junto con el id de clave (kid). También puedes Importar una clave pública propia: una clave ES256 (P-256), en PEM o JWK.

Las claves rotan sin interrupción: añade una clave, despliégala y revoca la anterior. Una clave revocada se rechaza de inmediato.

<iframe
id="dialog-assistant"
src="https://assistant-app.askdialog.com/?apiKey=TU_CLAVE_API_PUBLICA&locale=es-ES"
allow="camera"
></iframe>
Parámetro Requerido Descripción
apiKey sí Tu clave API pública. Incluida en la dirección que te da el panel.
locale no Una locale BCP 47 (es-ES, en-GB). Fija el idioma y el mercado del que vienen los precios. Por defecto, la del navegador.
countryCode no País en dos letras, cuando el mercado difiere de la región de la locale.

allow="camera" permite al asesor escanear códigos QR de producto. La app está pensada para un teléfono: dale al iframe un tamaño vertical, o escálala para que quepa.

¿Desarrollas una app Android nativa? Carga la app en una WebView: consulta App integrada en Android.

Sin token, la app responde preguntas y explora el catálogo. Favoritos y pre-carrito aparecen una vez autenticado el asesor.

Todos los mensajes pasan por postMessage. Publica hacia el origen exacto del iframe, y acepta solo mensajes cuyo origin sea ese mismo origen y cuya source sea la ventana del iframe.

Mensaje Contenido Cuándo
dialog:ready ninguno La app está cargada y escuchando. Responde con dialog:auth, y luego dialog:shopper si lo conoces.
dialog:token-expiring ninguno Unos 60 segundos antes de que expire el token, o tras un rechazo de Dialog. Responde con un dialog:auth nuevo.
dialog:pre-cart-sent { draftOrderName, invoiceUrl, invoiceSent } El pre-carrito se envió: el nombre del pedido borrador (#D1) y el enlace de pago. invoiceSent es false cuando Shopify no pudo enviarlo por correo; el pedido borrador existe de todos modos, y el enlace es la forma en que el cliente llega a él.
Mensaje Contenido Función
dialog:auth { token } El token de asesor. Envíalo en dialog:ready y en cada dialog:token-expiring.
dialog:shopper { email?, customerId? } El cliente que atiende el asesor. El correo rellena el formulario del pre-carrito; customerId (un GID de cliente Shopify) asocia el pedido borrador a esa cuenta. Envíalo de nuevo cuando el asesor cambie de cliente.
const frame = document.getElementById('dialog-assistant')
const appOrigin = new URL(frame.src).origin
window.addEventListener('message', async event => {
if (event.origin !== appOrigin || event.source !== frame.contentWindow) return
if (event.data.type === 'dialog:ready' || event.data.type === 'dialog:token-expiring') {
const { token } = await fetch('/api/dialog-token').then(r => r.json())
frame.contentWindow.postMessage({ type: 'dialog:auth', token }, appOrigin)
}
if (event.data.type === 'dialog:pre-cart-sent') {
console.log(event.data.draftOrderName, event.data.invoiceUrl, event.data.invoiceSent)
}
})

Un JWT firmado con ES256 por tu backend, nunca en el navegador. Tu ruta /api/dialog-token firma uno para el asesor con sesión iniciada, y solo para él.

Claim Valor
kid (cabecera) El id de clave que muestra el panel.
iss El slug de tu organización, como aparece en la URL del panel.
aud dialog-assistant-app
sub El id del asesor en tu sistema. Opaco para Dialog; indexa sus favoritos y su pre-carrito.
store Opcional: el id de la tienda física.
iat, exp Como máximo 15 minutos de diferencia. Dialog tolera 30 segundos de desfase de reloj.

Con jose en Node:

import { importPKCS8, SignJWT } from 'jose'
const privateKey = await importPKCS8(process.env.DIALOG_PRIVATE_KEY, 'ES256')
const token = await new SignJWT({ store: 'madrid-01' })
.setProtectedHeader({ alg: 'ES256', kid: process.env.DIALOG_KEY_ID })
.setIssuer('slug-de-tu-organizacion')
.setAudience('dialog-assistant-app')
.setSubject(advisor.id)
.setIssuedAt()
.setExpirationTime('15m')
.sign(privateKey)

Un token se rechaza cuando su clave es desconocida o está revocada, su firma o su audiencia es incorrecta, o vive más de 15 minutos. La app pide entonces uno nuevo a tu página con dialog:token-expiring.