Embedding a live dashboard in your SaaS takes four steps: connect your database, build the dashboard, generate a signed JWT that scopes data to the current tenant, and drop an iframe into your frontend. The whole thing can ship in a day if you skip the part where you build a BI tool from scratch. Here's the exact code.
What does the architecture look like?
┌─────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Your SaaS │ ──→ │ Your API │ ──→ │ Fastero │ ──→ │ Your DB │
│ Frontend │ │ (JWT mint) │ │ (dashboard) │ │ (Postgres, │
│ │ │ │ │ │ │ MySQL...) │
└─────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
│ │
│ <iframe> or fetch() │
└─────────────────────────────────────────┘Your backend mints a JWT containing the tenant ID and row-level filters. Your frontend passes that JWT to Fastero's embedded analytics layer — either as a query parameter on an iframe URL or as a Bearer token on an API call. Fastero validates the token, runs the query scoped to that tenant's data, and returns the result.
No separate login for your customers. No second auth flow.
Step 1: How do you connect your database?
Point Fastero at your existing database — Postgres, MySQL, Snowflake, BigQuery, whatever you're running. You need a read-only connection string (if your database sits behind a VPN, use an SSH tunnel). Create a dedicated read-only user for analytics queries — don't share your app's connection pool with dashboard traffic.
Fastero
Connect your database. Ask questions. Get dashboards.
Postgres, BigQuery, Snowflake, and 10+ sources — live-connected, AI-powered, no dashboard builder learning curve.
Try free →Step 2: How do you build the dashboard?
Create a dashboard in Fastero and add widgets backed by SQL queries. Use your real tables:
SELECT
date_trunc('month', e.created_at) AS month,
count(*) AS event_count,
count(DISTINCT e.user_id) AS active_users
FROM events e
WHERE e.org_id = :tenant_id
AND e.created_at >= now() - interval '6 months'
GROUP BY 1
ORDER BY 1;The :tenant_id parameter gets injected from the JWT automatically. Write the query once — it works for every customer.
Don't want to write SQL? Fastero's NL-to-SQL generates it from plain English. Ask "show monthly active users by org" and pin the result to a widget.
Step 3: How do you set up tenant-isolated auth?
This is the step that burns weeks on custom builds. Row-level security, token management, permission mapping. With Fastero, you mint a JWT on your backend:
// backend/routes/analytics.js
const jwt = require('jsonwebtoken');
app.get('/api/analytics/embed-token', auth, (req, res) => {
const token = jwt.sign(
{
tenant_id: req.user.organizationId,
role: req.user.role, // 'admin' | 'viewer'
filters: {
region: req.user.region, // row-level filtering
team_id: req.user.teamId
}
},
process.env.FASTERO_EMBED_SECRET,
{ expiresIn: '1h' }
);
res.json({ token });
});The filters object is the row-level security layer. An admin sees all regions. A regional manager sees only theirs. These filters get applied at the SQL level — in the WHERE clause before any data leaves the database, not in JavaScript after the fact.
Step 4: How do you embed the dashboard?
Option A: iframe (10 minutes)
Fetch the token from your backend and inject it into the iframe URL:
<iframe
id="analytics-dash"
src="https://app.fastero.com/embed/dashboard/dash_9f3k2m
?token=PLACEHOLDER
&theme=light
&hide_header=true"
width="100%"
height="600"
frameborder="0"
style="border: none; border-radius: 8px;"
></iframe>
<script>
fetch('/api/analytics/embed-token')
.then(r => r.json())
.then(({ token }) => {
const el = document.getElementById('analytics-dash');
el.src = el.src.replace('PLACEHOLDER', token);
});
</script>theme=light matches your product's appearance. hide_header=true strips Fastero's navigation so the dashboard looks native. Your customers see your brand, not a third-party tool.
Option B: API (full control)
Pull raw data and render with your own React components:
curl -X POST https://api.fastero.com/v1/query/results \
-H "Authorization: Bearer YOUR_EMBED_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"dashboard_id": "dash_9f3k2m",
"widget_id": "monthly_usage",
"cache_ttl": 300
}'The response is rows and columns in JSON. Render it with Recharts, Chart.js, a plain <table> — you own the pixels. Same tenant isolation, same row-level filtering. The API and webhooks docs cover pagination, scheduled refresh, and webhook subscriptions for data-change events.
What about keeping dashboards fresh?
Set a refresh schedule in Fastero — every 15 minutes, hourly, whatever matches your data velocity. The cache warms in the background so customers see sub-second load times, not a spinner.
You can also trigger refreshes on writes. Customer uploads a file? Fire a webhook. Dashboard updates within seconds. For the full pattern on event-driven refresh, see how to set up automated SQL alerts.
How does this compare to doing it yourself?
The honest math:
| Approach | Time to ship | Per-viewer cost | Row-level security | White-labeling |
|---|---|---|---|---|
| Custom (D3/Recharts) | 3-6 months | $0 (eng time) | Build it yourself | Full control |
| Metabase Embedded | 1-2 days | ~$85/user/mo (Pro) | Signed URL params | Limited theming |
| Fastero Embedded | 1 day | Flat rate | JWT + query-level | Full (CSS, logo, domain) |
The custom path gives you control but pulls your team off the core product for months. Metabase is fast to ship, but at $85/user the cost scales against you — 200 customers with analytics access is $17,000/month just for the embed layer. Fastero's flat pricing means unit economics improve as you grow.
For a broader comparison across the vendor landscape, the best embedded analytics platforms page covers pricing and tradeoffs side by side.
How does the full auth flow work?
Customer logs into your SaaS
│
▼
Your backend mints JWT
(tenant_id + role + filters)
│
▼
┌─────────┴──────────┐
│ │
▼ ▼
iframe API call
(embed URL (fetch JSON,
+ token) render in React)
│ │
└─────────┬──────────┘
│
▼
Fastero validates JWT,
applies row-level filters,
runs query against your DB
│
▼
Customer sees their data
(and only their data)No data leaves your database in unscoped form. The JWT is the security boundary, enforced server-side before any query executes. For the build-vs-buy decision and auth patterns, see adding customer-facing analytics to your SaaS. For pricing models and monetization, see embedding live dashboards without the per-viewer bill.
FAQ
Can I white-label the embedded dashboard completely?
Yes. Custom CSS, your logo, your color palette, and hide_header=true to strip Fastero's navigation. Your customers see your product's brand. On paid plans, you can serve the embed from a custom subdomain too.
What happens when the JWT expires?
The iframe shows a session-expired state. Your frontend should fetch a fresh token and update the iframe src — a few lines of JavaScript, shown in the embed snippet above. We recommend a 1-hour expiry for the right balance of security and UX.
Can different customer tiers see different dashboards?
Use the role field in the JWT. Your backend controls which dashboard ID gets embedded based on the customer's plan. Free tier gets a summary widget. Pro tier gets drill-down, filtering, and export. The routing logic lives in your code, not in Fastero's config.
Will scheduled refreshes overload my database?
Each refresh runs the dashboard's queries against your DB. Use a read replica if load is a concern, and set cache_ttl to match your freshness needs. A 15-minute cache means at most 4 queries per hour per dashboard — most production databases won't notice.
Does this work with a data warehouse instead of my production database? Yes. Fastero connects to BigQuery, Snowflake, Redshift, and 20+ other sources. If your analytics data already lives in a warehouse, point the dashboard queries there and keep your production DB out of the loop entirely.
Try Fastero free — embed tenant-isolated dashboards in your SaaS this week, not next quarter. No credit card required.

