Events
The Next Commerce JS SDK emits 34 internal events that you can listen to for tracking and custom functionality.
Event Categories
Section titled “Event Categories”- Cart Events - Track cart state changes
- Checkout Events - Monitor checkout process
- Payment Events - Handle payment states
- Order Events - Track order completion
- Campaign Events - Campaign data loading
- Coupon Events - Discount code usage
- Upsell Events - Post-purchase upsell tracking
- User Events - User authentication
- Behavioral Events - FOMO, exit intent
- Profile Events - Profile management and switching
- System Events - SDK state, errors, routing
SDK Initialization
Section titled “SDK Initialization”next:initialized
Section titled “next:initialized”Fired when SDK is fully loaded and ready (DOM event):
// Listen on document for initializationdocument.addEventListener('next:initialized', function(event) { console.log('SDK is ready at:', event.detail.timestamp); console.log('Version:', event.detail.version); // Safe to use SDK methods here});Cart Events
Section titled “Cart Events”cart:updated
Section titled “cart:updated”Fired whenever cart contents change (most common event):
next.on('cart:updated', (cartState) => { console.log('Cart updated:', cartState); // cartState includes: items, totals, enrichedItems, etc. console.log('Total items:', cartState.totalQuantity); console.log('Cart total:', cartState.totals.total.formatted);});cart:item-added
Section titled “cart:item-added”Fired when item is added to cart:
next.on('cart:item-added', (data) => { console.log('Item added:', data); // data includes: packageId, quantity, item details});cart:item-removed
Section titled “cart:item-removed”Fired when item is removed from cart:
next.on('cart:item-removed', (data) => { console.log('Item removed:', data); // data includes: packageId, item details that were removed});cart:quantity-changed
Section titled “cart:quantity-changed”Fired when item quantity is updated:
next.on('cart:quantity-changed', (data) => { console.log('Quantity changed:', data); // data includes: packageId, oldQuantity, newQuantity});cart:package-swapped
Section titled “cart:package-swapped”Fired when a package is swapped for another:
next.on('cart:package-swapped', (data) => { console.log('Package swapped:', data); // data includes: previousPackageId, newPackageId, // previousItem, newItem, priceDifference, source});Checkout & Order Events
Section titled “Checkout & Order Events”checkout:started
Section titled “checkout:started”Fired when checkout process begins:
next.on('checkout:started', (data) => { console.log('Checkout started:', data); // data includes: cart items, totals});checkout:form-initialized
Section titled “checkout:form-initialized”Fired when checkout form is ready:
next.on('checkout:form-initialized', () => { console.log('Checkout form ready'); // Form is now initialized and ready for input});order:completed
Section titled “order:completed”Fired when order is successfully completed:
next.on('order:completed', (order) => { console.log('Order completed:', order); // order includes: ref_id, total, lines, customer info});Payment Events
Section titled “Payment Events”payment:tokenized
Section titled “payment:tokenized”Fired when payment is successfully tokenized:
next.on('payment:tokenized', (data) => { console.log('Payment tokenized:', data); // data includes: token info, payment method});payment:error
Section titled “payment:error”Fired when payment processing fails:
next.on('payment:error', (error) => { console.error('Payment failed:', error); // error includes: message, code, details});express-checkout:started
Section titled “express-checkout:started”Fired when express checkout (PayPal, Apple Pay, etc.) begins:
next.on('express-checkout:started', (data) => { console.log('Express checkout started:', data); // data includes: method type (paypal, apple, google)});Campaign & Configuration Events
Section titled “Campaign & Configuration Events”campaign:loaded
Section titled “campaign:loaded”Fired when campaign data is loaded:
next.on('campaign:loaded', (campaign) => { console.log('Campaign loaded:', campaign); // campaign includes: packages, settings, currency, etc.});config:updated
Section titled “config:updated”Fired when SDK configuration changes:
next.on('config:updated', (config) => { console.log('Config updated:', config); // config includes: all SDK settings});Coupon Events
Section titled “Coupon Events”coupon:applied
Section titled “coupon:applied”Fired when coupon is successfully applied:
next.on('coupon:applied', (coupon) => { console.log('Coupon applied:', coupon); // coupon includes: code, discount amount, type});coupon:removed
Section titled “coupon:removed”Fired when coupon is removed:
next.on('coupon:removed', (code) => { console.log('Coupon removed:', code); // code is the removed coupon code string});Upsell Events
Section titled “Upsell Events”upsell:viewed
Section titled “upsell:viewed”Fired when upsell offer is displayed:
next.on('upsell:viewed', (data) => { console.log('Upsell viewed:', data); // data includes: packageId, offer details});upsell:accepted
Section titled “upsell:accepted”Fired when user accepts an upsell:
next.on('upsell:accepted', (data) => { console.log('Upsell accepted:', data); // data includes: packageId, quantity, value});upsell:added
Section titled “upsell:added”Fired when upsell is successfully added to order:
next.on('upsell:added', (data) => { console.log('Upsell added:', data); // data includes: packageId, order, value});upsell:skipped
Section titled “upsell:skipped”Fired when user skips/declines an upsell:
next.on('upsell:skipped', (data) => { console.log('Upsell skipped:', data); // data includes: packageId, reason});User Events
Section titled “User Events”user:logged-in
Section titled “user:logged-in”Fired when user logs in:
next.on('user:logged-in', (data) => { console.log('User logged in:', data); // data includes: user info, email});user:logged-out
Section titled “user:logged-out”Fired when user logs out:
next.on('user:logged-out', (data) => { console.log('User logged out:', data);});Behavioral Events
Section titled “Behavioral Events”fomo:shown
Section titled “fomo:shown”Fired when FOMO notification appears:
next.on('fomo:shown', (data) => { console.log('FOMO shown:', data); // data includes: customer name, product, location});exit-intent:clicked
Section titled “exit-intent:clicked”Fired when user clicks on exit intent popup:
next.on('exit-intent:clicked', (data) => { console.log('Exit intent clicked:', data); // data includes: imageUrl, template});exit-intent:dismissed
Section titled “exit-intent:dismissed”Fired when exit intent popup is dismissed:
next.on('exit-intent:dismissed', (data) => { console.log('Exit intent dismissed:', data); // data includes: imageUrl, template});exit-intent:closed
Section titled “exit-intent:closed”Fired when exit intent popup is closed:
next.on('exit-intent:closed', (data) => { console.log('Exit intent closed:', data); // data includes: imageUrl, template});exit-intent:action
Section titled “exit-intent:action”Fired when user takes an action on exit intent popup:
next.on('exit-intent:action', (data) => { console.log('Exit intent action:', data); // data includes: action, couponCode});Profile Events
Section titled “Profile Events”profile:applied
Section titled “profile:applied”Fired when a profile is applied to the cart:
next.on('profile:applied', (data) => { console.log('Profile applied:', data); // data includes: profileId, previousProfileId, // itemsSwapped, originalItems, cleared, profile});profile:reverted
Section titled “profile:reverted”Fired when profile changes are reverted:
next.on('profile:reverted', (data) => { console.log('Profile reverted:', data); // data includes: previousProfileId, itemsRestored});profile:switched
Section titled “profile:switched”Fired when switching between profiles:
next.on('profile:switched', (data) => { console.log('Profile switched:', data); // data includes: fromProfileId, toProfileId, itemsAffected});profile:registered
Section titled “profile:registered”Fired when a new profile is registered:
next.on('profile:registered', (data) => { console.log('Profile registered:', data); // data includes: profileId, mappingsCount});System Events
Section titled “System Events”route:changed
Section titled “route:changed”Fired when SDK detects route/page change:
next.on('route:changed', (route) => { console.log('Route changed:', route); // route includes: path, params});sdk:route-invalidated
Section titled “sdk:route-invalidated”Fired when SDK route context is invalidated:
next.on('sdk:route-invalidated', (data) => { console.log('Route invalidated:', data);});page:viewed
Section titled “page:viewed”Fired when page view is tracked:
next.on('page:viewed', (data) => { console.log('Page viewed:', data); // data includes: page info, timestamp});error:occurred
Section titled “error:occurred”Fired when SDK encounters an error:
next.on('error:occurred', (error) => { console.error('SDK error:', error); // error includes: message, stack, context});Complete Event List
Section titled “Complete Event List”All 34 available events organized by category:
Cart (5 events)
Section titled “Cart (5 events)”cart:updated- Cart state changedcart:item-added- Item added to cartcart:item-removed- Item removed from cartcart:quantity-changed- Item quantity changedcart:package-swapped- Package swapped for another
Checkout & Order (3 events)
Section titled “Checkout & Order (3 events)”checkout:started- Checkout process begancheckout:form-initialized- Checkout form readyorder:completed- Order successfully completed
Payment (3 events)
Section titled “Payment (3 events)”payment:tokenized- Payment token createdpayment:error- Payment processing failedexpress-checkout:started- Express checkout initiated
Campaign & Config (2 events)
Section titled “Campaign & Config (2 events)”campaign:loaded- Campaign data loadedconfig:updated- Configuration changed
Coupons (2 events)
Section titled “Coupons (2 events)”coupon:applied- Discount code appliedcoupon:removed- Discount code removed
Upsells (4 events)
Section titled “Upsells (4 events)”upsell:viewed- Upsell offer shownupsell:accepted- Upsell accepted by userupsell:added- Upsell added to orderupsell:skipped- Upsell declined/skipped
User (2 events)
Section titled “User (2 events)”user:logged-in- User authenticateduser:logged-out- User logged out
Behavioral (5 events)
Section titled “Behavioral (5 events)”fomo:shown- FOMO popup displayedexit-intent:clicked- Exit intent popup clickedexit-intent:dismissed- Exit intent popup dismissedexit-intent:closed- Exit intent popup closedexit-intent:action- Exit intent action taken
Profile (4 events)
Section titled “Profile (4 events)”profile:applied- Profile applied to cartprofile:reverted- Profile changes revertedprofile:switched- Switched between profilesprofile:registered- New profile registered
System (4 events)
Section titled “System (4 events)”route:changed- Page/route changedsdk:route-invalidated- Route context resetpage:viewed- Page view trackederror:occurred- Error encountered
Event Handling Patterns
Section titled “Event Handling Patterns”Basic Event Listening
Section titled “Basic Event Listening”// Subscribe to eventsnext.on('cart:updated', (data) => { console.log('Cart updated:', data);});
// Multiple events['cart:item-added', 'cart:item-removed'].forEach(event => { next.on(event, (data) => { console.log(`Event ${event}:`, data); });});Removing Listeners
Section titled “Removing Listeners”const handler = (data) => console.log(data);
// Add listenernext.on('cart:updated', handler);
// Remove listenernext.off('cart:updated', handler);Error Handling in Events
Section titled “Error Handling in Events”next.on('cart:updated', (data) => { try { // Your code here updateUI(data); } catch (error) { console.error('Error in event handler:', error); }});DOM Events vs SDK Events
Section titled “DOM Events vs SDK Events”// DOM events (for SDK lifecycle)document.addEventListener('next:initialized', (event) => { console.log('SDK ready via DOM event');});
// SDK events (for cart, checkout, etc.)next.on('cart:updated', (data) => { console.log('Cart updated via SDK event');});Custom Event Integration
Section titled “Custom Event Integration”Google Analytics
Section titled “Google Analytics”next.on('cart:item-added', (data) => { if (typeof gtag !== 'undefined') { gtag('event', 'add_to_cart', { value: data.item.price, currency: 'USD', items: [data.item] }); }});
next.on('order:completed', (order) => { if (typeof gtag !== 'undefined') { gtag('event', 'purchase', { transaction_id: order.ref_id, value: order.total, currency: order.currency, items: order.lines }); }});Facebook Pixel
Section titled “Facebook Pixel”next.on('cart:item-added', (data) => { if (typeof fbq !== 'undefined') { fbq('track', 'AddToCart', { content_ids: [data.packageId], content_type: 'product', value: data.item.price, currency: 'USD' }); }});
next.on('checkout:started', (data) => { if (typeof fbq !== 'undefined') { fbq('track', 'InitiateCheckout', { value: data.total, currency: 'USD', num_items: data.itemCount }); }});Custom Analytics
Section titled “Custom Analytics”// Track all cart changesnext.on('cart:updated', (data) => { fetch('/api/track', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ event: 'cart_updated', properties: data }) });});
// Track conversionsnext.on('order:completed', async (order) => { await fetch('/api/conversions', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(order) });});Debugging Events
Section titled “Debugging Events”List All Available Events
Section titled “List All Available Events”// Get all registered events from the EventBusif (window.next && window.next.eventBus) { const listeners = window.next.eventBus.listeners; const events = Array.from(listeners.keys()).sort();
console.log('Available events:', events.length); events.forEach((event, i) => { const count = listeners.get(event).size; console.log(`${i + 1}. ${event} (${count} listeners)`); });}Monitor All Events
Section titled “Monitor All Events”// Log all events for debuggingif (window.location.search.includes('debug=true')) { const allEvents = [ // Cart 'cart:updated', 'cart:item-added', 'cart:item-removed', 'cart:quantity-changed', 'cart:package-swapped', // Checkout & Order 'checkout:started', 'checkout:form-initialized', 'order:completed', // Payment 'payment:tokenized', 'payment:error', 'express-checkout:started', // Campaign & Config 'campaign:loaded', 'config:updated', // Coupons 'coupon:applied', 'coupon:removed', // Upsells 'upsell:viewed', 'upsell:accepted', 'upsell:added', 'upsell:skipped', // User 'user:logged-in', 'user:logged-out', // Behavioral 'fomo:shown', 'exit-intent:clicked', 'exit-intent:dismissed', 'exit-intent:closed', 'exit-intent:action', // Profile 'profile:applied', 'profile:reverted', 'profile:switched', 'profile:registered', // System 'route:changed', 'sdk:route-invalidated', 'page:viewed', 'error:occurred' ];
allEvents.forEach(event => { next.on(event, (data) => { console.log(`[Event] ${event}:`, data); }); });}Best Practices
Section titled “Best Practices”- Always check data: Validate event data before using
- Handle errors: Wrap handlers in try-catch
- Clean up: Remove listeners when no longer needed
- Don’t block: Keep handlers fast and async
- Test events: Verify events fire as expected
- Batch operations: Group related operations for performance
- Use appropriate events: Choose the most specific event for your use case
Common Use Cases
Section titled “Common Use Cases”Cart Abandonment Tracking
Section titled “Cart Abandonment Tracking”let cartTimer;const ABANDONMENT_DELAY = 30 * 60 * 1000; // 30 minutes
next.on('cart:updated', (data) => { clearTimeout(cartTimer);
if (data.totalQuantity > 0) { cartTimer = setTimeout(() => { // Track abandonment fetch('/api/cart-abandoned', { method: 'POST', body: JSON.stringify(data) }); }, ABANDONMENT_DELAY); }});
next.on('order:completed', () => { clearTimeout(cartTimer);});Dynamic UI Updates
Section titled “Dynamic UI Updates”// Update cart count in headernext.on('cart:updated', (data) => { const badge = document.querySelector('.cart-badge'); if (badge) { badge.textContent = data.totalQuantity || ''; badge.style.display = data.totalQuantity > 0 ? 'block' : 'none'; }});
// Show success notificationsnext.on('cart:item-added', (data) => { showNotification(`${data.item.name} added to cart!`, 'success');});
// Update checkout button statenext.on('cart:updated', (data) => { const checkoutBtn = document.querySelector('.checkout-button'); if (checkoutBtn) { checkoutBtn.disabled = data.totalQuantity === 0; }});Related Documentation
Section titled “Related Documentation”- JavaScript API Methods - Using SDK methods
- Callbacks - Legacy callback patterns
- Analytics - Tracking and analytics
- Data Attributes - HTML-based event triggers