Server Events
Server events are pushed from the Storefront API to your client application. Register handlers for these events to respond to basket updates and errors.
BasketUpdated
Triggered whenever the basket state changes. This event is fired after successful calls to AddItem, RemoveItems, ApplyPromoCode, or RemovePromoCode.
connection.on("BasketUpdated", (basket) => {
// Handle basket update
});
Payload
The event payload contains the complete basket state:
{
"items": [
{
"lineItemId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"productId": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"productName": "Gift Voucher - $50",
"retailPrice": {
"amount": 50.00,
"currency": "USD"
},
"quotedPrice": {
"amount": 45.00,
"currency": "USD"
}
}
],
"promoCode": "SUMMER20",
"stage": "Basket"
}
Basket Properties
| Property | Type | Description |
|---|---|---|
items | LineItem[] | Array of items in the basket |
promoCode | string | null | Currently applied promo code, if any |
stage | string | Basket stage (see below) |
Basket Stages
| Stage | Description |
|---|---|
Basket | Basket is active and can be modified |
Settled | Order has been completed - create a new basket |
Example Handler
connection.on("BasketUpdated", (basket) => {
// Update item count
updateCartBadge(basket.items.length);
// Calculate totals
let total = 0;
let discountedTotal = 0;
basket.items.forEach((item) => {
total += item.retailPrice.amount;
discountedTotal += item.quotedPrice.amount;
});
// Update UI
updatePriceDisplay(total, discountedTotal, basket.promoCode);
renderCartItems(basket.items);
// Handle completed orders
if (basket.stage === "Settled") {
clearLocalBasket();
showOrderConfirmation();
}
});
SomethingHappened
Triggered when an error occurs during a hub method invocation.
connection.on("SomethingHappened", (error) => {
// Handle error
});
Payload
{
"errorCode": "PromoCodeDoesntExist",
"message": "The promo code is invalid or expired"
}
Error Properties
| Property | Type | Description |
|---|---|---|
errorCode | string | Machine-readable error identifier |
message | string | Human-readable error description |
Error Codes
| Error Code | Description | Recommended Action |
|---|---|---|
PromoCodeDoesntExist | The promo code is invalid or expired | Display validation message to user |
UnavailableProduct | The product cannot be added to the basket | Remove from UI or show unavailable state |
OrderWasProcessed | The basket has already been completed | Create a new basket |
Example Handler
connection.on("SomethingHappened", async (error) => {
switch (error.errorCode) {
case "PromoCodeDoesntExist":
showPromoCodeError("This promo code is invalid or has expired");
break;
case "UnavailableProduct":
showNotification("This product is currently unavailable");
break;
case "OrderWasProcessed":
// Basket was already completed, create a new one
const newBasketId = generateBasketId();
localStorage.setItem("basketId", newBasketId);
await connection.invoke("CreateBasket", newBasketId, salesChannelId);
showNotification(
"Your previous order was completed. Starting a new basket.",
);
break;
default:
console.error("Unexpected error:", error);
showNotification("An error occurred. Please try again.");
}
});
Event Registration Best Practices
Register Before Connecting
Always register event handlers before starting the connection:
// Correct order
connection.on("BasketUpdated", handleBasketUpdate);
connection.on("SomethingHappened", handleError);
await connection.start();
// Incorrect - may miss events
await connection.start();
connection.on("BasketUpdated", handleBasketUpdate); // Too late!
Handle All Events
Always register handlers for both events to ensure your application responds appropriately:
function initializeEventHandlers(connection) {
connection.on("BasketUpdated", (basket) => {
hideLoadingSpinner();
updateUI(basket);
});
connection.on("SomethingHappened", (error) => {
hideLoadingSpinner();
handleError(error);
});
}