Saltar al contenido principal

Recipe: Cart bridge custom

Para activar el carrito en el widget necesitas dos cosas:

  1. Pasar CartConfig con callbacks al inicializar el widget vía NeuroonWidget.init()
  2. Emitir neuroon:cart-update cada vez que el carrito cambie fuera del widget

1. Configurar CartConfig

Al inicializar el widget, define los callbacks que conectan con tu backend:

const widget = window.NeuroonWidget.init({
container: '#neuroon-search',
token: '<widget-token>',
apiUrl: 'https://api.neuroon.ai',
locale: 'es',

cart: {
enabled: true,
initialCount: 0, // badge inicial desde cookie

// El widget llama esto cuando abre el drawer o recibe neuroon:cart-update
onGetCart: async () => {
const res = await fetch('/api/cart', { credentials: 'include' })
const data = await res.json()
return data.cart // CartState { items, totalItems, subtotal, total, currency }
},

onAddToCart: async (productId, quantity, externalProductId) => {
const res = await fetch('/api/cart/add', {
method: 'POST', credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ productId, quantity, externalProductId }),
})
const data = await res.json()
return { success: true, cart: data.cart, notice: data.notice }
},

onRemoveFromCart: async (itemKey) => {
const res = await fetch('/api/cart/remove', {
method: 'POST', credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ itemKey }),
})
const data = await res.json()
return { success: true, cart: data.cart }
},

onUpdateQuantity: async (itemKey, quantity) => {
const res = await fetch('/api/cart/update', {
method: 'POST', credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ itemKey, quantity }),
})
const data = await res.json()
return { success: true, cart: data.cart }
},

onCheckout: () => {
window.location.href = '/checkout'
},
},
})

2. Emitir el evento al mutar el carrito

Cada vez que tu storefront modifica el carrito fuera del widget, emite el evento. El widget lo recibe, aplica un debounce interno de 300 ms, y llama a onGetCart() para releer el estado:

<script>
(function () {
let timer = null;
const emit = () => {
clearTimeout(timer);
timer = setTimeout(() => {
window.dispatchEvent(new CustomEvent('neuroon:cart-update'));
}, 200);
};

document.addEventListener('cart:added', emit);
document.addEventListener('cart:removed', emit);
document.addEventListener('cart:cleared', emit);
})();
</script>

El widget ignora event.detail. Siempre consulta el carrito vía onGetCart(). No necesitas pasar datos en el evento.

React / Next.js

'use client';
import { useEffect } from 'react';

export function CartBridge({ cartSnapshot }: { cartSnapshot: unknown }) {
useEffect(() => {
const t = setTimeout(() => {
window.dispatchEvent(new CustomEvent('neuroon:cart-update'));
}, 200);
return () => clearTimeout(t);
}, [cartSnapshot]);

return null;
}

Renderiza <CartBridge cartSnapshot={cart} /> en tu layout principal.

Vue 3 / Nuxt 3

export function useNeuroonCartBridge(cartStore: Ref<unknown>) {
if (process.server) return;
let timer: ReturnType<typeof setTimeout> | null = null;

watch(cartStore, () => {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
window.dispatchEvent(new CustomEvent('neuroon:cart-update'));
}, 200);
}, { deep: true });
}

Validar que funciona

// Consola del navegador
window.addEventListener('neuroon:cart-update', () => console.log('cart-update recibido'));
// Añade un producto al carrito → deberías ver el log

Buenas prácticas

  • Debounce 200 ms en tu lado. El widget ya aplica 300 ms internamente.
  • initialCount desde cookie para que el badge sobreviva al cache de página.
  • canAddToCart para evitar "añadir al carrito" en productos variables o sin stock.
  • CartOperationResult siempre con el carrito completo. Nada de actualizaciones parciales.
  • Una sola fuente de verdad. Si usas WordPress, el plugin ya cubre esto.

Próximos pasos