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​