Customer Account Extensions
Customer-account extensions are iframes injected into the customer’s account pages (/account, /orders/[orderId], /account/profile).
Use them for order tracking widgets, loyalty balances, support chat
panels, and similar customer-facing surfaces.
These are distinct from admin extensions (which target the merchant
admin UI) and from checkout extensions (which target the
unauthenticated checkout flow). They run for a logged-in customer with
the customer’s session.
Targets
All four targets have a slot mounted in the storefront account
pages.
dashboard.block.render renders above the page header on
/account; order-list.block.render renders between the header and the
order history list on the same page; profile.block.render renders above
the “Profile” heading on /account/profile; order-status.block.render
renders on the per-order page.
The <CustomerAccountExtensionSlot target="..." /> component renders one
iframe per registered extension at the given target. It requires the
customer’s session token as bearerToken; without it the slot API returns
401 and the slot renders empty (correct secure default — extension
enumeration is gated behind authentication).
Manifest
How the iframe is rendered
Each registered extension is rendered as a plain iframe pointed at its resolvedurl:
- No App Bridge host on this surface. Unlike admin extensions, the
customer-account slot does not run an App Bridge postMessage host, and
it does not push any context object into the iframe. There is no
useApi()/EXTENSION_CONTEXTwiring on the storefront side. - No page context is injected into the URL. The slot mounts with the
store’s
domainSlugand the customer’s bearer token only — the host does not appendorderId/customerIdquery parameters to your iframeurl. If your extension needs to know which order or customer it’s rendering for, fetch that from your own backend using the customer session token (see Security), or derive it from the page your block targets. - Fixed height. The iframe renders at a fixed 120px height. Keep your block compact, or scroll within it.
Discovery
The storefront exposes:
Behind the storefront route, the platform resolves the first source via:
Extensions registered through the dev portal now render. Earlier builds
had no backend resolver for this category, so only on-disk manifests were
ever returned and portal-registered customer-account extensions stayed
invisible with no error. If you registered one previously and never saw
it, no manifest change is required — it resolves on its own.
Security
- The iframe is sandboxed with
allow-scripts allow-forms allow-popupsand noallow-same-origin, so it runs in an opaque origin and cannot read the parent page’s cookies or storage. - Enumerating a store’s installed extensions is gated behind
authentication: the discovery endpoint requires the customer’s bearer
token and returns
401without it (the slot then renders nothing). The token is validated by the platform on every call — a non-OK result yields no extensions rather than falling back to the on-disk manifests. - The bearer token the slot is mounted with is the customer’s session credential. If your iframe needs to call an API on behalf of the customer, your own backend must independently verify that credential — never trust ids passed to you in the clear.