Documentación
Guías técnicas para su integración: multicanal, widgets, API y Shopware.
Multicanal / Ubicaciones
Con la función de ubicaciones puede recopilar y analizar reseñas por separado según sucursal, canal de venta o región. Cada ubicación tiene su propio nombre, un slug, un dominio opcional y un idioma predeterminado.
Límites por plan: FREE = 1 ubicación, STARTER = 2, PRO = 10, ENTERPRISE = 100
¿Cuándo usar ubicaciones?
Las ubicaciones son ideales si usted:
- tiene varias sucursales o delegaciones
- tiene distintas tiendas online o dominios
- quiere separar las reseñas por región o departamento
- quiere integrar un widget propio por ubicación en el sitio web correspondiente
Gestionar ubicaciones
En Ajustes → Ubicaciones puede crear, editar y eliminar ubicaciones.
- Nombre: nombre visible (p. ej. «Sucursal Madrid Centro»)
- Slug: identificador único, se genera automáticamente a partir del nombre
- Dominio: opcional, la URL del sitio web de la ubicación
- Idioma: idioma predeterminado de esta ubicación
- Ubicación predeterminada: la ubicación marcada como predeterminada se usa para nuevas reseñas sin asignación explícita
Al eliminar una ubicación se conservan todas las reseñas asignadas; solo pierden la asignación a la ubicación.
¿Cómo se asignan las reseñas a una ubicación?
Hay tres formas:
- Automáticamente mediante el formulario de reseñas: si su empresa tiene varias ubicaciones, en la página de perfil aparece un desplegable «¿Qué ubicación desea valorar?» y el cliente la elige.
- Mediante invitaciones: al enviar una invitación puede indicar la ubicación. La reseña se asigna automáticamente.
- Mediante la API: envíe el
locationIdal crear una reseña.
Widgets por ubicación
En el editor de widgets, en Ajustes → Filtro de ubicación, puede limitar un widget a una ubicación concreta. El widget mostrará únicamente las reseñas de esa ubicación.
Así, por ejemplo, la web de su sucursal de Madrid puede mostrar solo las reseñas de Madrid y la de Barcelona solo las de Barcelona.
Referencia de la API
Crear una ubicación:
{
"name": "Tienda online ES",
"slug": "shop-es",
"domain": "https://www.mi-tienda.es",
"language": "es"
}Crear una reseña asignada a una ubicación:
{
"companyId": "...",
"locationId": "clx...",
"rating": 5,
"content": "¡Excelente servicio!",
"reviewerName": "Juan García"
}Filtrar reseñas por ubicación:
// Devuelve solo las reseñas de la ubicación indicada
// Sin locationId se devuelven todas las reseñasCrear un widget con filtro de ubicación:
{
"companyId": "...",
"locationId": "clx...",
"name": "Widget sucursal Madrid",
"type": "CAROUSEL",
"config": { "maxReviews": 5 }
}Widgets multilingües
El widget integrado admite 5 idiomas: Deutsch, English, Français, Español e Italiano. Todos los textos de la interfaz (botones, indicaciones de tiempo, campos de formulario) se muestran automáticamente en el idioma detectado.
Detección del idioma (prioridad)
- Atributo
data-langen el contenedor del widget (explícito) - Campo
localeen la configuración del widget (panel) document.documentElement.lang(idioma HTML de la página)- Valor por defecto:
de
Opción 1: explícitamente mediante un atributo HTML
Ideal para tiendas multilingües en las que se conoce el idioma de cada página:
<!-- Widget en alemán -->
<div data-zoom-widget="WIDGET_ID" data-lang="de"></div>
<!-- Widget en inglés -->
<div data-zoom-widget="WIDGET_ID" data-lang="en"></div>
<!-- Widget en francés -->
<div data-zoom-widget="WIDGET_ID" data-lang="fr"></div>
<script src="https://zoom.reviews/widget.js" async></script>Opción 2: automáticamente según el idioma de la tienda
Si la plantilla de su tienda define correctamente el atributo lang en la etiqueta <html>, el widget detecta el idioma automáticamente:
<html lang="fr">
...
<div data-zoom-widget="WIDGET_ID"></div>
<script src="https://zoom.reviews/widget.js" async></script>
</html>Opción 3: mediante la configuración del panel
En Widgets → Editar → Ajustes puede fijar un idioma por widget. Es útil si crea un widget propio para cada tienda o canal de idioma.
Ejemplo Shopware / Twig
{# En la plantilla de su tema #}
<div data-zoom-widget="WIDGET_ID"
data-lang="{{ app.request.locale[:2] }}"></div>
<script src="https://zoom.reviews/widget.js" async></script>Comprobación de integridad (SRI)
Si sus políticas de seguridad lo exigen, puede integrar una versión fija con Subresource Integrity en lugar del widget.js que se actualiza solo. Antes de ejecutarlo, el navegador comprueba mediante un hash que el script coincide exactamente con la versión publicada y, si no, lo bloquea.
<div data-zoom-widget="WIDGET_ID"></div>
<script src="https://zoom.reviews/widget/v1.js"
integrity="sha384-b+jQQNJZZso+gHv6OrEFQWf3CnUlnPR95LwStglzZ9EDIhLlhwIEMunoVr+X1GKT"
crossorigin="anonymous" async></script>Las versiones fijas no reciben actualizaciones automáticas ni correcciones de errores. Cuando publicamos una nueva versión, debe sustituir el snippet usted mismo. Le informamos por correo electrónico de cada cambio para que pueda sustituir el snippet a tiempo. El snippet actual se encuentra siempre en Widgets → Código de inserción.
Invitaciones a reseñas (posventa)
Envíe automáticamente invitaciones a reseñas a sus clientes después de la compra. Los correos son multilingües (DE/EN/FR/ES/IT) e incluyen un enlace personalizado.
Disponible desde: plan Pro (100 invitaciones/día) · Enterprise (1.000 invitaciones/día)
Crear una invitación
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
{
"email": "cliente@example.com",
"customerName": "Juan García",
"orderId": "ORD-10042",
"orderDate": "2026-07-28T14:30:00Z",
"locale": "es",
"locationId": "clx...",
"delayDays": 7
}| Parámetro | Obligatorio | Descripción |
|---|---|---|
| Sí | Correo electrónico del cliente | |
| customerName | Sí | Nombre del cliente |
| orderId | No | Número de pedido (para la asociación) |
| locale | No | Idioma del correo (de/en/fr/es/it) |
| locationId | No | ID de la ubicación para la asignación |
| delayDays | No | Retraso en días (0 = inmediato, por defecto: 7) |
Invitaciones en lote (hasta 100 a la vez)
{
"invitations": [
{ "email": "a@example.com", "customerName": "Anna", "locale": "de" },
{ "email": "b@example.com", "customerName": "Bob", "locale": "en" },
{ "email": "c@example.com", "customerName": "Claire", "locale": "fr" }
]
}Proceso para el cliente
- El cliente recibe un correo personalizado con un enlace para valorar
- El enlace abre su página de reseñas con el nombre ya rellenado
- La reseña se marca automáticamente como verificada (sin captcha)
- El token solo se puede usar una vez
Listar invitaciones
// Status: PENDING, SENT, OPENED, COMPLETED, EXPIREDWebhooks salientes
Reciba notificaciones en tiempo real sobre nuevas reseñas e invitaciones. Los webhooks se firman con HMAC-SHA256.
Solo plan Enterprise. Hasta 10 endpoints de webhook por empresa.
Eventos disponibles
| Evento | Descripción |
|---|---|
| review.created | Nueva reseña enviada |
| review.approved | Reseña aprobada |
| review.rejected | Reseña rechazada |
| invitation.sent | Invitación enviada |
| invitation.completed | Invitación completada (reseña enviada) |
Crear un webhook
{
"url": "https://your-server.com/webhooks/zoom-reviews",
"events": ["review.created", "review.approved"]
}La respuesta contiene un secret (¡solo se muestra una vez!) que sirve para verificar la firma.
Formato del payload
// Headers:
// X-Webhook-Signature: <HMAC-SHA256 of body>
// X-Webhook-Event: review.created
// X-Webhook-Timestamp: 2026-07-29T18:30:00.000Z
{
"event": "review.created",
"data": {
"id": "clx...",
"rating": 5,
"reviewerName": "Juan García",
"source": "WIDGET",
"locationId": "clx..."
},
"timestamp": "2026-07-29T18:30:00.000Z"
}Verificar la firma
const crypto = require('crypto');
function verifyWebhook(body, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}Gestión
En Ajustes → Webhooks (próximamente) o mediante la API:
GET /api/webhooks/outgoing— Listar todos los endpointsPATCH /api/webhooks/outgoing— Cambiar URL, eventos o estadoDELETE /api/webhooks/outgoing?id=...— Eliminar un endpoint
Integración con Shopware 6
Invitaciones automáticas a reseñas tras completar un pedido en su tienda Shopware 6. La integración detecta automáticamente el idioma del pedido y el canal de venta.
Resumen
Paso 1
Configurar la URL del webhook en Shopware
Paso 2
Elegir un evento del Flow Builder
Paso 3
Ajustar retraso e idioma
Método A: Shopware Flow Builder (recomendado)
- En la administración de Shopware, vaya a Ajustes → Flow Builder
- Cree un nuevo flow con el disparador
Order placeduOrder status changed → Completed - Añada una acción Send HTTP request
- Método:
POST - URL: su URL de webhook (ver ajustes de integración)
- Content-Type:
application/json
Método B: llamar directamente a la API REST
También puede llamar directamente a la API de invitaciones desde un plugin propio o una app:
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
{
"email": "{{ order.orderCustomer.email }}",
"customerName": "{{ order.orderCustomer.firstName }} {{ order.orderCustomer.lastName }}",
"orderId": "{{ order.orderNumber }}",
"locale": "es",
"delayDays": 7
}Multitienda / multicanal
Si tiene varios canales de venta en Shopware:
- Cree en Zoom.Reviews una ubicación por canal de venta
- Envíe el
locationIden la solicitud a la API - Las reseñas se recopilan por separado y se muestran por canal
Detección del idioma
La integración con Shopware detecta automáticamente el idioma del pedido a partir del campo locale. Idiomas admitidos: de, en, fr, es, it. Si no, se usa el idioma predeterminado configurado.
Integrar el widget en el tema de Shopware
{# Widget con detección automática del idioma #}
<div data-zoom-widget="WIDGET_ID"
data-lang="{{ app.request.locale[:2] }}">
</div>
<script src="https://zoom.reviews/widget.js" async></script>Consejo: cree un widget propio con el locationId correspondiente para cada canal de venta. Así cada tienda muestra solo sus propias reseñas.
¿Listo para la integración?
Empiece gratis e integre sus primeras reseñas en pocos minutos.