FFastero

Connect any database. Ask in plain English.

Try free
Back to blog

Blog article

How to Embed Live Dashboards in Your SaaS — Step by Step

A step-by-step tutorial for embedding live, tenant-isolated dashboards in your SaaS product using iframe embeds, JWT auth, and API-served data — with code you can copy.

Fastero Dev TeamFastero Dev Team
2026-08-08
embedded-analyticssaasdashboardsiframeapitutorial
How to Embed Live Dashboards in Your SaaS — Step by Step

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.

Ready to try it yourself?

Connect your database, ask questions in plain English, and get live dashboards — in under 2 minutes. No credit card required.