Inside the admin
Your app's home, panels beside a record, actions in a record's Apps menu, and actions on the rows a merchant ticks in a list.
An app shows up in the admin in four ways. Each one is a page of yours that the admin frames, hands a session to, and talks to over App Bridge.
| Kind | Where it appears | Declared with |
|---|---|---|
| Home | A full height page at /stores/<id>/apps/<slug>, with your navigation as tabs above it | [app] url and [[app.navigation]] |
| Panel | Beside a record, in the column on the right | [[extensions.admin]] at a .sidebar or .block point |
| Action on a record | In the record's Apps menu, opening your page in a window | [[extensions.admin]] at a .detail.action point |
| Action on a list | In the list's bar once rows are ticked, opening your page in a window with the ticked ids | [[extensions.admin]] at an .index.action point |
Your home
With [app] url set, an installed app gets a full height page in the admin at /stores/<id>/apps/<slug>. The admin frames your URL with ?session=<token>; verify it with authenticateAdmin before rendering anything. The path after your slug is the path inside your home, so pages can be bookmarked and back and forward work.
[[app.navigation]] entries become tabs above your home, so merchants can reach your pages directly. Your home is the page the title bar and the save bar are made for, and the page a modal opens a page of.
Points
Each [[extensions.admin]] entry names a point, the URL framed there, and a title: the panel's heading, or the action's name in the menu.
[[extensions.admin]]
point = "admin.order.detail.sidebar"
url = "https://reviews.example.com/embed/order"
title = "Reviews"
[[extensions.admin]]
point = "admin.product.index.action"
url = "https://reviews.example.com/embed/ask-for-reviews"
title = "Ask for reviews"| Point | What it is | In context |
|---|---|---|
admin.product.detail.sidebar | A panel beside a product | productId, productHandle |
admin.product.detail.action | An action in a product's Apps menu | productId, productHandle |
admin.product.index.action | An action on the products ticked in the list | selection |
admin.collection.detail.sidebar | A panel beside a collection | collectionId, collectionHandle |
admin.collection.detail.action | An action in a collection's Apps menu | collectionId, collectionHandle |
admin.order.detail.sidebar | A panel beside an order | orderId, orderNumber |
admin.order.detail.action | An action in an order's Apps menu | orderId, orderNumber |
admin.orders.index.action | An action on the orders ticked in the list | selection |
admin.customer.detail.sidebar | A panel beside a customer | customerId |
admin.customer.detail.action | An action in a customer's Apps menu | customerId |
admin.customers.index.action | An action on the customers ticked in the list | selection |
admin.settings.block | A block at the foot of the shop's settings, sharing its save bar | nothing |
context is in the session's claims, and in App Bridge's welcome. Every point reads the release the shop has approved: a panel added or moved by a newer manifest appears once the merchant approves that release.
Actions on a list
An action at an .index.action point appears in the list's bar once a merchant ticks rows. Choosing it opens your page in a window over the list, and context.selection holds the ids of the rows ticked, at most 100.
The selection is inside the signed session token, never in your page's address. Nobody can hand your app a selection the merchant did not make by editing a URL, and your server reads it from the claims it has already verified:
const admin = await storeware.authenticateAdmin(request);
const ids = admin.claims.context.selection ?? [];A list's actions act on the rows ticked on the page. When a merchant chooses every row that matches across pages, the Apps button is off: those rows were never sent to the browser.
When your action is done, close the window with modal.close from App Bridge. The merchant can always close it themselves.
Actions on a record
An action at a .detail.action point is listed in the record's Apps menu, at the top of the page, with your app's name beside it. It opens your page in a window with the record's id in context, and closes the same way.
The frame
- Your page is cross origin and sandboxed: it cannot reach the admin's cookies or page.
- Every panel and window is labelled with your app's name, so a merchant can always tell your page from Storeware's.
- Talk to the admin with
postMessageto its exact origin, never*, and check the origin of everything you receive. App Bridge does both. - Send your session token on calls to your own server, rather than setting cookies, which a framed page may not keep.
- A panel's height follows what you ask for, between 80 and 1200 pixels.