Context, Cart & Analytics
Context, Cart & Analytics
Storefront extensions automatically receive enriched context about the page, the visitor, and their cart. Extensions can also add items to the cart and emit analytics events.
Context Data
Every storefront extension receives a context object with data about the current page and visitor. The exact fields depend on the target.
Universal Context (all targets)
| Field | Type | Description |
|---|---|---|
store_id | number | The store's ID |
domain | string | The store's domain |
is_logged_in | boolean | Whether the visitor has an auth token |
cart_item_count | number | Number of items in the visitor's cart |
cart_total | number | Total value of the cart |
__target | string | The extension target name |
__loading | boolean | Whether a call_backend action is in progress |
Product Page Context (storefront.product.block)
| Field | Type | Description |
|---|---|---|
product_id | number | Product ID |
product_name | string | Product name |
product_price | number | Product price |
category_id | number | Product category ID |
Checkout Context (storefront.checkout.block)
| Field | Type | Description |
|---|---|---|
store_id | number | Store ID |
Use {{context.product_id}} in templates to access context values.
Cart Integration
Extensions can add items to the shopper's cart using the add_to_cart action type.
Add to Cart
{
"type": "Button",
"props": {
"label": "Add to Cart",
"icon": "ShoppingCart",
"action": {
"type": "add_to_cart",
"sku_id": 12345,
"product_id": 42,
"name": "Premium Widget",
"price": 999,
"quantity": 1,
"image": "https://cdn.example.com/product.jpg",
"variant_name": "Large / Blue",
"message": "Added to your cart!"
}
}
}The item is added to the storefront's Redux basket. If the sku_id already exists in the cart, the quantity is increased instead of creating a duplicate.
A success toast is shown automatically with the message text (defaults to "Added to cart!").
Remove from Cart
{ "type": "Button", "props": { "label": "Remove", "action": { "type": "remove_from_cart", "sku_id": 12345 } } }Other Action Types
| Action Type | Props | Description |
|---|---|---|
call_backend | url, method, body, onLoading, onSuccess, onError | Proxy request to your app backend |
set_state | state (object) | Merge values into extension state |
open_link | url | Open URL in new tab |
navigate | to or url | Redirect the page |
open_modal | modal (object) | Open a modal overlay |
close_modal | — | Close the active modal |
copy | text | Copy text to clipboard |
share | title, text, url | Web Share API (falls back to clipboard) |
scroll_to | selector | Smooth scroll to a CSS selector |
track | event, data | Fire a custom analytics event |
add_to_cart | sku_id, name, price, quantity, etc. | Add product to cart |
remove_from_cart | sku_id | Remove product from cart |
Analytics Events
Storefront extensions automatically emit analytics events through the store's existing tracking system (Facebook Pixel, GTM, SeloraX Analytics all receive them).
Automatic Events
| Event | When | Data |
|---|---|---|
EXT_slot_loaded | Extension slot fetched and rendered | target, store_id, count, load_time_ms |
EXT_impression | Extension first visible | extension_id, app_id, target, app_name |
EXT_click | Any action button clicked | extension_id, action_type, target |
EXT_action | Backend action completed | extension_id, action_url, status, duration_ms |
EXT_add_to_cart | Item added to cart from extension | extension_id, sku_id, price |
EXT_error | Extension crashes (caught by error boundary) | extension_id, error |
Custom Events
Extensions can fire custom analytics events:
{
"type": "Button",
"props": {
"label": "View Offer",
"action": { "type": "track", "event": "offer_viewed", "data": { "offer_id": "summer-sale" } }
}
}This fires EXT_custom with { extension_id, event: "offer_viewed", offer_id: "summer-sale" }.
Listening to Extension Events
In GTM or custom scripts, listen for extension events:
document.addEventListener("EXT_impression", (e) => {
console.log("Extension viewed:", e.detail);
});
window.addEventListener("selorax:ext:add_to_cart", (e) => {
console.log("Extension added to cart:", e.detail);
});Caching
Extension data is cached in sessionStorage for 5 minutes per store+target combination. This means:
- Navigating between pages doesn't re-fetch extensions
- The cache auto-expires after 5 minutes
- Extensions can force a refetch via the
refresh_extensionsresponse directive - Clearing
sessionStorageclears the cache immediately
Cache key format: sf_ext_{store_id}_{target}
Lazy Loading
Storefront slots use IntersectionObserver by default:
- Extensions below the fold are not fetched until the slot scrolls within 200px of the viewport
- Extensions above the fold (e.g.,
storefront.header.block) should setlazy={false}for immediate loading - The observer disconnects once the slot becomes visible (no ongoing overhead)
Error Isolation
Each extension runs inside a React Error Boundary. If one extension crashes:
- It is silently hidden (no error UI shown to shoppers)
- Other extensions in the same slot continue working
- An
EXT_erroranalytics event is fired - The error is logged to the browser console
Print Behavior
All extension slots are hidden during @media print — extensions don't appear on printed pages.