Tableau Embedded Analytics: Adding Interactive Dashboards to Your Web App
Your users deserve better than a screenshot of a chart emailed every Monday — here's how to give them live, interactive Tableau dashboards inside the product they already use.
Multivak Labs
Engineering Team
Somewhere in your organisation, right now, someone is exporting a Tableau dashboard to PDF, attaching it to an email, and sending it to a client who will glance at it once before filing it in the same mental drawer as their gym membership renewal notice. Meanwhile, you have a perfectly good web application that your users actually log into every day — and it has zero interactive analytics.
Tableau Embedded Analytics fixes this by letting you drop live, filterable, clickable dashboards directly into your web app. No PDFs. No screenshots. No "please see the attached." Your users get analytics where they already work, and you get to stop pretending that a static export counts as "data-driven decision making."
This guide walks you through everything: what the Embedding API v3 actually is, how authentication works, the code to get a dashboard rendering in your app, the pricing you need to budget for, the performance gotchas that will bite you if you ignore them, and a few things the official documentation is suspiciously quiet about.
What Is Tableau Embedded Analytics?
Tableau Embedded Analytics is the capability to integrate Tableau dashboards and visualisations directly into external web applications, portals, and products. Instead of your users navigating to a separate Tableau Server or Tableau Cloud URL, they interact with live dashboards inside your application's interface — same session, same context, no context-switching.
The core technology behind this is the Tableau Embedding API v3, which replaced the older JavaScript API v2 starting with Tableau 2021.4. The v3 API uses web components (specifically, custom HTML elements like <tableau-viz>) rather than the constructor-based approach of v2. This is not a cosmetic change — it fundamentally simplifies how you declare and configure embedded views.
There are four primary use cases for embedded analytics, and understanding which one you're building for will save you from over-engineering or under-engineering your implementation:
- Internal portals — Embedding dashboards into an intranet or internal tool so employees can view KPIs without leaving the app they use daily. The simplest case.
- Customer-facing products — Adding analytics as a feature of your SaaS product. Your customers see their own data, filtered by their tenant. This is where row-level security becomes non-negotiable.
- Partner and vendor portals — Giving external stakeholders controlled access to specific data slices. Think supplier performance dashboards or franchise reporting.
- White-labelled analytics — Embedding Tableau so deeply that the end user has no idea they're looking at Tableau. Your branding, your colours, your UI. Tableau is the engine; your product is the car.
The Embedding API v3: How It Actually Works
If you've worked with the old JavaScript API v2, the v3 API will feel like upgrading from hand-cranking a car engine to using a key fob. The fundamental shift is from imperative JavaScript to declarative web components.
Here's what a minimal embed looks like with the v3 API:
<script type="module" src="https://your-server.example.com/javascripts/api/tableau.embedding.3.latest.min.js"> </script> <tableau-viz id="tableauViz" src="https://your-server.example.com/views/Sales/Overview" toolbar="bottom" hide-tabs> </tableau-viz>
That's it. No new tableau.Viz() constructor, no container div you have to manually target, no callback spaghetti. The <tableau-viz> element is a native web component that handles its own lifecycle. You configure it with HTML attributes, and it renders the visualisation when the element mounts in the DOM.
For programmatic control — filtering, selecting marks, listening for events — you grab a reference to the element and call methods on it:
const viz = document.getElementById('tableauViz');
// Apply a filter
const sheet = viz.workbook.activeSheet;
await sheet.applyFilterAsync('Region', ['West', 'East'],
FilterUpdateType.Replace);
// Listen for mark selection
viz.addEventListener(TableauEventType.MarkSelectionChanged,
(event) => {
const marks = event.detail.getMarksAsync();
console.log('Selected marks:', marks);
}
);
The API surface is cleaner than v2, but the concepts are the same: workbooks contain sheets, sheets have filters and marks, and you can listen for user interactions. If you've built integrations with v2, the migration is straightforward — Tableau provides a migration guide, and the mental model hasn't changed.
Authentication: The Part Everyone Gets Wrong First
Authentication is where embedded analytics goes from "neat demo" to "production nightmare" if you don't plan it correctly. The fundamental challenge: your web app has its own authentication system, and Tableau has its own. You need to bridge the two so users don't see a Tableau login screen inside your product (because nothing screams "we bolted this on" quite like a second login prompt).
Tableau offers several authentication methods for embedded scenarios. Here's what actually matters in 2026:
Connected Apps (Recommended for Most Cases)
Connected Apps use JSON Web Tokens (JWTs) to establish trust between your web application and Tableau Cloud or Tableau Server. Your app generates a JWT, signs it with a shared secret or an RSA key pair, and passes it to the Embedding API. Tableau validates the token and grants access — no separate login required.
// Server-side: generate a JWT for the current user
const jwt = sign({
iss: CONNECTED_APP_CLIENT_ID, // from Tableau site settings
sub: user.tableauUsername, // the Tableau user
aud: 'tableau',
exp: Math.floor(Date.now() / 1000) + 600, // 10 min expiry
jti: uuidv4(),
scp: ['tableau:views:embed'] // scopes
}, CONNECTED_APP_SECRET_VALUE, {
algorithm: 'HS256',
header: { kid: CONNECTED_APP_SECRET_ID, iss: CONNECTED_APP_CLIENT_ID }
});
On the front end, you pass that token to the web component:
<tableau-viz id="tableauViz" src="https://your-cloud.online.tableau.com/views/Sales/Overview" token="GENERATED_JWT_HERE"> </tableau-viz>
This is the approach Tableau recommends for new implementations in 2026, and for good reason — it's clean, stateless, and doesn't require your server to maintain a session with Tableau.
External Authorisation Server (EAS) with OAuth 2.0
If you already have an OAuth 2.0 identity provider (Okta, Auth0, Azure AD, etc.), you can register it as an External Authorisation Server with Tableau. This lets you use your existing identity infrastructure to broker access. The flow is standard OAuth — your IdP issues tokens that Tableau trusts.
EAS is the more architecturally elegant solution for enterprises that already have an IdP handling SSO across dozens of applications. If you're already doing OAuth everywhere, adding Tableau to that flow is natural. If you're not, Connected Apps are simpler.
Trusted Authentication (Legacy)
Trusted Authentication (sometimes called "trusted tickets") is the older approach: your server requests a ticket from Tableau Server, and passes it to the client. It still works, but it's server-only (no Tableau Cloud support), requires your backend to make a synchronous call to Tableau before rendering the page, and is generally harder to debug when things go wrong. We've seen more than a few teams spend days chasing "ticket redemption failed" errors that turned out to be a trailing slash in a URL. If you're starting fresh, skip this and use Connected Apps.
Row-Level Security: Because Your Customers Should Not See Each Other's Data
This should go without saying, but we'll say it anyway because we've audited implementations where it wasn't implemented: if you're embedding Tableau in a multi-tenant application, you need row-level security (RLS). Full stop. No exceptions. Not even "oh, but our beta users trust each other."
Tableau supports RLS through two primary mechanisms:
- User filters in the workbook — The dashboard creator adds a filter that references the logged-in Tableau user. When embedded, the JWT identifies the user, and the filter restricts the data automatically. Simple, effective, and handled entirely in Tableau.
- Database-level RLS — Your data source enforces row-level permissions. This is more robust for complex scenarios because the filtering happens before data ever reaches Tableau. If your data warehouse supports policies (Snowflake, BigQuery, Redshift), this is the gold standard.
For multi-tenant SaaS, we strongly recommend database-level RLS as the primary mechanism with Tableau user filters as a secondary check. Belt and suspenders. The performance team will thank you too, because database-level filtering means Tableau processes less data per query.
The best security architecture is the one where even if a developer forgets a filter, the data layer catches it. Assume every layer above the database will eventually have a bug — because it will.
Customisation and White-Labelling
Your product manager will — with absolute certainty — walk into a meeting and say: "Can we make it not look like Tableau?" The answer is yes, mostly. Here's what you can and can't control.
What You Can Customise
- Toolbar visibility and position — Show it, hide it, or move it to the bottom. The
toolbarattribute on<tableau-viz>handles this. - Tab visibility — Use
hide-tabsto prevent users from navigating between sheets in a workbook. - Colours and fonts in the dashboard — Controlled at the workbook level in Tableau Desktop. Use custom colour palettes and fonts that match your brand.
- Responsive sizing — Set the viz to fill its container with CSS, and design the dashboard in Tableau with automatic or range-based sizing. The
<tableau-viz>element respects standard CSS sizing. - Custom interactions — Use the API to build your own filter controls, parameter selectors, or navigation outside the Tableau frame. Your UI, your components, driving Tableau's data.
- Loading spinners — Listen for the
FirstInteractiveevent to show your own loading state while the viz initialises.
What You Cannot (Easily) Customise
- Tooltip styling — Tooltips follow Tableau's rendering engine. You can control content but not the chrome around them.
- Right-click menus — These are Tableau's. You can disable them with JavaScript event interception, but you can't restyle them.
- The Tableau loading animation — The brief Tableau-branded loading state is visible before your custom loading handler kicks in. For most users it's a flash; for your designer it's an eternity.
The general rule: if it's inside the iframe, Tableau controls the rendering. If it's outside the iframe, you control everything. The API lets you build a remarkably seamless experience, but true pixel-perfect white-labelling requires designing your Tableau workbooks with embedding in mind from day one — not retrofitting existing dashboards.
Performance Optimisation: Making Dashboards Load Fast
Embedded dashboards live inside your application, which means their load time is your load time. If the dashboard takes eight seconds to render, your users don't blame Tableau — they blame you. Here are the performance levers you actually have control over.
Dashboard Design
- Reduce marks — Every data point is a mark. A scatter plot with 500,000 points is technically possible and practically unbearable. Aggregate, filter, or sample before rendering.
- Limit filters — Each visible filter is a query. Five dropdown filters on a dashboard means five queries before the first render completes. Use action filters or parameter-driven filtering instead.
- Extract over live connections — Tableau extracts are materialised snapshots. They're faster than live connections for almost every read-heavy embedded scenario. Schedule extracts to refresh at the frequency your data demands — hourly for operational dashboards, daily for everything else.
- Device-specific layouts — Don't serve a desktop dashboard to mobile users and hope for the best. Tableau's device designer lets you create phone and tablet layouts. Use them.
Infrastructure
- CDN for the API script — If you're self-hosting Tableau Server, make sure the JavaScript API file is served quickly. A slow script load delays everything.
- Geographic proximity — Your Tableau Cloud site (or Server) should be in the same region as your application servers and your users. Embedding a dashboard from a Tableau Cloud site in the US for users in Southeast Asia adds 200-400ms of latency per interaction. That adds up.
- Pre-warming — The first load of a view after an extract refresh or cache clear is the slowest. Use Tableau's subscription feature or a synthetic monitoring hit to pre-warm popular views before peak usage.
Front-End Implementation
- Lazy loading — If the dashboard is below the fold, don't load it until the user scrolls to it. Use the
IntersectionObserverAPI to trigger the embed on visibility. - Skeleton screens — Show a placeholder while the viz loads. Listen for the
FirstInteractiveevent and swap the skeleton for the live dashboard. - Single-viz embeds — Embed individual sheets rather than multi-tab workbooks when possible. Less data to load, faster render.
// Lazy-load a Tableau viz when it scrolls into view
const placeholder = document.getElementById('viz-placeholder');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const viz = document.createElement('tableau-viz');
viz.setAttribute('src', 'https://your-server/views/Dashboard/Sheet1');
viz.setAttribute('token', getJwtToken());
placeholder.replaceWith(viz);
observer.disconnect();
}
});
}, { threshold: 0.1 });
observer.observe(placeholder);
Pricing: What Tableau Embedded Actually Costs in 2026
Let's talk money, because this is where a lot of embedded analytics projects stall. The conversation usually goes: "This is incredible!" (demo), "Wait, how much?" (pricing call), "Can we just use iframes?" (denial).
Tableau restructured its pricing significantly in early 2026, following the Tableau Conference in May where Salesforce rebranded the platform as the "Agentic Analytics Platform." Here's the landscape as it stands:
Tableau Cloud Editions (2026)
Tableau Cloud now comes in four editions: Standard, Enterprise, Cloud+, and the Tableau+ Bundle. Embedded analytics capabilities vary by edition, and you'll need at minimum the Enterprise tier for production embedded use cases with Connected Apps and full API access.
License Types That Matter for Embedding
- Creator ($115/user/month on Tableau Cloud) — For the people building dashboards. You need at least one. Includes Tableau Desktop and Tableau Prep Builder.
- Explorer (~$42/user/month) — For users who interact with dashboards: filtering, drilling down, creating custom views. Most of your internal embedded users fall here.
- Viewer (~$15/user/month) — For users who view dashboards but don't modify them. This is your bread-and-butter license for external/customer-facing embeds.
The Scaling Problem
Here's where it gets uncomfortable. If you're embedding dashboards in a customer-facing product with 10,000 users, even at the Viewer tier you're looking at $150,000 per month in licensing alone. That's $1.8 million annually, and that's before Creator licenses, extract storage, or support.
For large-scale external embedding, Tableau offers a custom-quoted Embedded Analytics OEM SKU. This is a negotiated deal — typically based on deployment volume rather than named users. If your use case involves thousands of external users, this is the path to explore. Be prepared for a sales cycle that involves multiple calls, an NDA on pricing, and a spreadsheet of "committed annual spend."
The alternative, which an increasing number of teams are choosing, is to use Tableau for internal analytics and a purpose-built embedded analytics tool (Luzmo, Metabase, Superset, or custom-built with a charting library) for the customer-facing layer. We've seen this hybrid approach reduce embedded analytics costs by 60-80% while keeping Tableau where it shines — analyst-driven exploration and executive dashboards.
Step-by-Step Implementation Guide
Enough theory. Let's build. Here's the sequence for embedding a Tableau dashboard into an existing web application, from zero to interactive.
Step 1: Prepare Your Tableau Content
Publish your dashboard to Tableau Cloud or Tableau Server. Ensure it's designed for embedding:
- Set the dashboard size to "Automatic" or a specific range that matches your embed container
- Remove unnecessary tabs — publish only the sheets you intend to embed
- Apply your brand colour palette
- Test with sample users to verify RLS filters work correctly
Step 2: Configure Connected Apps
In Tableau Cloud, navigate to Settings > Connected Apps and create a new app. Choose "Direct Trust" for the simplest setup, or "OAuth 2.0 Trust" if you're using an external IdP. Record the Client ID, Secret ID, and Secret Value. These go in your application's server-side environment variables — not in your front-end code (we shouldn't have to say this, and yet).
Step 3: Build the Server-Side Token Endpoint
// Express.js example
const jwt = require('jsonwebtoken');
const { v4: uuidv4 } = require('uuid');
app.get('/api/tableau-token', authenticate, (req, res) => {
const token = jwt.sign(
{
iss: process.env.TABLEAU_CONNECTED_APP_CLIENT_ID,
sub: req.user.tableauUsername,
aud: 'tableau',
exp: Math.floor(Date.now() / 1000) + 600,
jti: uuidv4(),
scp: ['tableau:views:embed']
},
process.env.TABLEAU_CONNECTED_APP_SECRET_VALUE,
{
algorithm: 'HS256',
header: {
kid: process.env.TABLEAU_CONNECTED_APP_SECRET_ID,
iss: process.env.TABLEAU_CONNECTED_APP_CLIENT_ID
}
}
);
res.json({ token });
});
Step 4: Embed the Dashboard in Your Front End
<!-- Load the Embedding API -->
<script type="module"
src="https://your-cloud.online.tableau.com/javascripts/api/tableau.embedding.3.latest.min.js">
</script>
<!-- Container with loading state -->
<div id="dashboard-container" class="dashboard-wrapper">
<div id="loading-skeleton" class="skeleton-loader">
Loading analytics...
</div>
<tableau-viz id="tableauViz"
src="https://your-cloud.online.tableau.com/views/YourWorkbook/YourDashboard"
toolbar="bottom"
hide-tabs
style="width: 100%; height: 700px;">
</tableau-viz>
</div>
<script type="module">
// Fetch token and apply it
const response = await fetch('/api/tableau-token');
const { token } = await response.json();
const viz = document.getElementById('tableauViz');
viz.token = token;
// Hide skeleton when viz is ready
viz.addEventListener('firstinteractive', () => {
document.getElementById('loading-skeleton').style.display = 'none';
});
</script>
Step 5: Add Interactivity
Once the basic embed works, layer in the features that make embedded analytics genuinely useful rather than a fancy iframe:
// Sync your app's filters with Tableau
function applyDateRange(startDate, endDate) {
const sheet = viz.workbook.activeSheet;
return sheet.applyRangeFilterAsync('Order Date', {
min: new Date(startDate),
max: new Date(endDate)
});
}
// Export data from a selected mark
viz.addEventListener('markselectionchanged', async (event) => {
const marksCollection = await event.detail.getMarksAsync();
const data = marksCollection.data[0];
// Pass to your app's detail panel, modal, etc.
showDetailPanel(data);
});
Tableau Cloud vs. Tableau Server for Embedding
This decision shapes your entire embedding architecture, so get it right early. Here's the honest comparison:
- Tableau Cloud — Managed by Salesforce. No infrastructure to maintain, automatic updates, and Connected Apps work out of the box. The downside: you're on Salesforce's update schedule (quarterly releases), and you have less control over performance tuning. Best for teams that don't want to manage Tableau infrastructure.
- Tableau Server — Self-hosted (on-prem or your own cloud VMs). Full control over configuration, scaling, and update timing. The downside: you own the uptime, patching, and capacity planning. Best for organisations with strict data residency requirements or existing Tableau Server deployments.
For new embedded analytics projects in 2026, Tableau Cloud is the default recommendation unless you have a specific reason to self-host. The operational overhead of Tableau Server is real — we've watched teams spend more on DevOps engineer time managing Tableau Server than they would have spent on a Tableau Cloud subscription.
Common Pitfalls and How to Avoid Them
We've helped enough teams implement Tableau embeds that we can predict the mistakes before they happen. Here's the greatest hits, so you can skip them.
- Embedding desktop-designed dashboards — A dashboard built at 1920x1080 in Tableau Desktop does not gracefully shrink to a 600px-wide container in your responsive web app. Design for the embed container from the start, or you'll spend weeks "fixing" layout issues that shouldn't have existed.
- Ignoring token expiry — JWTs expire. If your users leave a tab open for hours (and they will), the embedded viz will stop working silently. Implement token refresh logic — periodically fetch a new token and update the viz's
tokenproperty before the current one expires. - Exposing secrets client-side — Your Connected App secret goes in your backend. Never generate JWTs in the browser. We've seen this in production code. We're not naming names. (We are judging.)
- Skipping the loading state — Tableau dashboards take 2-5 seconds to load. If you don't show a skeleton or spinner, users will see a blank space and assume the page is broken. Worse, they'll click refresh, doubling the load on your Tableau server.
- Not testing with realistic data volumes — A dashboard that loads in 1 second with 10,000 rows may take 15 seconds with 10 million. Test with production-scale data before launching.
- Treating embedding as a front-end task — Embedding Tableau is a full-stack problem. Authentication, token generation, user provisioning, RLS configuration, extract scheduling — the front-end embed code is maybe 20% of the work.
React, Angular, and Vue Integration Patterns
Most modern web apps aren't writing vanilla HTML. Here's how Tableau embeds play with the big three frameworks.
React
Tableau's web component works in React, but you'll want to wrap it in a component that handles token fetching and lifecycle:
import { useEffect, useRef, useState } from 'react';
function TableauDashboard({ viewUrl }) {
const vizRef = useRef(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
let mounted = true;
async function initViz() {
const res = await fetch('/api/tableau-token');
const { token } = await res.json();
if (!mounted || !vizRef.current) return;
vizRef.current.token = token;
vizRef.current.addEventListener('firstinteractive', () => {
if (mounted) setLoading(false);
});
}
initViz();
return () => { mounted = false; };
}, [viewUrl]);
return (
<div className="relative">
{loading && <SkeletonLoader />}
<tableau-viz
ref={vizRef}
src={viewUrl}
toolbar="bottom"
hide-tabs
style={{ width: '100%', height: '700px' }}
/>
</div>
);
}
Angular
Angular requires you to add CUSTOM_ELEMENTS_SCHEMA to your module so it doesn't complain about the <tableau-viz> element. Beyond that, the pattern is similar — use ngAfterViewInit to set the token and bind events.
Vue
Vue handles web components natively via compilerOptions.isCustomElement in your build config. Add a rule matching /^tableau-/ and Vue will pass through the custom element without trying to resolve it as a Vue component.
Security Best Practices for Production Deployments
Embedding analytics means opening a window from your application into your data layer. That window needs guardrails. Here's the security checklist:
- Short-lived tokens — Set JWT expiry to 5-10 minutes, not hours. Refresh proactively.
- Scope restrictions — Use the
scpclaim to limit what the token can do.tableau:views:embedis the minimum scope for embedding. Don't grant broader access than needed. - CORS configuration — Configure your Tableau Cloud or Server to only accept requests from your application's domain. This prevents your embedded dashboards from being iframed on third-party sites.
- Content Security Policy — Update your app's CSP headers to allow framing from your Tableau host. Add
frame-srcandconnect-srcdirectives for your Tableau domain. - Audit logging — Tableau logs view access. Use these logs to monitor who's accessing what, and set up alerts for anomalous patterns — like a single user account accessing hundreds of different tenant views.
- Secret rotation — Connected App secrets should be rotated on a schedule. Automate this. The number of production deployments running on secrets from 2022 is alarming.
Alternatives Worth Knowing About
Tableau is not the only game in town, and for some use cases, it's not the best choice. Intellectual honesty here will save you from a painful migration later.
- Power BI Embedded — Microsoft's offering. Uses Azure capacity-based pricing rather than per-user licensing, which can be significantly cheaper at scale. Deep integration with the Microsoft ecosystem. If you're already on Azure, this deserves a hard look.
- Looker (Google Cloud) — Code-first approach with LookML. Strong for teams that want version-controlled analytics models. Embedded via iframes with SSO, not as polished as Tableau's web component approach.
- Metabase — Open-source, self-hosted, and free for most embedded use cases. Interactive embedding requires the Pro plan ($85/month), but it's orders of magnitude cheaper than Tableau at scale. The visualisation quality gap has narrowed considerably.
- Luzmo — Built specifically for embedded analytics. Purpose-built tools tend to handle the edge cases better than general-purpose BI tools adapted for embedding. Transparent pricing starting around $495/month.
- Custom-built with D3.js, Chart.js, or Apache ECharts — Maximum control, zero licensing cost, and infinite customisation. The trade-off is development time. If your embedded analytics are a core product feature (not a nice-to-have), building custom might be the right long-term play.
Tableau Pulse and AI Features in Embedded Contexts
Tableau's 2026 push into agentic analytics introduced Tableau Pulse — proactive, AI-generated insights delivered as digestible metric cards. Can you embed Pulse? Sort of. Tableau Pulse metrics can be embedded via the Embedding API, giving your users AI-powered anomaly detection and trend summaries alongside traditional dashboards.
The practical value here is real: instead of your users staring at a dashboard trying to spot what changed, Pulse tells them. "Revenue dropped 12% in the Northeast region last week, driven primarily by a decline in Enterprise segment renewals." That's the kind of sentence that saves a 30-minute meeting.
The caveat: Pulse is a Tableau Cloud feature, requires a Tableau+ subscription tier, and its quality depends heavily on how well your metrics are defined. Garbage metric definitions in, garbage insights out. Set up your metrics carefully, and Pulse becomes genuinely useful. Throw in every KPI from every department, and it becomes a firehose of obvious observations.
Monitoring and Maintaining Embedded Dashboards
Embedding a dashboard is not a "set it and forget it" task — despite what your project plan says. Here's what ongoing maintenance looks like:
- Extract refresh monitoring — If an extract fails to refresh, your users see stale data. Set up alerts (Tableau has built-in notifications; supplement with your own monitoring) for failed extract refreshes.
- Version compatibility — The Embedding API is versioned. When Tableau updates (quarterly for Cloud), test your embeds. The migration from v3.x to v3.y is usually painless, but "usually" is not "always."
- User provisioning — New users in your app need corresponding Tableau accounts. Automate this with the Tableau REST API or SCIM provisioning. Manual user creation does not scale past about five users (ask us how we know).
- Performance baselines — Measure initial load time and interaction latency. Track these over time. Dashboards accumulate complexity like attics accumulate boxes — slowly, invisibly, until one day you can't walk through the room.
- Licence utilisation — Track how many users actually interact with embedded dashboards versus how many licenses you're paying for. The gap is almost always wider than expected.
Frequently Asked Questions
Can I embed Tableau dashboards for free?
Tableau Public visualisations can be embedded for free using the Embedding API, but they are publicly accessible — no authentication, no row-level security, and your data is visible to everyone. For any commercial, internal, or customer-facing use case, you need Tableau Cloud or Tableau Server with appropriate licenses. There is no free tier for private embedded analytics.
What is the difference between Tableau Embedding API v2 and v3?
The v3 API uses web components (custom HTML elements like <tableau-viz>) instead of the constructor-based JavaScript approach in v2. This means declarative HTML configuration, cleaner lifecycle management, and better compatibility with modern frameworks like React, Angular, and Vue. The v3 API also supports Connected Apps authentication natively. Tableau recommends v3 for all new implementations; v2 is still functional but no longer receives new features.
How do I handle authentication for embedded Tableau without showing a login screen?
Use Connected Apps with JWT authentication. Your backend generates a signed JWT containing the user's identity and scopes, then passes it to the <tableau-viz> web component via the token attribute. Tableau validates the token server-side and grants access without any login prompt. For organisations with an existing OAuth 2.0 identity provider, registering it as an External Authorisation Server (EAS) achieves the same seamless experience.
How much does Tableau Embedded Analytics cost for 1,000 external users?
At standard Viewer pricing ($15/user/month on Tableau Cloud), 1,000 external users costs $15,000 per month ($180,000 annually), plus Creator licenses for dashboard authors. For deployments at this scale, contact Tableau's sales team about the Embedded Analytics OEM SKU, which offers custom volume-based pricing. Many organisations find that purpose-built embedded analytics tools offer significantly lower per-user costs for external-facing use cases.
Can I embed Tableau dashboards in a React or Angular application?
Yes. The Embedding API v3 uses web components, which are natively supported by all major browsers and work with React, Angular, and Vue. In React, use the <tableau-viz> element directly with a ref for programmatic access. In Angular, add CUSTOM_ELEMENTS_SCHEMA to your module. In Vue, configure compilerOptions.isCustomElement to recognise the tableau- prefix. Wrap the web component in a framework component to handle token fetching and lifecycle management.
What is the typical load time for an embedded Tableau dashboard?
Initial load time ranges from 2-8 seconds depending on dashboard complexity, data volume, extract vs. live connection, and network latency. Optimised dashboards with extracts and limited marks typically load in 2-4 seconds. Complex dashboards with live connections to large datasets can exceed 10 seconds. Use lazy loading, skeleton screens, and pre-warming to mitigate perceived latency. Subsequent interactions (filtering, drilling) are generally faster at 0.5-2 seconds.
Should I use Tableau Cloud or Tableau Server for embedded analytics?
For new projects in 2026, Tableau Cloud is the default recommendation. It eliminates infrastructure management, includes automatic updates, and supports Connected Apps natively. Choose Tableau Server only if you have strict data residency requirements, need fine-grained infrastructure control, or are extending an existing Server deployment. The operational cost of self-hosting Tableau Server (patching, scaling, monitoring, upgrades) frequently exceeds the incremental licensing cost of Tableau Cloud.
The Bottom Line
Tableau Embedded Analytics is a powerful way to bring interactive, production-quality dashboards into your web application. The Embedding API v3 is a genuine improvement over its predecessor — cleaner, more declarative, and friendlier to modern front-end architectures. Authentication via Connected Apps is robust. The visualisation quality is best-in-class.
The real questions are about fit, not capability. Can your budget absorb per-user licensing at scale? Is your team prepared for the full-stack complexity of token management, RLS, user provisioning, and ongoing maintenance? Are you embedding as a core product feature or a nice-to-have?
If the answer to all three is yes, Tableau embeds beautifully. If the licensing math makes your CFO's eye twitch, explore the OEM SKU or consider a hybrid approach — Tableau for internal analytics, a purpose-built tool for the customer-facing layer.
Either way, your users deserve better than a PDF attached to a Monday morning email. Give them analytics that live where they work, respond to their questions in real time, and make "data-driven" something they actually do rather than something they put on a slide deck.