Skip to content

Embedded apps

An embedded app is a page you host, rendered by OneBooks inside a sandboxed, cross-origin <iframe> — on its own home route, and at every UI extension slot you register.

Your App URL (set on the console’s Embedding tab — this is your app’s home page) must be:

  • https, with no username/password and no #fragment, at most 2,048 characters.
  • Served with Content-Security-Policy: frame-ancestors https://app.getonebooks.com on every page you want embedded — the App URL and every extension path. Without it, browsers refuse to render your page inside OneBooks’ frame — the single most common “my app shows a blank iframe” cause.

Setting an App URL is what makes your app embeddable: it’s required for extensions, for the one-click managed install from the marketplace, and for your app’s own row under Apps in the merchant’s sidebar.

App home (your App URL) gets:

ParamValue
hostThe OneBooks SPA origin — the targetOrigin for your App Bridge messages
localeThe merchant’s current UI language (en, ar, es, fr, pt)
embeddedAlways 1

Extension pages get those three plus:

ParamValue
targetThe extension target, e.g. INVOICE_ACTION — see UI extensions
resourceTypeThe record type, e.g. INVOICE (omitted for DASHBOARD_BLOCK)
resourceIdThe specific record’s id (omitted for DASHBOARD_BLOCK)

An extension’s URL is your App URL’s origin plus the extension’s path — the path is resolved against the origin, not appended to the App URL’s own path. With an App URL of https://yourapp.example.com/onebooks and a path of /invoice-action, OneBooks loads:

https://yourapp.example.com/invoice-action
?host=https%3A%2F%2Fapp.getonebooks.com
&locale=ar
&embedded=1
&target=INVOICE_ACTION
&resourceType=INVOICE
&resourceId=cm1invoice0000000000000001

Treat these parameters as hints for rendering, not as proof of anything: anyone can open your URL with any query string. Identity comes only from a verified session token.

OneBooks renders your page with:

<iframe
src="…"
sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads"
allow="clipboard-write"
referrerpolicy="strict-origin"
loading="lazy"
></iframe>

loading="lazy" applies to blocks only; your home page and action dialogs load eagerly. allow-same-origin alongside allow-scripts is safe here specifically because your frame is cross-origin from the host — it grants your page access to its own origin, not the host’s.

OneBooks always shows who your content comes from, outside your iframe where your page can’t hide or restyle it — deliberate anti-phishing UI a merchant can always check:

  • Home page and action dialogs get a chrome bar: your app’s icon and name, by your organization’s name, a menu with Manage app, and the note This content is provided by <your app>, not OneBooks. In an action dialog the bar also has a close (×) button; Escape and clicking outside the dialog close it too. If your page is taller than the screen, it scrolls under the bar, which stays in place, and a dialog never grows past the viewport however tall you ask it to be.
  • Blocks show your extension’s label with one light line under it: Provided by <your app> (<your organization>), not OneBooks.

These always use the names your app and organization are registered under — title.set can add a secondary heading, but never changes the attribution.

OneBooks sizes your home page itself: it fills the space under the chrome bar, and the resize action isn’t available there. Blocks and action dialogs follow your page instead: each starts at a set height (see UI extensions) and then takes whatever height your page asks for, clamped to 60–1600 px.

The simplest way to ask is app.autoResize(): it measures your <body> content and keeps the frame matched to it, shrinking as well as growing. That relies on <body> keeping its natural height — don’t give it a fixed or 100% height.

Chrome still allows third-party cookies as of this writing, but Safari and Firefox block them by default — a cookie set by your origin inside the iframe will not reliably come back on the next load. Don’t build auth on cookies set inside the embed.

Session tokens are the supported mechanism: App Bridge attaches one to every request your page makes to your own backend, and your backend verifies it on every request and exchanges it for API tokens the first time it sees that business and user. Persist those tokens (the refresh token, specifically) the normal OAuth way — see Authentication — and you have a durable per-user credential without ever relying on a browser cookie surviving inside the frame.

The locale param (and App Bridge’s context.get().dir) tell you the merchant’s language and reading direction. Arabic is right-to-left; mirror your layout accordingly rather than assuming LTR. See Design guidelines for the full expectations.

The locale param is only the language your page starts in: when the merchant switches language or theme, OneBooks does not reload your frame. Listen for the locale.changed and theme.changed App Bridge events and re-render in place.

If OneBooks suspends your app — or your developer account, which takes your organization’s apps offline with it — the app can’t be opened anywhere: its Open app buttons disappear, its sidebar row, actions and blocks stop showing, and its app URL in OneBooks shows Suspended by OneBooks instead of your page. An app you deleted in the console can’t be opened either — no Open app button, sidebar row, actions or blocks — but merchants see No longer available, not Suspended by OneBooks, on its card and at its address. After an uninstall, the same address shows App not installed with a link to your listing; and if you remove your App URL, businesses that still have your app see This app can’t be opened here.