iframe mode
Embed a trend dashboard with a plain iframe tag. The 5-minute integration.
The simplest way to embed a trend dashboard is a plain <iframe> tag. Two steps:
- Your backend mints a token via
POST /api/embed/token. - Your frontend renders
<iframe src="https://app.trend.dev/embed/dashboards/<id>?token=<jwe>">.
If your app is server-rendered (Rails, Django, Laravel, Next.js SSR), the mint happens in the same request that renders the page — no separate frontend fetch.
1. Get an API key
Embed → API keys → New API key. You’ll see the plaintext once; store it in your secrets manager as TREND_EMBED_API_KEY. Format: trnd_emb_<43 random chars>.
Warning
This key is a server-to-server credential. Never send it to the browser. If a browser could see it, an attacker could mint arbitrary tokens for any customer.
2. Mint a token (your backend)
POST https://app.trend.dev/api/embed/token
Authorization: Bearer trnd_emb_...
Content-Type: application/json
{
"externalId": "acme-corp",
"attributes": { "company_id": "acme-corp" }
}
Response:
{
"token": "eyJhbGciOiJkaXIi...",
"expiresAt": 1735939200
}
Node.js:
const res = await fetch('https://app.trend.dev/api/embed/token', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.TREND_EMBED_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
externalId: currentCustomer.id,
attributes: { company_id: currentCustomer.id },
}),
})
const { token } = await res.json()
Python:
import os, requests
res = requests.post(
"https://app.trend.dev/api/embed/token",
headers={
"Authorization": f"Bearer {os.environ['TREND_EMBED_API_KEY']}",
"Content-Type": "application/json",
},
json={
"externalId": current_customer.id,
"attributes": {"company_id": current_customer.id},
},
)
token = res.json()["token"]
3. Render the iframe (your frontend)
<iframe
src="https://app.trend.dev/embed/dashboards/<DASHBOARD_UUID>?token=<TOKEN>"
width="100%"
height="600"
frameborder="0"
></iframe>
Get the dashboard UUID from the dashboard’s ellipsis menu once you’ve toggled Embed on.
Token lifetime
Tokens are valid for 1 hour from mint. Two ways to handle expiry:
- Mint per pageview (simplest). Your backend mints a fresh token every time the parent page loads. Zero session state.
- Cache + refresh (higher-traffic). Cache the token per customer for ~50 minutes, mint a fresh one before it expires.
Either way, when a token expires, the iframe shows an "Invalid or expired embed token" page. Refresh the parent page — the fresh mint fixes it.
Prefilling variables from the URL
Any dashboard variable can be prefilled by appending var_<name>=<value> to the iframe URL:
<iframe
src="https://app.trend.dev/embed/dashboards/<uuid>?token=…&var_country=US&var_tier=premium"
width="100%" height="600"
></iframe>
Values that look like JSON arrays (e.g. ["a","b"]) parse as arrays; everything else stays as a string. For live filter updates from a parent SPA without reloading, use the web component — iframes can't take runtime attribute changes.
Demo customers (free, watermarked)
Any customer toggled to Demo in Embed → Customers → Registered is excluded from billing AND renders with a diagonal "DEMO" watermark across every chart. Use for sales demos, dev/QA environments, or internal previews. Details: Overview → Pricing.
Error paths
| Error | Cause | Fix |
|---|---|---|
401 Invalid API key | API key wrong / revoked | Regenerate in Embed → API keys |
403 Embed is not enabled for this workspace | Workspace lost the embed feature flag | Check billing |
404 Dashboard not found | Dashboard doesn’t exist, doesn’t belong to the workspace, or embed_enabled is off | Toggle Embed on the dashboard |
400 Missing required attributes: X | A dataset in the dashboard references {{trend.attributes.X}} but the token didn’t supply X | Add the attribute to your mint call |
What to read next
- Web component mode — the
<trend-dashboard>custom element, better for SPAs. - Per-customer attributes — the safety semantics for
{{trend.attributes.*}}.