top of page
Search

Beyond the Viz: What Tableau Extensions Can Do and How to Build One

Most Tableau developers don't know this exists


Tableau has a feature that's been available since version 2019.3, is fully documented, requires no licensing add-on, and is almost entirely ignored by the community.


Extensions. Not plugins, not integrations — extensions. A way to embed a fully custom web application directly inside a Tableau dashboard or worksheet, with live access to data, filters, parameters, and mark selections. Real-time. Two-way. No iframe tricks, no external embedding.


If you've spent any real time in Tableau, you've probably hit the ceiling at least once — a chart type Tableau can't render, a developer tool you wished existed, a KPI layout that requires more flexibility than native sheets allow. Extensions are the answer to almost all of it.


This post is a practical introduction: what they are, how they work, how to host and deploy them, and how to build your own. Plus two real examples we built from scratch.


---

What is a Tableau Extension?

An extension is a web application — HTML, CSS, and JavaScript — that runs inside Tableau as a first-class object. It's not a wrapper or an embed; it's a fully integrated component that communicates directly with the Tableau Extensions API.


There are two kinds:


Dashboard extensions live on a Tableau dashboard as a draggable, resizable zone — just like a text box or image object. They can read data from any worksheet on the dashboard, respond to filter and parameter changes in real time, and render whatever you build: custom charts, developer tools, data exports, integrations.


Viz extensions (also called worksheet extensions) replace the mark type on a worksheet. Instead of bars or circles, your worksheet renders whatever custom visualisation you build. The data pipeline — filters, context filters, encoding shelves — all works exactly as normal, and your extension draws the result. Custom chord diagrams, pixel-perfect KPI cards, radial charts, whatever Tableau can't produce natively.


Both types share the same API, the same deployment model, and the same manifest format. The key difference is where they live: on a dashboard vs. inside a worksheet.


---

Why do they matter?

Extensions matter because they close the gap between what Tableau does and what your team actually needs.


They unlock custom visualisations. Tableau's native mark types are powerful but finite. Extensions let you render anything a browser can draw — D3, Canvas, SVG, Chart.js, or plain vanilla code. The data comes through the standard Tableau pipeline so it stays filtered, contextual, and live.


They enable developer tooling inside Tableau. This is underexplored. Because an extension runs inside Tableau Desktop, it can inspect the workbook it's embedded in — metadata, structure, even the raw XML of a .twb file. That's how we built Workbook X-Ray (more on that below).


They stay in sync with the dashboard. Unlike an external tool or a custom portal, an extension responds to the same filter changes and mark selections as everything else on the dashboard. No polling, no separate data pipeline — it's just there, live.


They're simpler to build than people expect. No build pipeline, no framework requirement, no Tableau-specific SDK to install beyond a single script tag. A working extension is genuinely just an HTML file with a <script src="tableau.extensions.1.latest.min.js"> and a couple of API calls.


---

The anatomy of an extension


Every extension has three parts:


1. The manifest file (.trex)

A small XML file that tells Tableau what the extension is and where to find it. It contains a name, description, author, minimum API version, and most importantly, a <source-location> URL pointing to your web app.


This is the only file you give to users. They load it in Tableau; Tableau fetches the web app from the URL inside it.













2. The web app

Your HTML/CSS/JS files. Hosted anywhere accessible to Tableau — a local server, GitHub Pages, any web host. The extension loads in Tableau's embedded browser like any web page.


3. The Extensions API

A JavaScript library you load via a script tag. Call tableau.extensions.initializeAsync() first, then you have access to worksheets, data, parameters, settings, and events.


That's the full pattern. Everything else is just your application code.


---

How to add an extension to Tableau


For dashboard extensions:

  • 1. Open a workbook in Tableau Desktop and navigate to a Dashboard sheet

  • 2. In the left panel under Objects, drag Extension onto the canvas

  • 3. In the dialog, click "Access Local Extensions" (for a .trex on your machine) or browse to a URL

  • 4. Select the .trex file and click OK on the trust prompt


For viz extensions:

  • 1. Navigate to a regular Worksheet

  • 2. In the Marks card, open the mark type dropdown

  • 3. Select Extension at the bottom of the list

  • 4. Load your .trex the same way


That's it. The extension loads in the zone and you interact with it like any Tableau object.


---

Hosting


The URL in your .trex is just a web address. Tableau fetches it in its embedded browser, so anything that serves HTML over HTTPS works.


Local development — the fastest way to iterate. Run a local HTTP server (Python: python -m http.server 8765) and set the .trex URL to http://localhost:8765/index.html. Tableau on the same machine loads it instantly. Change your JS, reload the extension zone (right-click → Reload Extension), see the result. No build step, no deploy.


GitHub Pages — the right answer for sharing with a team. Push your extension files to a GitHub repo, enable Pages in Settings, and your extension is live at https://yourusername.github.io/your-repo/. Users need only the .trex file — no server to run, nothing to install. GitHub Actions can automate deployment on every push.


Any web host — Netlify, Vercel, S3 + CloudFront, your own server. Anything that serves static files over HTTPS. Tableau just needs to be able to fetch the URL in the manifest.


One important rule: the .trex you share with others must point to the hosted HTTPS URL, not localhost. Localhost is only reachable on your machine.


---

Whitelisting


Tableau's trust model for extensions works through an allowlist. By default, Tableau Desktop prompts the user to trust each new extension the first time it's loaded — a one-time dialog per extension per workbook.


For organisational deployment (Tableau Server or Tableau Cloud), admins can whitelist extensions at the server level so users aren't prompted at all. This is done through the server admin panel under Extensions Settings, where you add the extension's source URL to the approved list.


There are two levels:

- Full data access — the extension can read data from worksheets and access the Tableau Extensions API fully

- Sandboxed — more restricted, appropriate for extensions from unknown sources


For internal team extensions hosted on a trusted domain, full data access with URL-based whitelisting is standard. For extension authors, this means the domain your extension is hosted on matters — use a stable, persistent URL, not a localhost address.


---

How to build your own


The barrier is lower than it looks. If you can write JavaScript, you can build a Tableau extension.


The stack: HTML + CSS + JS. No framework required. No build pipeline. Single file if you want. The only external dependency is the Tableau Extensions API script, which you load from Tableau's CDN:



The loop: Write code → reload the extension zone in Tableau → see the result. No compilation, no deploy, no waiting. Iteration is as fast as web development gets.


The key API surface you'll use most:

- initializeAsync() — always the first call

- dashboardContent.dashboard.worksheets — get all worksheets on the dashboard

- worksheet.getSummaryDataAsync() — read the summary data (what Tableau shows)

- worksheet.addEventListener(FilterChanged, handler) — react to filter changes

- workbook.getParametersAsync() — read and write parameters

- settings.set() / settings.saveAsync() — persist configuration across sessions (viz extensions only)

- For viz extensions: worksheetContent.worksheet to access the worksheet the viz is on


A recommended starting point: Eric Summers has built and published a Claude Code skill (tableau-extensions) that gives you a complete, opinionated framework — finished examples to clone, a manifest guide, errors-and-fixes reference, and hosting instructions. It's the fastest path from zero to a working extension. His writing on LinkedIn is also consistently the most practical content on this topic in the community.


The workflow: start from the closest finished example, change only what you need, deploy to GitHub Pages, share the .trex. Most working extensions take an afternoon.

 
 
 

Comments


Post: Blog2_Post

Subscribe Form

Thanks for submitting!

©2021 by Tableau Tips and Tricks. Proudly created with Wix.com

bottom of page