Video · Viz Extensions · Tableau Cloud

How to Host a Tableau Viz Extension, from Local to Cloud

The part that stops most people: running a viz extension on localhost to test it, then hosting it and safelisting it so it actually renders in Tableau Cloud or Server.

AUG 8, 20261:05:2219 chapters

The short version

Most of Eric's workshops jump straight into building extensions. This one goes backwards to the setup that actually blocks people: how Tableau finds an extension's files, how to run them locally while you build, and what changes when you want the same extension working in Tableau Cloud or Server.

The short version: an extension is just web files plus a .trex manifest, and the .trex is mostly a pointer. Locally, it points at localhost and a port you serve with a small Python server. Hosted, it is the same file with one URL changed to wherever the files now live.

Hosting alone is not enough. Eric publishes a workbook to his sandbox site, walks through every error that shows up along the way, and fixes each one: the workbook still pointing at localhost, the hosted URL not yet safelisted by a site admin, and the access prompt users would otherwise see on every load. He closes with a security note on why it matters who hosts an extension you allow.

The breakdown

2:41

The .trex is a small set of instructions, and the source URL is the part that matters

The .trex is XML. The top tags identify the extension (a reverse-domain id, version, name, description, author), but none of that runs anything. The one element Tableau really depends on is the source location URL, which tells Desktop where the actual web files are.

For a viz extension, the manifest also defines the Marks card. The encodings you declare replace the usual Color, Size, Detail and Tooltip slots, and the web code uses those ids to read what the user drops on them. In the demo Sankey, that means Source, Target and Value.

12:00

A splash screen tells users what the extension needs before it can draw

The local .trex points at localhost on port 9999, with index.html as the root file. Once the extension is allowed, Eric's build shows a custom splash screen asking for a dimension on Source, a dimension on Target and a measure on Value. Without one, he expects you just get a blank canvas.

The splash logic watches the encodings, so the message can change as fields arrive, for example telling the user they still need Target and Value. The chart itself is drawn by the HTML and JavaScript, rendered by Tableau in something like an iframe, with the Tableau Extensions API library packaged alongside as a requirement.

19:51

Serve from the folder that holds index.html, and test in the browser first

Eric runs his local server with Python: open a terminal in the root folder where index.html sits and run python -m http.server followed by the port. The port has to match the one in the .trex. He stops any other server first so they do not compete.

To take Tableau out of the equation, go to localhost and the port in a browser. You should not see errors there. Many extensions are not built to run outside Tableau and will say they cannot find Tableau, which is expected. If the files sit in a subfolder, you have to start the server from that folder instead, and relative paths like the library reference have to still resolve.

29:34

The manifest is cached in the workbook, so .trex edits need a fresh add

If you change only the web files, re-selecting the already loaded extension from the dropdown refreshes it with your changes. If the local server is stopped, you get an error message, unless the build happens to be self-contained, which is why Eric's demo kept rendering after he shut the server down.

Changes to the .trex itself are different. The manifest is cached in the workbook, so after Eric comments out the Source encoding nothing changes until he adds the extension again as a new one. Repointing a .trex works the same way.

32:03

Tableau Cloud has to be able to reach the files, but they do not have to be public to the world

A workbook using a localhost .trex publishes fine and then fails to render. On Server, if you have access to the VM, you can run the same small local server on the machine running Tableau Server. On Cloud, or without that access, the web files have to be hosted somewhere Cloud can reach.

That can be wide open, like a public S3 bucket or Cloudflare, or locked down to the Tableau Cloud IP addresses. The Tableau Exchange is the third option: those extensions are hosted files running on a server somewhere. In Q&A, Eric adds that hosting extensions adds no new Bridge requirement.

44:18

The hosted .trex is the same file with one URL swapped

Eric keeps a second .trex with hosted in the name. The only difference is the URL. He uploads the root folder to ext.tableauops.com, his own hosting platform, which checks for the files an extension requires and shows a preview. It gives back the URL of the folder holding index.html, and he pastes that into the hosted .trex.

Because each .trex acts as its own extension, he then adds it as a new extension in the workbook, clears a cached version, confirms the extension URL now shows the hosted address, and republishes so the workbook picks up the change. He built in a label showing whether the local or hosted version is connected, which makes this easy to check.

54:14

A site admin has to safelist the host, and can hide the prompt

Even with the files hosted and the workbook republished, Cloud still errors until the host is safelisted. An admin goes to Settings, then the Extensions tab, and adds the same URL that is in the .trex. A wildcard works too, with a slightly unusual syntax: a period then a star.

The same settings page controls the prompt asking users to allow the extension. By default it appears every time the workbook loads, even for users who already accepted. Setting it to hide removes it, and on reload the extension renders with no prompt.

55:43

Allowing data access means trusting whoever wrote and hosts the JavaScript

Granting an extension access to the data does not mean the data goes anywhere. But with a bad actor behind it, JavaScript could siphon data off the data source. Eric says the Exchange helps because Tableau certifies some partners, such as LA Data Viz, though not every Exchange extension has that certification.

That risk is part of why he wanted local and self-hosted options: if you host the files yourself, you are not depending on an outside third-party developer you do not know.

Key takeaways

  • A Tableau extension is web files plus a .trex, and the .trex's source URL is what tells Tableau where those files live.
  • Test locally with a server started in the folder holding index.html, on the same port as the .trex, and check it in a browser before blaming Tableau.
  • The manifest is cached in the workbook, so any .trex change means adding the extension again and republishing.
  • Moving to Cloud is the same .trex with one URL changed, pointing at files Cloud can reach.
  • A site admin has to safelist the hosted URL under Settings, Extensions, and can hide the per-load access prompt there.
  • Know who hosts an extension before you grant it data access, because its JavaScript could send that data elsewhere.

Watch this when

You have a viz extension working in Tableau Desktop on localhost and cannot get it to render after publishing to Tableau Cloud or Server.

Mentioned in this video