Storefront Extensions Overview
Storefront Extensions
Storefront extensions let apps inject UI directly into the customer-facing store — product pages, checkout, homepage, cart, header, and footer. Unlike dashboard extensions which only merchants see, storefront extensions are visible to shoppers.
There are two rendering modes (same as dashboard extensions):
- JSON mode — Declarative UI tree rendered natively by the storefront. No iframe, no hosting. 35+ components including storefront-specific widgets like ratings, countdown timers, trust badges, and product cards.
- Sandbox mode — Your JavaScript runs inside an isolated
<iframe sandbox="allow-scripts">. You control rendering, communicate via postMessage.
Storefront Targets
Every storefront extension declares a target starting with storefront. — this determines where it renders on the store.
| Target | Type | Description |
|---|---|---|
storefront.product.block | Block | Widget below product details (reviews, badges, upsells) |
storefront.product.action | Action | Action button on product page |
storefront.cart.block | Block | Widget in the cart |
storefront.checkout.block | Block | Widget on checkout (upsells, trust badges, custom fields) |
storefront.homepage.block | Block | Section on the homepage |
storefront.global.embed | Embed | Floating widget on all pages (chat bubbles, popups) |
storefront.header.block | Block | Banner or announcement above the header |
storefront.footer.block | Block | Widget above the footer |
storefront.thankyou.block | Block | Post-purchase widget on the thank-you page |
How It Works
1. App registers extension with a storefront.* target
2. App is installed by a store
3. Storefront fetches extensions via GET /api/apps/extensions/storefront
4. StorefrontSlot renders each extension with the StorefrontRenderer
5. Extensions receive page context (product_id, store_id, cart data, etc.)
6. Actions (button clicks) are proxied to your backend via POST /api/apps/extensions/storefront/action
Key Differences from Dashboard Extensions
| Feature | Dashboard | Storefront |
|---|---|---|
| Audience | Merchants/admins | Shoppers/customers |
| Authentication | Requires admin JWT | Public (no auth) |
| API endpoint | GET /api/apps/extensions/page | GET /api/apps/extensions/storefront |
| Action proxy | POST /api/apps/extensions/action | POST /api/apps/extensions/storefront/action |
| Component count | 74 components | 35+ components (storefront-optimized) |
| Available context | Order data, customer details | Product info, cart state, visitor status |
| Caching | 5-minute React Query stale time | 5-minute sessionStorage cache |
| Lazy loading | No | Yes (IntersectionObserver, 200px pre-load) |
| Cart integration | No | Yes (add_to_cart action bridges to Redux) |
| Analytics | No built-in tracking | Automatic impression, click, action tracking |
Public API Endpoints
Fetch Storefront Extensions
GET /api/apps/extensions/storefront?store_id={id}&targets={target1},{target2}
No authentication required. Only accepts storefront.* targets — admin targets are rejected with 400.
Response:
{
"status": 200,
"data": {
"storefront.product.block": [
{
"extension_id": "my-reviews",
"app_id": 42,
"target": "storefront.product.block",
"title": "Customer Reviews",
"mode": "json",
"ui": { "type": "Card", "children": [...] },
"initial_state": {},
"installation_id": 99,
"app_name": "ReviewApp",
"app_slug": "review-app"
}
]
}
}Storefront Action Proxy
POST /api/apps/extensions/storefront/action
No authentication required. Validates installation_id + store_id against the database. Only works for apps with active storefront.* extensions.
Request body:
{
"installation_id": 99,
"store_id": 3,
"action_url": "https://myapp.com/api/reviews/submit",
"method": "POST",
"body": { "product_id": 42, "rating": 5, "comment": "Great!" }
}The backend generates a session token and forwards the request to your app with:
Authorization: Bearer <session_token>headerX-SeloraX-Store-IdheaderX-SeloraX-Installation-IdheaderX-SeloraX-Source: storefrontheader (so you can distinguish storefront vs admin requests)
Rate limited: 60 requests per minute per installation.
SSRF protection: action_url hostname must match your app's registered app_url.
Response Directives
Your app backend can return directives that the storefront automatically processes:
{
"show_toast": { "message": "Review submitted!", "type": "success" },
"update_state": { "submitted": true, "review_count": 43 },
"update_ui": { "type": "Card", "children": [...] },
"navigate": { "url": "/products/other-product" },
"open_link": { "url": "https://example.com" },
"refresh_extensions": true
}| Directive | Effect |
|---|---|
show_toast | Shows a toast notification to the shopper |
update_state | Merges new state into the extension's local state |
update_ui | Replaces the extension's entire UI tree |
navigate | Redirects the page (only http://, https://, / URLs allowed) |
open_link | Opens a URL in a new tab |
refresh_extensions | Clears cache and re-fetches all extensions in this slot |