Overview
Embedded analytics lets you mount Go Fig dashboards inside your own application as an iframe. Each of your customers signs in to your product. The embed shows them their own dashboards and only their own rows. You never expose a Go Fig login, and one customer can never see another customer’s data. The flow is always the same three steps:- On your server, mint a short-lived token that names which of your customers is viewing and whether they may edit.
- Exchange the token for a handshake URL and drop that URL into the iframe’s
src. - On first load the embed swaps the token for a cookie and cleans it out of the URL, so the credential never rides a later request.
Embedded analytics is provisioned per team. Ask Go Fig support to enable an
Embedded team for your organization. You configure the rest in the setup wizard
described below.
Roles
Every token carries exactly one role.
A viewer reads the team’s shared template project. An editor gets a private project of
their own, keyed on the tenant identifier in their token so two editors from two of your
customers never share a workspace.
Setup in the wizard
Open the embedded setup wizard for your team (Embedded → Setup). It walks four steps:- Multitenant: declare the identity claims your tokens carry and pick which one is the tenant identifier (the claim that names one of your customers). This is the key your row filters and private-project routing hang on.
- Data: choose which tables the embed may expose and, per table, the filter column and the token claim whose value it must match. This is what scopes rows to a tenant (see Data isolation).
- Test: preview the embed as any tenant/role using the built-in picker.
- Deploy: register the origins allowed to frame your embed and copy your client API key and iframe snippet.
Registering embed origins
The embed refuses to render in a frame unless the framing page’s origin is on your allowlist. This is enforced with a per-customerframe-ancestors Content-Security-Policy
directive.
- Add each origin you embed from, e.g.
https://app.acme.com. - An empty allowlist refuses all framing (
frame-ancestors 'none'). This is the conservative default. A missing origin surfaces during setup, not in production.
Minting a token
Tokens are minted server-side. Never mint a token in the browser: minting requires your client API key, which must stay on your server.POST /embedded/api/token with your API key. Authenticate with an Authorization: Bearer
header, an X-API-Key header, or an api_key field.
account_id above) are the identity claims you enabled in the wizard.
The tenant identifier claim is required. A request that omits it is refused with a
400, never issued a token that cannot be scoped.
The response carries the token and, more usefully, the handshake URL to drop into your
iframe:
Embedding the iframe
Set the iframesrc to the embedded_url from the token response:
src) and never again.
The framing page’s origin must be on your embed-origin allowlist (see
Registering embed origins), or the browser refuses to render
the frame.
Data isolation
Isolation runs at two levels, and both matter. Project level. A viewer reads the team’s shared template project. An editor gets a private project keyed on their tenant identifier so editors from different customers never share a workspace. Row level. Within a shared dashboard, the tenant row filter you configure in the wizard narrows every widget’s query to the rows belonging to the viewing tenant. For each table you gave a filter column and a token claim, the embed ANDscolumn == token[claim] onto the query before it runs. Two tenants viewing the same widget
see two different result sets, and their cached results are keyed separately so one tenant
can never read another’s bytes.
The filter is fail-closed: any configuration that cannot be satisfied returns zero
rows, never every tenant’s rows. A token that is missing its tenant claim, or missing a
claim a configured filter needs, produces an empty result rather than a leak.
Rate limits
Each tenant has its own request budget so one of your customers cannot starve another sharing the same embed. Viewers and editors carry independent sustained and burst limits, configurable per team. A tenant that exceeds either limit receives a429. Other tenants
are unaffected.

