How the embedded UI works
When a merchant opens your app from the dashboard dock, your app’sappUrl is loaded in a
sandboxed <iframe> inside the dashboard. The dashboard appends a few context parameters so
your app can recognise the active store and user without a separate auth step:
| Parameter | Description |
|---|---|
shop | The installed store’s id. Use this to look up your stored OAuth tokens and make API calls on behalf of this store. |
name | The store’s display name. Useful for greeting the merchant before your API call returns. |
user | The Salesive user id of the merchant currently using the dashboard. Check this against your session to detect account switches (see session binding). |
embedded | Always "1". Use this to detect the embedded context and hide your public marketing shell. |
host | The dashboard’s origin (https://app.salesive.com). |
These parameters are for convenience — they identify the context, not prove identity.
The actual authentication proof is your signed, HttpOnly session cookie set during the OAuth
install (see Install flow). Never trust
shop/user from the URL
without validating against your session.Background pre-loading
The dashboard pre-loads every installed app in a hidden iframe when the merchant opens the dashboard — before the merchant ever taps the dock icon. This means:- Your app’s code, assets, and connections are already warm by the time the merchant opens it.
- Background work (polling, WebSocket connections, sync) can start immediately, not only when the merchant looks at the app.
- The first open is instant — no loading spinner if your app has initialised in the background.
salesive:app-wake
postMessage. Register a handler for this to start background work:
fetch() calls all work normally in the background.
Full lifecycle
Every embedded app goes through these events:Runtime permissions
Some capabilities — expanding the app programmatically, reading the clipboard, cancelling orders — require explicit, time-limited merchant approval. Unlike OAuth install scopes (which are approved once at install), runtime permissions can be requested at any time via a dashboard modal the merchant approves or denies. The merchant chooses a duration (once, 1 day, 7 days, etc.) and can revoke at any time.Available runtime permissions
| Permission | What it lets your app do |
|---|---|
AUTO_LAUNCH | Call onLaunch() to expand the app from background without the merchant tapping the dock. |
WRITE_DOMAINS | Add and remove custom domains linked to the merchant’s store. |
CLIPBOARD_READ | Read text from the merchant’s system clipboard. |
WRITE_ORDERS_CANCEL | Cancel orders on the merchant’s behalf (irreversible). |
The App Bridge package
Install the helper:@types/ package needed.
onAppWake(callback)
Fires when the dashboard first loads the app in the background. This is the earliest point
at which your app’s JavaScript runs. Use it to start long-running background work.
onAppOpened(callback)
Fires each time the merchant expands the app to full view (first open or restore from
minimized). Use it to refresh UI data that may be stale after time in the background.
onAppMinimized(callback)
Fires when the merchant presses − (minimize) or swipes the sheet down on mobile. The app
is hidden but still running.
onAppClosed(callback)
Fires when the merchant presses × (close / dismiss). The app is still running in the
background — this is the same as minimized from a lifecycle standpoint, but signals that
the merchant deliberately dismissed the panel rather than just hiding it.
requestPermission(permission, options?, timeoutMs?)
Show the merchant a permission modal. Returns true if approved, false if denied or
timed out. The modal has a 10-second auto-deny countdown.
| Constant | String | Lasts |
|---|---|---|
DURATIONS.ONCE | "once" | Consumed on first exercise |
DURATIONS.ONE_DAY | "1day" | 1 day |
DURATIONS.SEVEN_DAYS | "7days" | 7 days |
DURATIONS.FOURTEEN_DAYS | "14days" | 14 days |
DURATIONS.THIRTY_ONE_DAYS | "31days" | 31 days |
getGrantedPermissions(timeoutMs?)
Silently retrieve the merchant’s active grants — no modal shown. Call this on wake or
mount to avoid requesting a permission the merchant already approved.
Permission → GrantRecord:
onLaunch()
Ask the dashboard to expand (un-minimize) this app. The call is silently ignored if
AUTO_LAUNCH has not been granted.
onEvent(type, callback)
Subscribe to any postMessage event by type string — including future event types not yet in
this helper. Callbacks receive the full raw message data object.
APP_EVENTS constants
| Constant | Event type string | When it fires |
|---|---|---|
APP_EVENTS.WAKE | salesive:app-wake | Background iframe first loaded |
APP_EVENTS.OPENED | salesive:app-opened | App expanded to full view |
APP_EVENTS.MINIMIZED | salesive:app-minimized | Merchant pressed − |
APP_EVENTS.CLOSED | salesive:app-closed | Merchant pressed × |
APP_EVENTS.PERMISSION_RESPONSE | salesive:permission-response | Response to requestPermission() |
APP_EVENTS.PERMISSIONS_STATE | salesive:permissions-state | Response to getGrantedPermissions() |
Complete React example
Environment notes
- Browser only — all functions are no-ops in Node.js / SSR contexts (return
false,{}, or a no-op unsubscribe). Safe to import in Next.js or Remix server components. - No runtime dependencies — the permissions subpath has zero dependencies.
- Single listener — one
window.addEventListener("message", …)is registered on module import. Multiple concurrentrequestPermission()calls resolve independently.
Next steps
OAuth install flow
Set up the token exchange and session binding.
Scopes & permissions
The API scopes your backend calls need.
Build & publish
Submit your app for marketplace review.
Webhooks
Real-time store events for your backend.

