Tableau Embedding in Lightning
Tableau dashboards can be embedded directly in a Salesforce Lightning page so users do not have to switch tools. The embedding mechanics are well-documented; the operational complexity is in auth (SSO from Salesforce to Tableau) and in row-level security (making sure a logged-in Salesforce user only sees their own slice of the Tableau data).
This skill covers the LWC build, the JWT-based SSO pattern, the Trusted Sites / CSP configuration that the platform requires, and the row-level security pattern that ties it all together.
The two embed approaches
| Approach | When to use |
|---|---|
| Tableau Viz LWC | Drag-and-drop component on a Lightning page; minimal-code option; suitable for simple dashboards |
| Custom LWC + Tableau Embedding API v3 | Need programmatic control: pass parameters, filter on record context, listen to viz events |
Tableau Pulse (Tableau's metric / AI-summary surface) embeds similarly — Tableau provides Pulse-specific embedding.
Tableau Embedding API v3 (custom LWC)
The Embedding API is a JavaScript SDK. In an LWC, you load the SDK
as a static resource (or a third-party <script> if CSP allows),
then instantiate a tableau.Viz against a <div> you render.
import { LightningElement } from 'lwc';
import { loadScript } from 'lightning/platformResourceLoader';
import tableauApi from '@salesforce/resourceUrl/tableauEmbeddingApiV3';
export default class TableauEmbed extends LightningElement {
async renderedCallback() {
if (this.isInitialized) return;
this.isInitialized = true;
await loadScript(this, tableauApi);
const viz = document.createElement('tableau-viz');
viz.src = 'https://tableau.example.com/views/Sales/Dashboard';
viz.token = await this.getJwt(); // SSO token; see below
this.template.querySelector('.tableau-container').appendChild(viz);
}
}
The <tableau-viz> web component is provided by the Embedding API;
its attributes drive filters, parameters, and styling.
JWT SSO — the trust pattern
Anonymous embed (no SSO) works for fully public dashboards but exposes them to anyone with the URL — almost never what you want.
The recommended SSO is JWT-based:
- Tableau admin creates a Connected App in Tableau (a "JWT Direct Trust" type). This generates a Client Id and Secret Id.
- Salesforce Apex generates a short-lived JWT signed with that Secret Id, with claims that identify the Salesforce user (email or username) as the Tableau viewer.
- The LWC asks Apex for the JWT and passes it to
<tableau-viz>as thetokenattribute. - Tableau validates the JWT, identifies the user, and applies row- level security based on the user identity.
The Apex side typically uses Crypto.signWithCertificate with a
named certificate; secrets are stored in Custom Metadata or Named
Credentials, not hardcoded.
Row-level security
Tableau's row-level security is configured on the Tableau side, not Salesforce. The pattern:
- Data source has a user-identity column (e.g.
OwnerEmail). - Data source filter:
[OwnerEmail] = USERNAME()whereUSERNAME()is Tableau's user-identity function. - SSO from Salesforce passes the Salesforce user's email as the Tableau identity.
- When the user opens the embedded viz, the filter restricts to their rows.
If the SSO claim is wrong (e.g. passes a service-account name), the filter applies to that account's rows — typically empty or incorrect. RLS bugs almost always trace back to identity-claim misconfiguration.
CSP and Trusted Sites
The Tableau host URL must be added to:
- Lightning Trusted Sites (Setup -> CSP Trusted Sites). Without this, the iframe / fetch is blocked by Lightning's CSP.
- CORS allowlist if Apex makes a fetch to Tableau (rarer; JWT flow is local).
Both are admin-side configuration steps.
Recommended Workflow
- Choose the embed approach. Tableau Viz LWC for simple drop-in; custom LWC + Embedding API v3 for programmatic control.
- Configure CSP Trusted Sites. Setup -> CSP Trusted Sites; add the Tableau host URL with
Connect-SourceandFrame-Sourcepermissions as appropriate. - Set up JWT Connected App in Tableau. This is Tableau-side config; provides Client Id and Secret Id.
- Implement the JWT generator in Apex. Sign with
Crypto.signWithCertificate; claim payload identifies the Salesforce user; expiry short (5 min). - Build the LWC. Load the Embedding API static resource; render
<tableau-viz>; pass JWT and parameters. - Configure Tableau-side row-level security. Data-source filter matches the JWT subject claim.
- Test as different Salesforce users to confirm RLS works. Test with an inactive user to confirm the JWT generation fails gracefully.
What This Skill Does Not Cover
| Topic | See instead |
|---|---|
| Building Tableau dashboards / data sources | Tableau-side training |
| CRM Analytics (Salesforce native) | data/crm-analytics-patterns |
| Tableau-side admin (sites, projects, permissions) | Tableau Server / Cloud admin |
| SAML SSO into Tableau (alternative to JWT) | Tableau SSO docs |