Embedding API Beginner

#DDQ2025-09 Embed Tableau Content w/ the Embedding API (Beginner)

What is the Metadata API, how do you get started using it?

K

Kyle Massey

Author

2025-09-19T18:35:18
5 min read
preview.png

Welcome to the Beginner DataDevQuest challenge for September 2025! This month we’re focusing on harnessing the power of the Tableau Embedding API (formerly, the JavaScript API), which allows you to make your Tableau content live seamlessly within your external application.

An understanding of JavaScript basics will be very helpful in these challenges, but certainly isn’t required.

Note: We’re focusing on embedding content with the full API here, but there are certainly use cases where iframe embedding will be perfectly sufficient. Just know that this method will result in the loss of bi-directional interactivity.

Challenge Overview

Objective:

Familiarize yourself with the Embedding API v3 while adding a Tableau dashboard or view to a basic webpage. The page should add an JavaScript event listener that will perform an action once the embedded viz becomes interactive.

Why this challenge?

Embedding Tableau content in your application or website is a great way to harness the power of the tool, while also creating custom/bespoke experiences for your users. Imagine you have a central portal that allows users to perform several actions related to their duties, but you also want your Tableau insights to be front and center!

For the beginner challenge, we want our page/application to do something to inform the user that the embedded content has full loaded and is ready for them to interact with, e.g.:

Learning Goals

  • Familiarize yourself with the Embedding API capabilities
  • Embed a Tableau View or Dashboard
  • Using a JavaScript event listener, perform an action once the viz is interactive

Submission Guidelines

  • Source Code: Publish your project publicly in your GitHub profile
  • Add README: Include any setup instructions and describe how to run the program.
  • Video of Solution: Include a video of your solution in the README file. You can publish it on YouTube and embed the iframe, or save the video file in the repository’s root directory
  • Comments: Ensure your code is well-commented
  • Submission: Submit your challenge in the following forms

Additional Resources


Getting Started

The first thing you’ll need to get started is a webpage/application where you can embed content. Here’s an example you can start with:

CODE
<!DOCTYPE html>
<html lang="en" data-bs-theme="dark" class="html-height">

    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <!-- Custom CSS -->
        <link rel="stylesheet" href="styles.css">

        <!-- Bootstrap CSS -->
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet"
            integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">

        <!-- Bootstrap Icons -->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css">
        <title>DataDevQuest - DDQ2025-09 - Embedding: Beginner</title>
    </head>

    <body class="body-height">
        <nav class="navbar bg-body-secondary">
            <div class="container-fluid">
                <a class="navbar-brand"><i class="bi bi-globe-americas-fill pe-3"></i>My Application or Website </a>

                <div id="loadingSpinner">
                    <div class="spinner-border spinner-border-sm loading-text" role="status">
                        <span class="visually-hidden">Loading...</span>

                    </div>
                    <span class="ms-2 loading-text">Tableau content is loading...</span>
                </div>

                <div class="d-flex align-items-center">
                    <span class="double-em">
                        <i class="bi bi-person-fill me-2"></i>
                    </span>
                    <span>
                        Kyle
                    </span>
                </div>
            </div>
        </nav>


        <div class="container-fluid d-flex h-100 main-container-width">
          // PUT YOUR VIZ HERE
        </div>

        <!--  Bootstrap Bundle with Popper -->
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous">
            </script>

        <!-- Tableau Embedding API -->
        
        // START CODE/EVENT LISTENER(S)


    </body>

</html>

NOTES:

  • I am using Bootstrap in the example above, a light-weight component library for building responsive pages with little overhead
  • Embedding is also possible with JS frameworks like React, Vue, Svelt, etc. but the steps will vary
    • If you generally work with one of these frameworks, you may need to research how importing external JS modules works for you and how they scope against the frameworks own functionality, i.e. YMMV!

CODE
// CSS Styles
.loading-spinner {
    width: 100vw;
    height: 100vh;
    position: absolute;
    top: 0;
    left: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    background-color: rgba(0, 0, 0, 0.85);
    z-index: 9999;
}

.loading-hidden {
    display: none;
}

.text-not-ready {
    color: orange;
    font-style: italic;
}

.text-ready {
    color: green;
    font-weight: bold;
}

.double-em {
    font-size: 2em;
}

.main-container-width {
    max-width: 85%;
}

.html-height {
    height: 100%;
}

.body-height {
    height: 90%
}

.loading-text {
    color: orange
}

1. Copy/paste the HTML and CSS examples above to files named index.html and styles.css (or use your own!)

2. You will need to serve up the page with an HTML server — if you’re using VS Code, this is super easy! Just right click on the file and select “Open with Live Server”

3. If this is your first time using the Embedding API, I strongly recommend you start with the Tableau Embedding Playground! It will show you how to setup your script imports and create your first EventListener — which you’ll need to complete this challenge.


Challenge

Once you’ve got the Embedding API module imported, set up your event listener:

  • For this challenge, you’ll want to listen for the FirstInteractive event
  • Once the event is detected, hide the spinner (if using the above template) or perform another action to let the user know things are ready to go!

JavaScript Solution

NOTE: If you used the the HTML/CSS templates above, you can use this code as-is. Otherwise, be sure to make any necessary changes to element IDs, names, etc.

Place this code inside your <body> tag, as close to the bottom as possible:

CODE
<!-- Tableau Embedding API -->
<script type="module">
import { TableauEventType } from "https://public.tableau.com/javascripts/api/tableau.embedding.3.latest.js";

    // Get the viz object from the HTML web component
    const viz = document.querySelector('tableau-viz');


    // Wait for the viz to become interactive
    await new Promise((resolve, reject) => {
        // Add an event listener to verify the viz becomes interactive
        viz.addEventListener(TableauEventType.FirstInteractive, () => {
            console.log('Viz is interactive!');

            resolve();
            hideSpinner();
        });
    });
</script>

 <!-- Custom JavaScript -->
<script src="funcs.js"></script>

Place this inside a separate file in the same directory as index.html, named funcs.js:

CODE
function hideSpinner() {
    document.getElementById("loadingSpinner").style.visibility = "hidden";
}

Who am I?

I am Kyle Massey, 4x Tableau DataDev Ambassador and Visionary. I am a co-founder of DataDevQuest. I get my kicks with data, automation, music and my pets!

Have questions or feedback about this challenge? I’d love to hear from you: LinkedIn / X (fka Twitter).


Related Challenges

Continue learning about the: Embedding API