Venta cruzada
Cuando el host tiene cart.enabled = true, el widget puede pedir al backend recomendaciones complementarias para el carrito actual: productos que suelen comprarse junto a los items presentes, descartando los que ya están en el carrito o que ya viste. Se renderiza con CrossSellSection.
Endpoint
/api/widget/cart/cross-sellcurl -X POST https://api.neuroon.ai/api/widget/cart/cross-sell \
-H "X-Widget-Token: $WIDGET_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"productIds": ["p_iphone_15"],
"language": "es"
}'
Definido en
WidgetProductController.java(body:CartCrossSellRequestDTO { productIds: string[], language?: string }). Devuelve{ message, products[] }. Si no hay recomendaciones aplicables, responde 204 No Content sin body.
Diferencia con cartAction.ADD_SUGGESTION
Hay dos canales por los que el widget recomienda añadir un producto:
| Canal | Origen | UX |
|---|---|---|
POST /api/widget/cart/cross-sell | El widget invoca el endpoint cuando se monta el cart drawer o tras cambios de items | Sección con varios productos en el drawer / página de carrito. |
cartAction.ADD_SUGGESTION en SearchResponse | El agente conversacional decide proactivamente (durante búsqueda) que tiene sentido sugerir un producto concreto | Tarjeta premium con confirmationPrompt, una sola sugerencia. |
Ranking
El backend usa señales como:
- Co-compra histórica (carritos cerrados con ambos productos).
- Compatibilidad de categoría (regla declarativa por shop).
- Margen y stock (penaliza out-of-stock).
- Reduplicación (no devuelve productos ya en el carrito).
El motor de recomendaciones está en el engine Python, no en este repo del widget. Si necesitas inspeccionar la lógica concreta, abre un issue a soporte.
Cuándo se invoca
- Al abrir el drawer del carrito si no hay datos cacheados.
- Cuando el drawer está abierto y cambian los items del carrito (debounce 600 ms en
useCartCrossSell.ts:90). El listener no se dispara automáticamente con cadaneuroon:cart-update— sólo cuando el drawer está visible. - Manual:
widget.openCart().
Tracking
Click en una card de cross-sell se reporta como evento normal (POST /api/widget/track/click) con metadata.source = 'cross_sell', lo que permite medir incremento real vs base.
Próximas lecturas
- Integración de carrito
- Configuración — habilitar
cart. - Analytics y tracking