How to embed Metabase charts into your SaaS product workflow

So your customers want analytics, but you don’t want to reinvent the wheel. Maybe you’re already using Metabase to crunch numbers and build dashboards internally. Good news: you can actually embed those same charts and dashboards right inside your SaaS app—no need to build a whole reporting system from scratch. This guide walks through how to do it, what to watch out for, and where things can get messy.

This is for product engineers, full-stack devs, or technical founders who want to actually get this working—fast, secure, and without marketing fluff. Let’s dig in.


1. Decide What You Actually Need to Embed

Before you start, get clear on what you want your users to see:

  • Single chart or full dashboard? Embedding a simple bar chart is way easier than a whole dashboard with filters.
  • Static analytics or user-specific data? Do you want every user to see the same thing, or should the data change based on who's logged in?
  • Interactivity? Will users drill down, filter, or just view?

Pro tip: Start small. Embedding one chart is a lot easier to debug than rolling out an entire analytics suite at once.


2. Get Your Metabase Instance Ready

You’ll need admin access to your Metabase server. If you don’t have one running, get that going first and connect it to your data source.

  • Self-hosted or Metabase Cloud? Embedding works with both, but your setup steps might differ a bit.
  • SSL matters. If your app is HTTPS, your Metabase instance should be too, or browsers will complain and block embeds.
  • Permissions: Make sure the charts/dashboards you want to embed are accessible to the account you’ll use for embedding.

Gotcha: Don’t use your admin account’s credentials for embedding—set up a service user with only the access you need.


3. Choose an Embedding Option: Public or Signed?

Metabase offers two main ways to embed charts:

A. Public Embeds (Easiest, but Kind of Open)

  • How it works: You make a question or dashboard public, and Metabase gives you an iframe code.
  • Security: Anyone with the link can see the data. No authentication, no user-level filtering.
  • Use case: Fine for low-stakes info or internal tools, but risky for anything sensitive.

How to do it:

  1. In Metabase, go to the chart or dashboard.
  2. Click the sharing/embedding icon.
  3. Enable “Public sharing.”
  4. Copy the iframe code and paste it into your app.

What to watch out for:
If your app is public, anyone can view the chart—even if they’re not logged in. This is a dealbreaker for most SaaS scenarios.


B. Signed Embeds (Secure, and What You Probably Want)

  • How it works: You generate a signed JWT token on your server that tells Metabase who the user is and what data they can see.
  • Security: Much better. You control exactly what each user sees.
  • Use case: For any production SaaS workflow where data privacy matters.

How to do it:

  1. Enable embedding in Metabase:
  2. Go to Admin > Settings > Embedding.
  3. Turn on “Embedding in other applications.”
  4. Copy the “Embedding secret key.”

  5. On your backend, generate a signed JWT:

  6. The token includes info like which dashboard to show, optional user attributes (for row-level security), and expiration.

Example (Node.js with jsonwebtoken):

js const jwt = require('jsonwebtoken');

const METABASE_SITE_URL = "https://your-metabase.example.com"; const METABASE_SECRET_KEY = "your-metabase-secret-key"; const payload = { resource: { dashboard: 1 }, // or { question: 5 } params: { user_id: 123 }, // optional, for row-level permissions exp: Math.round(Date.now() / 1000) + (10 * 60) // expires in 10 mins };

const token = jwt.sign(payload, METABASE_SECRET_KEY); const iframeUrl = ${METABASE_SITE_URL}/embed/dashboard/${token}#bordered=true&titled=true;

  1. Embed the iframe in your frontend: html

What doesn’t work:
Don’t try to generate the JWT in the browser—it exposes your secret key. Always do this server-side.

Pro tip:
JWT expiration time matters. Too short, and your users get logged out of charts; too long, and you risk stale permissions if accounts change.


4. Handle Row-Level Security (User-Specific Data)

If you want each user to only see their data, you need to set up row-level permissions in Metabase.

  • Define parameters in your charts: When building a question, use a variable like {{user_id}} in your SQL.
  • Pass params in your JWT: When generating the JWT, include params: { user_id: whatever }.
  • Metabase swaps in the value: The chart only shows rows where user_id matches.

Pitfalls: - If you forget to add the parameter in both your chart and JWT, users will see either nothing or everything. - Don’t use sensitive info (like emails) as parameters unless you’re sure it’s safe.


5. Polish the Embedded Experience

A raw iframe usually looks like… a raw iframe. Take a few minutes to make your charts feel native:

  • Size: Set width and height to match your layout. Metabase iframes don’t auto-resize.
  • Hide controls: Add #bordered=false&titled=false to the iframe URL if you want a cleaner look.
  • Responsiveness: Use CSS to make iframes responsive, but don’t expect miracles—Metabase isn’t built for mobile-first embeds.
  • Loading: Show a skeleton or spinner while the chart loads, especially if Metabase is slow.

What to ignore:
Trying to restyle Metabase charts via CSS in your app. The iframe is sandboxed—you can’t mess with its styles.


6. Secure Your Setup

Don’t skimp here. Some common mistakes:

  • Never expose your secret key anywhere on the client.
  • Same-origin policies: If your Metabase and app are on different domains, check CORS and X-Frame-Options settings.
  • Audit permissions: Only allow the embedding user to see exactly what’s needed—nothing more.
  • Regularly rotate your secret key if possible, and monitor for unauthorized embeds.

7. Test, Test, Test

Before rolling out to customers:

  • Try with different users: Make sure data filters work as expected.
  • Test on slow connections: Metabase can be laggy on big dashboards—watch for timeouts.
  • Mobile: If your app is mobile-first, embedding might not be the best fit.

Heads-up:
Metabase upgrades can break embeds. Always test after updates.


8. When Not To Embed (and Alternatives)

Embedding Metabase is great for:

  • Fast analytics features without heavy dev time.
  • Internal dashboards you want outside the Metabase UI.

But it’s not magic:

  • Custom branding: You can’t fully reskin Metabase in an iframe.
  • Deep UX integration: If you need fancy interactions, or seamless blending with your app’s style, you’ll hit walls.
  • Performance: Heavy queries = slow loads.

Alternatives:
If you outgrow Metabase embeds, look at options like building your own front-end with chart libraries (Chart.js, Plotly, etc.), or using a more extensible BI tool with a real SDK.


Keep It Simple and Iterate

Don’t get sucked into endless customization. Start with a simple embedded chart, make sure it’s secure, and see how users react. If they want more, add dashboards or filters later. If the approach hits a wall, you’ll know before you’ve sunk a month into it.

Embedding Metabase isn’t perfect, but for most SaaS teams, it’s a huge shortcut. Just keep your setup lean, your secrets safe, and don’t be afraid to rip it out if it stops working for your needs.