Skip to content
Joe BI Platform
Esc
navigateopen⌘Jpreview
On this page

Merchant Manager embed integration

Exact migration steps for replacing a Looker iframe with Joe's shop-locked Metabase embed API or stable links.

Merchant Manager embed integration

Merchant Manager has two supported ways to replace a Looker iframe. Prefer the authenticated API for an interactive signed-in product. Use a signed /e/ URL when the browser cannot attach a bearer token, such as a no-login email destination or a directly assigned iframe src.

Option 1: authenticated product iframe

  1. On the Merchant Manager server, mint the normal short-lived Joe control-plane JWT. Its shopIds claim must contain the canonical shop UUID and its audience must be joe-data-plane.

  2. Server-side, call:

    GET https://data-plane.joe.coffee/v1/embed/reports/shop_sales?shopId=<shop-uuid>
    Authorization: Bearer <control-plane-jwt>
  3. Return only data.iframeUrl and data.expiresAt to the Merchant Manager browser.

  4. Replace the Looker iframe src with data.iframeUrl.

  5. Refetch shortly before expiresAt or after an iframe authorization failure. Do not edit Metabase query parameters.

Merchant browser        Merchant Manager server       Joe data plane             Metabase
       |                           |                         |                         |
       | request shop report      |                         |                         |
       |-------------------------->|                         |                         |
       |                           | GET /v1/embed/reports   |                         |
       |                           | Authorization: Bearer   |                         |
       |                           |------------------------>| verify JWT + shopIds    |
       |                           |                         | mint 10-minute JWT      |
       |                           |<------------------------| iframeUrl, expiresAt     |
       |<--------------------------| iframeUrl               |                         |
       | GET iframeUrl -------------------------------------------------------------->|
       |<---------------------------------------------------------------------------- dashboard

Auth requirement: the /v1/embed/reports/:key request requires a valid data-plane bearer. For control-plane users, assertShopAccess rejects a shop UUID absent from shopIds. Do not expose a service token in browser JavaScript.

Option 2: stable /e/ URL

Use one of these as the navigation target or iframe src:

# Authenticated viewer; access is checked on every click
https://data-plane.joe.coffee/e/shop_sales/<shop-uuid>

# No-login recipient; generate this in /v1/reports/admin
https://data-plane.joe.coffee/e/shop_sales/<shop-uuid>?exp=<unix-seconds>&sig=<signature>

The data plane verifies access or the signature, confirms the shop exists, mints a fresh 10-minute Metabase token, and redirects. Merchant Manager must preserve the complete signed query string and must not add shop names or Metabase filters.

Merchant browser                 Joe data plane                         Metabase
       |                               |                                   |
       | GET /e/shop_sales/<uuid>      |                                   |
       |------------------------------>| verify user or sig + shop          |
       |                               | mint 10-minute Metabase JWT         |
       |<------------------------------| 302 Location: /embed/dashboard/... |
       | GET signed embed ------------------------------------------------>|
       |<------------------------------------------------------------------ dashboard

Auth requirement: a plain /e/ URL needs a request credential that requireUser accepts and, for a control-plane JWT, access to the requested shop. A sig URL needs no session; the signature is the credential until its optional exp timestamp. Because ordinary iframe navigation cannot attach an Authorization header, use the authenticated API flow or a signed /e/ link instead of placing a plain /e/ URL in an iframe.

Migration checklist

  • Replace the Looker question/dashboard URL; do not retain Looker filter parameters.
  • Resolve and pass the canonical shop UUID, never a shop name.
  • Keep bearer-token calls server-to-server.
  • Handle 403 as expired/unauthorized and 404 as unavailable without showing internal configuration detail.
  • For signed links, choose the shortest practical 7/30/90-day lifetime and regenerate rather than modifying the URL.
  • Verify two shops cannot open each other’s dashboard before rollout.

Was this page helpful?