Building Customer-Facing Dashboards with the Apache Superset Embedded SDK
Learn how to embed Apache Superset dashboards into your SaaS product. Step-by-step guide covering SDK setup, authentication, and production deployment.
What Is the Apache Superset Embedded SDK?
The Apache Superset Embedded SDK is a lightweight JavaScript library that lets you drop fully functional dashboards directly into your application without forcing users to navigate to a separate BI tool. Instead of sending customers to a Looker or Tableau instance, you’re embedding rich, interactive analytics natively—inside your product, under your brand, with your data.
This isn’t iframe embedding at its crudest. The Superset Embedded SDK gives you programmatic control over dashboards: you can set filter values from your application state, listen to dashboard events, manage authentication tokens, and customize the visual experience. It’s built on the same proven architecture that powers Preset’s embedding features, which is itself built on Apache Superset.
For SaaS teams, this matters because embedded analytics directly reduces churn. When your customer can see their KPIs, usage metrics, or performance data without leaving your product, they’re more engaged, more likely to renew, and more likely to expand. You’re not just offering a dashboard—you’re offering visibility into the value they’re getting.
The SDK handles the complexity: guest token generation, secure iframe communication, filter synchronization, and responsive layout. You focus on the user experience and business logic.
Why Embedded Analytics Changes the Game for SaaS
Traditional BI platforms like Looker, Tableau, and Power BI are designed for internal analytics teams. You buy a seat, you get access to a dedicated BI interface, and you explore data there. That architecture works fine when your users are analysts. It breaks down when your users are customers who just want to see their own data in context.
Embedded analytics flips the model. Instead of customers logging into a separate tool, the analytics live where the work happens—in your application. This shifts several key metrics:
Time to insight: A customer doesn’t navigate to a new tab, log in, find the right dashboard, and wait for it to load. They click a “Reports” tab and see live data in milliseconds.
Feature adoption: Self-serve BI embedded in your product naturally drives higher adoption than a bolted-on external tool. The friction is gone.
Retention: Customers who can see their metrics are less likely to churn. Visibility is a retention driver.
Competitive positioning: If your competitor requires customers to use an external BI tool, and you embed analytics natively, you’ve won a UX battle.
The Apache Superset Embedded SDK makes this achievable without building a custom analytics engine from scratch. Superset is open-source, battle-tested, and built for exactly this use case. You get production-grade SQL query execution, caching, data connectors, and visualization libraries—all available to embed.
Compared to building a custom solution or licensing Tableau/Looker embedded (which can cost $10K–$100K+ per month depending on usage), the Superset path is dramatically cheaper and faster to ship.
Core Architecture: How the Embedded SDK Works
Before you write code, you need to understand the three-part architecture of Superset embedding:
The Superset Backend
Your Superset instance (whether self-hosted or managed through a service like D23) runs the core analytics engine. It connects to your data sources—PostgreSQL, Snowflake, BigQuery, whatever—and executes queries. It stores dashboard configurations, filters, and metadata.
The backend exposes a REST API. This is critical. When you embed a dashboard, your frontend doesn’t talk directly to your database. It talks to Superset, which handles authentication, query execution, caching, and row-level security.
You can explore the full API Reference - Apache Superset to understand all available endpoints. For embedding, the key endpoints are:
- Dashboard metadata and configuration retrieval
- Guest token generation (for secure, temporary access)
- Filter and parameter updates
- Query execution and result streaming
Guest Token Authentication
You can’t embed a dashboard and let anyone access it. You need authentication. But you also can’t require your customers to create Superset accounts.
Enter guest tokens. A guest token is a short-lived JWT that grants temporary, scoped access to specific dashboards and data. Your backend generates it, your frontend uses it to authenticate with Superset, and Superset validates it.
The flow looks like this:
- A customer logs into your SaaS app.
- Your backend receives the request and identifies the customer.
- Your backend calls the Superset API to generate a guest token scoped to that customer’s data (via filters or row-level security).
- Your frontend receives the token and passes it to the Embedded SDK.
- The SDK uses the token to authenticate all subsequent requests to Superset.
- The dashboard loads and displays only the data the customer is authorized to see.
Guest tokens are ephemeral—they expire after a set period (typically 15 minutes to 1 hour). This means even if a token is compromised, the window of exposure is small.
The Embedded SDK (Frontend)
The @superset-ui/embedded-sdk is an NPM package you install in your frontend application. It’s a thin wrapper around iframe communication and Superset’s REST API.
The SDK handles:
- Iframe initialization: Creates and configures the iframe that displays the dashboard.
- Token management: Accepts the guest token and manages its lifecycle.
- Filter synchronization: Lets you set dashboard filters from your app state and listen for filter changes.
- Event handling: Emits events when dashboards load, errors occur, or users interact with filters.
- Responsive layout: Adjusts the dashboard to fit your container.
You don’t need to understand the iframe plumbing. You just import the SDK, instantiate it with a dashboard ID and token, and it works.
Setting Up Your Superset Instance
Before you can embed, you need a Superset instance. You have three options:
Option 1: Self-Hosted Superset
You run Superset on your own infrastructure (Docker, Kubernetes, etc.). You control everything: data connections, security policies, scaling. You also own the operational burden: upgrades, monitoring, backups, and scaling.
For a SaaS team, self-hosting makes sense if you have dedicated DevOps resources and need maximum control. For most teams, it’s overhead.
Option 2: Managed Superset (D23)
D23 is a managed Superset platform purpose-built for SaaS teams. You don’t manage infrastructure. You connect your data sources, build dashboards, and embed them. D23 handles scaling, security, backups, and upgrades. It includes built-in support for text-to-SQL, MCP server integration, and API-first workflows.
For embedded analytics, managed Superset removes the operational complexity. You focus on the user experience, not the platform.
Option 3: Preset
Preset is a managed Superset service (acquired by Databricks). It offers similar benefits to self-hosted but with managed infrastructure. Preset has its own embedding documentation and SDKs, which largely mirror the open-source Superset approach.
For this guide, we’ll focus on the open-source Apache Superset SDK, which works with any Superset instance.
Step 1: Install and Configure the Embedded SDK
Assuming you have a Superset instance running and accessible, here’s how to embed a dashboard.
Install the NPM Package
First, install the SDK in your frontend project:
npm install @superset-ui/embedded-sdk
Or with yarn:
yarn add @superset-ui/embedded-sdk
The SDK is compatible with React, Vue, Angular, or vanilla JavaScript. We’ll focus on React, but the patterns apply elsewhere.
Create a Container and Initialize the SDK
In your React component, create a div to hold the dashboard:
import React, { useEffect } from 'react';
import { embedDashboard } from '@superset-ui/embedded-sdk';
function EmbeddedDashboard({ token, dashboardId, superset_url }) {
useEffect(() => {
embedDashboard({
id: dashboardId,
supersetDomain: superset_url,
mountPoint: document.getElementById('dashboard-container'),
fetchGuestToken: () => Promise.resolve(token),
dashboardUiConfig: {
hideTitle: false,
hideCharts: false,
hideFilters: false,
},
});
}, [token, dashboardId, superset_url]);
return <div id="dashboard-container" style={{ height: '100vh' }} />;
}
export default EmbeddedDashboard;
Let’s break this down:
id: The dashboard ID from your Superset instance.supersetDomain: The URL of your Superset instance (e.g.,https://superset.yourcompany.com).mountPoint: The DOM element where the dashboard will render.fetchGuestToken: A function that returns the guest token. This is called when the SDK needs to authenticate.dashboardUiConfig: Options to show or hide UI elements (title, charts, filters, etc.).
For more details on configuration options, check the superset-embedded-sdk README.md at master - GitHub.
Step 2: Generate Guest Tokens
Guest tokens are the security layer. Your backend generates them, your frontend uses them. Here’s how.
Backend: Token Generation
Your backend needs to call the Superset API to generate a guest token. Here’s a Node.js example:
const axios = require('axios');
async function generateGuestToken(customerId, supersetUrl, adminUsername, adminPassword) {
// Step 1: Get an admin access token
const loginResponse = await axios.post(`${supersetUrl}/api/v1/security/login`, {
username: adminUsername,
password: adminPassword,
});
const adminToken = loginResponse.data.access_token;
// Step 2: Generate a guest token scoped to the customer
const guestTokenResponse = await axios.post(
`${supersetUrl}/api/v1/security/guest_token/`,
{
username: `guest_${customerId}`,
first_name: 'Guest',
last_name: 'User',
resources: [
{
type: 'dashboard',
id: 'your-dashboard-id', // The dashboard you're embedding
},
],
rls: [
{
clause: `customer_id = '${customerId}'`, // Row-level security filter
},
],
},
{
headers: {
Authorization: `Bearer ${adminToken}`,
},
}
);
return guestTokenResponse.data.token;
}
This code:
- Authenticates as an admin user (you’ll store admin credentials securely, e.g., in environment variables).
- Calls the guest token endpoint with the customer ID and RLS (row-level security) filters.
- Returns the guest token.
The RLS clause ensures the guest only sees data for their customer. If your data model has a customer_id column, you set clause: "customer_id = '${customerId}'". Superset automatically applies this filter to all queries.
For the full API details, see the API Reference - Apache Superset.
Frontend: Using the Token
Your frontend calls your backend to get the token, then passes it to the SDK:
async function fetchGuestToken() {
const response = await fetch('/api/superset-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ customerId: currentCustomerId }),
});
const data = await response.json();
return data.token;
}
Then pass this function to embedDashboard:
embedDashboard({
id: dashboardId,
supersetDomain: superset_url,
mountPoint: document.getElementById('dashboard-container'),
fetchGuestToken: fetchGuestToken,
});
The SDK will call fetchGuestToken() whenever it needs to authenticate.
Step 3: Manage Filters and Interactivity
Embedded dashboards aren’t static. You want to let customers filter by their own criteria, and you want to sync filters between your app and the dashboard.
Setting Filters Programmatically
The SDK provides an api object that lets you interact with the dashboard after it loads:
let dashboardApi;
embedDashboard({
id: dashboardId,
supersetDomain: superset_url,
mountPoint: document.getElementById('dashboard-container'),
fetchGuestToken: fetchGuestToken,
onLoad: (api) => {
dashboardApi = api; // Store the API for later use
},
});
// Later, when the user changes a filter in your app:
function handleDateRangeChange(startDate, endDate) {
dashboardApi.setFilterValues({
date_range: `${startDate} : ${endDate}`,
});
}
The setFilterValues() method updates the dashboard filters and re-executes queries.
Listening to Dashboard Events
You can also listen for events from the dashboard:
embedDashboard({
// ... other config
onLoad: (api) => {
// Listen for filter changes
api.addEventListener('filter_changed', (event) => {
console.log('Filters changed:', event.detail);
// Update your app state if needed
});
// Listen for errors
api.addEventListener('error', (event) => {
console.error('Dashboard error:', event.detail);
});
},
});
This two-way communication keeps your app and the dashboard in sync.
Step 4: Deployment and Security Considerations
Embedding dashboards in production requires careful attention to security and performance.
HTTPS and CORS
Your Superset instance must be accessible over HTTPS. Mixed content (HTTPS frontend, HTTP backend) will fail in modern browsers.
You’ll also need to configure CORS (Cross-Origin Resource Sharing) on your Superset instance to allow requests from your frontend domain. In Superset’s configuration, set:
SUPERSET_CORS_ORIGINS = [
'https://yourappdomain.com',
'https://www.yourappdomain.com',
]
For more on deployment specifics, the Step 2: Deployment - Dashboard Embedding - Preset Docs provides practical guidance.
Token Expiration and Refresh
Guest tokens expire. By default, they’re valid for 15 minutes. Your frontend needs to handle token refresh gracefully.
The SDK handles this automatically—when a token expires, it calls fetchGuestToken() again. Make sure your fetchGuestToken() function is efficient and doesn’t block the user experience.
Rate Limiting and Query Caching
Embedded dashboards can generate a lot of queries. If every customer loads the same dashboard, you’re executing the same queries repeatedly. Superset’s caching layer helps here.
Configure Superset’s query cache (usually Redis) and set appropriate cache expiration times. For dashboards that update hourly, a 5–10 minute cache is reasonable. For real-time dashboards, you might cache for 1 minute or disable caching entirely.
CACHE_CONFIG = {
'CACHE_TYPE': 'redis',
'CACHE_DEFAULT_TIMEOUT': 300, # 5 minutes
'CACHE_KEY_PREFIX': 'superset_',
'CACHE_REDIS_URL': 'redis://localhost:6379/0',
}
Data Privacy and Row-Level Security
Guest tokens with RLS filters ensure customers only see their data. But don’t rely on this alone. Always validate on the backend:
- The guest token was generated for the logged-in customer.
- The RLS filters in the token match the customer’s data scope.
- The dashboard being embedded is authorized for this customer.
This defense-in-depth approach prevents accidental or malicious data leaks.
For sensitive data, consider additional layers: IP whitelisting, request signing, or audit logging.
Step 5: Customizing the User Experience
The Embedded SDK offers UI customization options to match your brand and use case.
Dashboard UI Configuration
You can hide or show specific UI elements:
embedDashboard({
// ... other config
dashboardUiConfig: {
hideTitle: false, // Show the dashboard title
hideCharts: false, // Show all charts
hideFilters: false, // Show filter controls
hideDownloadCSV: false, // Allow CSV export
hideDownloadImage: false, // Allow image export
},
});
For white-label scenarios, you might hide the Superset branding and show only your own.
Responsive Design
Embedded dashboards need to work on mobile and desktop. The SDK handles responsive layout automatically, but you need to set the container size appropriately:
#dashboard-container {
width: 100%;
height: 100vh; /* Full viewport height */
overflow: hidden;
}
/* On mobile, adjust height to account for navigation */
@media (max-width: 768px) {
#dashboard-container {
height: calc(100vh - 60px); /* Subtract header height */
}
}
Custom Styling
You can’t directly style Superset charts from your app (they’re in an iframe), but you can:
- Customize the dashboard theme in Superset itself (colors, fonts, etc.).
- Adjust the iframe container styling in your app.
- Use Superset’s CSS variable support (in newer versions) for theme customization.
Real-World Example: Embedding Usage Analytics
Let’s walk through a concrete example: a SaaS product embedding customer usage analytics.
Scenario
You have a multi-tenant SaaS app. Each customer should see their own usage metrics: API calls, active users, feature usage, errors. You want to embed these in the customer’s dashboard without forcing them to log into a separate tool.
Implementation
Backend (Node.js/Express):
app.post('/api/superset-token', authenticateUser, async (req, res) => {
const customerId = req.user.customerId;
const supersetUrl = process.env.SUPERSET_URL;
const adminUser = process.env.SUPERSET_ADMIN_USER;
const adminPassword = process.env.SUPERSET_ADMIN_PASSWORD;
try {
const token = await generateGuestToken(
customerId,
supersetUrl,
adminUser,
adminPassword
);
res.json({ token });
} catch (error) {
res.status(500).json({ error: 'Failed to generate token' });
}
});
Frontend (React):
import React, { useState, useEffect } from 'react';
import { embedDashboard } from '@superset-ui/embedded-sdk';
function UsageAnalytics() {
const [dashboardApi, setDashboardApi] = useState(null);
const [dateRange, setDateRange] = useState('last_30_days');
useEffect(() => {
async function loadDashboard() {
const tokenResponse = await fetch('/api/superset-token', {
method: 'POST',
});
const { token } = await tokenResponse.json();
const api = await embedDashboard({
id: 'usage-analytics-dashboard',
supersetDomain: process.env.REACT_APP_SUPERSET_URL,
mountPoint: document.getElementById('dashboard'),
fetchGuestToken: () => Promise.resolve(token),
dashboardUiConfig: {
hideTitle: false,
hideFilters: false,
},
onLoad: (api) => {
setDashboardApi(api);
// Apply initial filter
api.setFilterValues({ date_range: dateRange });
},
});
}
loadDashboard();
}, []);
const handleDateRangeChange = (newRange) => {
setDateRange(newRange);
if (dashboardApi) {
dashboardApi.setFilterValues({ date_range: newRange });
}
};
return (
<div>
<div style={{ marginBottom: '20px' }}>
<label>Date Range: </label>
<select value={dateRange} onChange={(e) => handleDateRangeChange(e.target.value)}>
<option value="last_7_days">Last 7 Days</option>
<option value="last_30_days">Last 30 Days</option>
<option value="last_90_days">Last 90 Days</option>
</select>
</div>
<div id="dashboard" style={{ height: '600px' }} />
</div>
);
}
export default UsageAnalytics;
Superset Dashboard Setup:
- Connect Superset to your analytics database (PostgreSQL, Snowflake, etc.).
- Create a dataset from your
customer_usagetable. - Build charts: API calls over time, active users, feature adoption, error rates.
- Create a dashboard and add the charts.
- Add a
customer_idfilter to the dashboard. - Note the dashboard ID (visible in the URL:
/dashboard/{id}).
Guest Token RLS:
When generating the guest token, include:
rls: [
{
clause: `customer_id = '${customerId}'`,
},
]
This ensures the guest only sees data for their customer, even if they somehow manipulate the filter.
Result
Customers now see their usage analytics embedded in your product. They can filter by date range, drill into details, and export reports. You’ve reduced churn by making data visible and accessible.
Common Challenges and Solutions
Challenge 1: Slow Dashboard Load Times
Problem: Embedded dashboards take 10+ seconds to load.
Solutions:
- Enable Superset query caching (Redis).
- Optimize the underlying SQL queries (add indexes, materialize views).
- Use D23’s managed infrastructure, which includes query optimization and caching out of the box.
- Pre-aggregate data: instead of querying raw events, query pre-computed aggregates.
- Reduce the number of charts on the dashboard.
Challenge 2: Guest Token Expiration Issues
Problem: Dashboards stop working after 15 minutes.
Solution: Ensure your fetchGuestToken() function is always available and responsive. The SDK will call it automatically when a token expires. Test token refresh in your QA environment.
Challenge 3: Data Freshness vs. Performance
Problem: Customers expect real-time data, but queries are slow.
Solution:
- Use materialized views for pre-computed metrics.
- Implement incremental data refreshes (only update changed rows).
- Set cache TTL based on acceptable staleness (e.g., 1 minute for near-real-time).
- Communicate cache freshness to customers (“Data updates every 5 minutes”).
Challenge 4: Row-Level Security Complexity
Problem: Your data model has complex hierarchies (organization > team > user), and RLS filters are hard to manage.
Solution:
- Use Superset’s role-based access control (RBAC) and base permissions.
- Pre-compute RLS clauses in your backend based on the user’s role.
- For complex scenarios, consider a dedicated data warehouse with built-in RLS (e.g., Snowflake’s dynamic masking).
Challenge 5: Embedded Analytics Don’t Match Your Brand
Problem: The Superset UI doesn’t match your product’s design.
Solution:
- Customize the Superset theme (colors, fonts, logos) to match your brand.
- Use the
dashboardUiConfigto hide unnecessary UI elements. - Build a custom wrapper around the embedded dashboard with your own header, footer, and styling.
Advanced Patterns: Text-to-SQL and AI-Assisted Analytics
If you’re using D23 or a Superset instance with text-to-SQL capabilities, you can offer customers natural language query generation. Instead of pre-built dashboards, customers type questions like “Show me revenue by region for Q4” and the system generates the query.
This is more powerful than static dashboards but requires:
- A well-documented data schema.
- An LLM (large language model) to convert text to SQL.
- Query validation and safety checks.
Text-to-SQL integration with Superset is an advanced feature. If you’re interested, D23’s managed platform includes built-in text-to-SQL and MCP (Model Context Protocol) integration.
Comparing Embedded Superset to Alternatives
vs. Looker Embedded
Looker embedded is powerful but expensive: $10K–$100K+ per month depending on usage. Superset is open-source and free (you pay for hosting). For SaaS teams, Superset offers better economics.
vs. Tableau Embedded
Tableau embedded is similar to Looker: expensive and enterprise-focused. Superset is more accessible and developer-friendly.
vs. Metabase Embedded
Metabase offers embedding, but it’s less mature than Superset for production SaaS use cases. Superset has more features, better performance, and a larger community.
vs. Mode Embedded
Mode is a collaborative analytics platform with embedding capabilities. It’s good for internal analytics but less optimized for customer-facing dashboards.
vs. Hex Embedded
Hex is newer and focused on interactive notebooks. It’s not as mature as Superset for embedded analytics at scale.
Bottom line: For cost, flexibility, and feature completeness, Superset is the strongest choice for embedded analytics in SaaS.
Best Practices for Production Embedding
1. Separate Dashboards by Tenant
Create one dashboard per customer or use a single dashboard with RLS filters. Separate dashboards give you more control but higher maintenance. RLS filters are more scalable.
2. Monitor Performance
Track:
- Dashboard load times
- Query execution times
- Cache hit rates
- Error rates
Use Superset’s built-in metrics or integrate with your monitoring stack (Datadog, New Relic, etc.).
3. Plan for Scale
Embedded analytics can generate significant query load. As you scale:
- Upgrade your Superset infrastructure (more CPU, memory).
- Increase database resources.
- Implement caching aggressively.
- Consider a dedicated analytics database (separate from your transactional database).
4. Document Your Dashboards
For customers and internal teams, document:
- What data each dashboard shows
- How often data is refreshed
- How to interpret metrics
- Known limitations or caveats
5. Gather Customer Feedback
Embedded dashboards are part of your product. Treat them like any other feature:
- Collect feedback from customers.
- Track which dashboards are used most.
- Iterate based on usage patterns.
- Communicate updates and changes.
Getting Started with Embedded Superset
Here’s a quick checklist to get from zero to embedded dashboards:
- Set up Superset: Use a managed service like D23 or self-host.
- Connect your data: Add your database as a data source.
- Build dashboards: Create charts and dashboards in Superset.
- Install the SDK:
npm install @superset-ui/embedded-sdk. - Generate guest tokens: Set up your backend to generate tokens with RLS filters.
- Embed dashboards: Use the SDK to embed in your frontend.
- Test thoroughly: Verify authentication, filters, performance, and data accuracy.
- Deploy: Roll out to customers gradually; monitor for issues.
- Iterate: Gather feedback and improve dashboards based on usage.
The entire process—from setup to first embedded dashboard—typically takes 2–4 weeks for a small team with existing data infrastructure.
Conclusion
Embedded analytics with the Apache Superset Embedded SDK is a proven way to reduce churn, increase engagement, and differentiate your SaaS product. Unlike licensing Looker or Tableau, Superset gives you cost-effective, flexible, developer-friendly embedding that scales with your business.
The technical barrier is low: the SDK is well-documented, the API is straightforward, and the security model (guest tokens + RLS) is sound. The main work is in data modeling, dashboard design, and operational planning.
If you’re evaluating embedded analytics options, Superset deserves serious consideration. And if you want to skip the operational overhead, D23 offers managed Superset with additional features like text-to-SQL and MCP integration, purpose-built for SaaS teams.
Start small: embed one dashboard for one customer segment. Measure the impact on engagement and retention. Scale from there. The ROI compounds as you expand embedded analytics across your product.
For more technical details, refer to the Superset Embedded SDK README, the Embedding Preset Dashboards Into Your Application guide, and the @superset-ui/embedded-sdk NPM documentation. These resources cover implementation details, configuration options, and troubleshooting.
Your customers are waiting for analytics. Embed them.