How to initiate Tableau data source refreshes from backend with WebSockets

Eski's data stories
4 min readOct 13, 2023

When Tableau is Embedded in a web app or a client portal, imagine a scenario where a user submits new data or parameters through a backend process. Once the underlying database completes saving this data, the corresponding changes need to be reflected in the frontend. How can we achieve this seamlessly, ensuring that the data on the dashboard is always up-to-date?

A button to simulate a backend-initiated data source refresh. This actually fires the backend code to kick off the refresh

This article explores a solution to this challenge by demonstrating how to initiate a Tableau data source refresh from the backend via WebSockets. We’ll walk you through the steps to set up a system that allows for real-time updates in a frontend application with the Tableau Embedded Dashboard. The beauty of this approach is that it enables specific targeting for refreshes if needed, giving you full control over your data.

NOTE: DO NOT use this solution to create auto-refreshing dashboards, such as those used in call centers, as this is not permitted by Tableau Cloud, and your site could be blocked. Use this only for the specified cases where an occasional backend-initiated refresh is needed, for instance, when critical user-defined parameters alter the underlying database data.

Full Codebase can be found here:

https://github.com/Tab-SE/tab_backend_ds_refresh_websocket

Prerequisites

Before we dive into the implementation, here are the prerequisites you’ll need:

  • Node.js installed.
  • A running Tableau Server or Tableau Cloud visualization that you’d like to embed and refresh.

Implementation

Let’s break down the implementation into two main parts: the frontend and the backend.

Frontend

In the frontend, we’ll establish a WebSocket connection with the backend and listen for refresh commands. Here’s the detailed explanation:

1. Import Libraries and Initialize WebSocket

We begin by importing the necessary libraries, including the Tableau Embedding API, and initializing the WebSocket connection.

  • We import the Tableau Embedding API to work with Tableau visualizations.
  • We set up an event listener for when the DOM is loaded, ensuring our JavaScript code runs after the page is ready.
  • We initialize a WebSocket connection and define a function (triggerBackend) to handle backend-initiated refreshes.

2. Establish WebSocket Connection

Now, let’s establish the WebSocket connection and handle messages from the backend:

  • We create a function initializeWebSocket to set up the WebSocket connection.
  • We specify the WebSocket server URL (ws://localhost:3000) to connect to the backend.
  • We define event listeners for the WebSocket connection’s open state and incoming messages.

3. Simulate Backend Refresh

To simulate a backend-initiated refresh from the frontend, we define the triggerBackend function:

  • We check if the clientUUID is defined, which indicates that the WebSocket connection is established.
  • If clientUUID exists, we use the fetch API to add the client UUID to the refresh list on the backend (/add-to-refresh-list/:uuid) and trigger the backend refresh (/trigger-refresh).

4. Refresh Tableau Data

Finally, when the backend-initiated refresh is received or when the user interacts with the Tableau visualization, we call the refreshTableauData function:

  • This function uses the Tableau Embedding API to refresh the data source asynchronously.
  • After a successful refresh, a message is displayed in the UI with the current time.

Backend

In the backend, we set up an Express.js server that handles WebSocket connections and refresh commands. Here’s how it works:

1. WebSocket Server and Client Registration

We create a WebSocket server using the ws library, and clients receive a unique UUID upon connection.

  • We initialize a WebSocket server and listen for client connections.
  • Each connected client receives a unique UUID generated using the uuidv4 library.
  • We maintain a map of client UUIDs to WebSocket connections.

2. Triggering Refresh

We provide two options for triggering refreshes: broadcasting to all clients or targeting specific clients.

  • We check the value of BROADCAST_TO_ALL to determine whether to broadcast the refresh to all clients or specific ones.
  • If BROADCAST_TO_ALL is true, we loop through all connected clients and send a refresh command to those with an open WebSocket connection.
  • If BROADCAST_TO_ALL is false, we loop through the clientsToRefresh set, which contains UUIDs of specific clients to target for refresh.
  • We use the WebSocket connections stored in clientMap to send refresh commands to the selected clients.
  • A response is sent to the requester to confirm the refresh.

3. Adding Clients to the Refresh List

We provide an endpoint to add a client to the list of clients to be refreshed.

Clients can access this endpoint with their UUID as a parameter to add themselves to the clientsToRefresh set.

  • The UUID is added to the set, indicating that this client should receive refresh commands.

4. Configuration

You can easily configure the behavior of the backend by changing the value of BROADCAST_TO_ALL:

  • Set BROADCAST_TO_ALL to true if you want to broadcast refresh commands to all connected clients.
  • Set it to false if you prefer to target specific clients based on the UUIDs stored in the clientsToRefresh set.

By following this method, you empower your Tableau Embedded clients to maintain synchronization with the most up-to-date data.

--

--