A Guide to Embedding Tableau # 2: Embed Examples
The previous blog in this series, A Guide to Embedding Tableau # 1: A Primer on Embedding, introduced you to the concept of embedding, defined some important terms, discussed the primary methods we’ll be using, and discussed a few common scenarios. If you haven’t read this primer, then I highly recommend going back and reading it, as we’re going to build upon that foundation today, diving into some specific examples.
As a reminder, the last blog shared the three methods we’ll use for embedding: iFrame, JavaScript Embed API v2, and JavaScript Embed API v3. And we also discussed the three most common embedding scenarios:
1) Fixed-Sized – A dashboard that uses fixed sizing—essentially a static height and width.
2) Device Layouts – A dashboard built using Tableau’s Device Designer. Essentially, these contain what amounts to separate dashboards for different target platforms—each with its own unique height and width.
3) Automatic or Ranged Sizing – Dashboards that are built with automatic or ranged sizing, which allows them to automatically resize to fit the page.
In this blog, we’ll show you how to address each of these common scenarios using each of the three embed methods—a total of nine different examples. The goal of these examples is to give you something you can use as a sort of template so you can easily leverage them in your work.
As detailed in the previous post, there is a big difference between creating raw HTML with embedded content and embedding that content within a web platform. I’ve created complete working HTML examples which I’ve posted on Github. I’ve also uploaded these to flerlageapps.com so you can open and interact with them. But, when embedding into a platform, you do not want to use all the code—you’ll want to strip out the extraneous HTML. To help with this, I’ve done two things. First, I’ve added clear comments to the code on Github, indicating the start and end of the embed code. Second, I’ve created a collection of “pens” on codepen.io. These pens allow you to see just the embed code and view the results of that code. In addition, these pens allow you to play with the code so you can experiment with your own embeds. As we go through each example, I’ll share a link to the code on Github, the working HTML page on flerlageapps.com, and the pen on codepen.io.
One last note before we begin. All of my pure HTML code includes the following meta tag:
<meta name="viewport" content="width=device-width, initial-scale=1">
In the past, I’ve found that device layouts did not always work without this tag in place. I tested this while writing this blog and found that everything worked fine without it (so perhaps that issue is in the past). However, I tend to add it to all my pure HTML code just in case.
Fixed-Size Embedding
Fixed-size dashboards have a static height and width. This is probably the most common type of embed because building more dynamic sizes is a lot of work and isn’t always necessary. And this simplicity makes it the easiest type of embed—thus the reason we’re starting here first.
For these examples, I’m going to be using my viz, The Widening Divide. The dashboard has a width of 1500 pixels and a height of 2000 pixels. Our goal is that the embed will look like the following image, with the workbook centered on the page. We’re centering because, in my experience, it tends to make more sense with Tableau than left or right alignment.
Zoomed to 40% so we can see the entire dashboard.
IFrame
This type of embed is quite simple using an iFrame. Here’s the code:
iFrame embeds have a lot of different parameters available, but I’ve chosen to only specify the most important ones in this example:
width – Set to the width of the dashboard, in pixels. Put “px” after the number of pixels and include the whole thing within double quotes. So, with our example, we use width="1500px"
height – Set to the height of the dashboard, in pixels plus adjustments for whether or not you wish to show the toolbar or tabs. If you wish to show the toolbar, add 27. If you wish to include tabs, add 23. Note: You cannot hide the toolbar on Tableau Public. With our example, we use width="2027px" since this is Tableau Public and we can’t remove the toolbar even if we wished.
src – This is the URL of the workbook you wish to embed. To get this, open the workbook on Server/Cloud/Public, select the share option then use the link option. Strip out everything after the first "?". For example:
https://public.tableau.com/views/TheWideningDivide/01?:language=en-US&:display_count=n&:origin=viz_share_link
becomes…
https://public.tableau.com/views/TheWideningDivide/01
You can add additional parameters if desired. These include options for hiding toolbars, hiding tabs, and many other options. For a complete list of parameters and examples on how to use them in the URL, see Embed Code Parameters for Views (look at the section labeled Parameters for prior versions of embedding then scroll down to the options for iFrames).
Finally, we are then wrapping the entire iFrame with <p align="center">. This will center the embed on the page (you can use “right” or “left” if preferred).
JavaScript Embed API v2
This is not quite as nearly as straightforward as an iFrame as we’re now introducing some JavaScript code. But don’t be intimidated. We’ll take this apart and I’ll show you how to plug your own values into this script to make it work.
After viewing this code, you’re likely wondering why we don’t just use the iFrame since it’s so much easier. That would certainly be a viable option, but iFrames have a lot of limitations, especially when you want to have a bit more granular control over how the embed behaves—we’ll see some examples of this in the next section. There are also some other concerns with iFrames—security, in particular—which we’ll address at the end of the blog.
As you can see, the code, is broken into two segments. At the top, we have a div—essentially a container for content. And, at the bottom, we have a script—an element used for some executable code (in our case, the actual JavaScript code). These object types will be used in all of our JavaScript examples, so get used to them. In our case, the div defines the content we’re going to embed and the script then actually creates those elements on the page.
When discussing the iFrame example, I mentioned that we have a variety of parameters available to us. The same is true with this example, with the majority of the parameters being placed into the div element. I’ve included a few of these, but most of the time, you won’t need to change them. Like the iFrame, you can also add new parameters, if desired—see Embed Code Parameters for Views (look at the section labeled Parameters for prior versions of embedding).
To modify this code for your use, you’ll need to consider the following key parameters:
width – Found in the script section, this appears as vizElement.style.width. Set this to the width of the dashboard, in pixels. Put “px” after the number of pixels. So, with our example, we use vizElement.style.width = '1500px';
height – Also found in the script section, this appears as vizElement.style.height. Set to the height of the dashboard, in pixels plus adjustments for whether or not you wish to show the toolbar or tabs (as noted in the previous section). With our example, we use vizElement.style.height = '2027px';
host_url – This is essentially the root URL of Tableau Server, Cloud, or Public. For example, for Tableau Public, you’d use https://public.tableau.com/
name – This is the “name” of the workbook we’re embedding. To get this, open the workbook on Server/Cloud/Public, select the share option then use the link option. Then extract just the workbook and sheet name (essentially the last two elements before “?:”). For example:
https://public.tableau.com/views/TheWideningDivide/01?:language=en-US&:display_count=n&:origin=viz_share_link
becomes…
TheWideningDivide/01
To center the embed, we’re using style='margin: 0 auto;' in the div at the top. This essentially tells the browser to automatically set the left and right margins, which it does by making both of them the same.
Before we move on from this section, I want to point out that this code is basically what we get when we use the Share option on a workbook then choose the Embed code. Tableau Server/Cloud/Public still supply this code in the older version of the API (though I’d imagine they’ll change it to version 3 at some point in the future). All I’ve done is add some formatting to the code and strip out some of the less critical parameters.
JavaScript Embed API v3
Version 3 of the JavaScript Embed API gives us code that is much more succinct than prior versions.
The code is broken into two segments. At the top, we have a script element and below that, a div. And there isn’t really any JavaScript code here at all because this simple embed doesn’t really require it. Instead, the script element essentially loads the Tableau code we need for embedding and the div object defines the element.
To modify this code for your use, you’ll need to consider the following key parameters:
width – Found in the div style section. Set this the width of the dashboard, in pixels. Put “px” after the number of pixels. So, with our example, we use width:1500px;
height – Also found in the div style section. Set to the height of the dashboard, in pixels plus adjustments for whether or not you wish to show the toolbar or tabs (as noted in earlier sections). With our example, we use height:2027px;
src – This is the URL of the workbook you wish to embed. To get this, open the workbook on Server/Cloud/Public, select the share option then use the link option. Strip out everything after the first "?". For example:
https://public.tableau.com/views/TheWideningDivide/01?:language=en-US&:display_count=n&:origin=viz_share_link
becomes…
https://public.tableau.com/views/TheWideningDivide/01
Parameters are added after the src. In this example, we’re turning off tabs and pushing the toolbar to the bottom. A full list of these parameter can be found in Table of properties and values for embedded objects and components.
Like the JavaScript v2 example, we’re using style='margin: 0 auto;' in the div to center the content.
Device Layouts Embedding
While fixed-size dashboards are extremely common, they aren’t always the best bet for embedded content since much of the world now consumes web content via mobile devices. Fortunately, through Tableau’s Device Designer, we can create what amounts to separate dashboards for different target platforms—each with its own unique height and width. This complicates embedding as we need to account for these changing dimensions.
For these examples, I’m going to be using my viz, Fleetwood Mac: The Members and the Albums. The dashboard has two device layouts—Desktop and Phone. The Desktop layout has a width of 1100 pixels and a height of 1600 pixels. The Phone layout has a minimum width of 375 pixels and a height of 845 pixels. The nature of phone layouts in Tableau is that they are set up to resize the width to fit nicely on the specific mobile device being used. This is why there is only a minimum width. That, of course, adds additional complexity to our embed because, in some situations, we may want the width to grow to match the screen and, in others, we might want to force a specific width. I’ve included an option in all of my examples to account for this. I should also note that we can also use Device Designer to create tablet layouts. I’ve personally found that the desktop layout tends to work okay for tablets, so I generally only focus on desktop and phone. But, if you had additional device layouts, my example code could be easily modified to handle those.
Our goal is that our embed will display the desktop view when displayed on larger screens and the phone view on smaller screens. To do this, we need to insert logic that essentially checks the width and height of the window and based on that, sets the dimensions of the dashboard. Tableau’s device layouts will then kick in and display the correct layout. And, like last time, we’re also going to center the content within the page.
Zoomed to 50% so we can see the entire dashboard.
One more note before I jump into the examples. The images above use a browser, on my Desktop, and I’ve simply resized the window to show what happens to the embed. This mimics what would happen on a phone. If you open the interactive examples and follow along, you’ll notice that the page does not auto-refresh. We have to manually refresh the page to get the new layout to display. While it would be possible, in some situations, to force the page to update automatically (we’ll apply one of these techniques in the responsive embed section), I’d argue that this doesn’t really make much sense. You’re either going to be using a desktop computer or using a phone and you’ll get the layout that best matches that device. For that reason, my examples aren’t set up to automatically update.
IFrame
Unfortunately, the introduction of device layouts makes iFrames quite a bit more difficult. As noted above, we need to check the dimensions of the window then adjust the dashboard size accordingly. But, since iFrames are just an HTML element, they don’t really have the ability to perform this type of logic—this is one of the huge advantages of JavaScript. However, we can leverage Cascading Style Sheets or CSS. CSS is a sort of rule-based-language that is primarily used for defining the formatting of a web page. However, we’re going to use it to control the dimensions.
Here is our actual embed code:
And here is our CSS:
We’ll need to edit both in order to make this embed work. One potential problem with this is that CSS isn’t always readily accessible, particularly if you’re embedding into a web platform. Most platforms have some method for changing the CSS, but some are more straightforward than others. In addition, we’re sort of hacking CSS to make this work—it would be much better done using a full programming language such as JavaScript.
But, this is the only option I could personally find for making this work with iFrames so let’s take a closer look. As you can see, the iFrame itself is quite simple. We really only need to define the source URL. The CSS is more complex. In lines 4-7, we’re defining 4 variables we will use later in the CSS. Lines 10-25 define the default layout of the iFrame (in our case, the desktop layout). Lines 27-44 use what’s called a ”media query” to test the width of the window. If it’s less than a certain minimum, it then redefines the iFrame for the phone layout.
To modify this code for you use, you’ll need to consider the following key parameters. Only one of these is in the iFrame embed code:
src – This is the URL of the workbook you wish to embed. To get this, open the workbook on Server/Cloud/Public, select the share option then use the link option. Strip out everything after the first "?". We then add ?:showVizHome=no to the end. For example:
https://public.tableau.com/views/FleetwoodMacTheMembersandtheAlbums/FWM?:embed=y&:display_count=y&:toolbar=n&:origin=viz_share_link
becomes…
https://public.tableau.com/views/FleetwoodMacTheMembersandtheAlbums/FWM?:showVizHome=no
The rest are within the CSS. Since the CSS is a bit lengthy, I’ve tried to create variables for as many of these as possible—these will then be used later in the CSS.
--desktopWidth and --phoneWidth – Set these to the width of the desktop and phone layout, respectively, in pixels. Put “px” after the number of pixels. So, with our example, we use --desktopWidth: 1100px; and --phoneWidth: 375px; If you want the phone view to automatically expand the width to fit the device, then change --phoneWidth to 100%.
--desktopHeight and --phoneHeight – Set these to the width of the desktop and phone layout, respectively, in pixels. Put “px” after the number of pixels. Be sure to make adjustments if you’re showing the toolbar or tabs. For our example, we’ll use --desktopHeight: 1627px and --phoneHeight: 827px;
Finally, we need to edit the min-width within the media query on line 28. From what I can tell, we cannot use a variable here, so you’ll need to edit it directly.
min-width – Set this to the window width threshold at which the view will change from desktop to phone. In my code, I’ve used max-width: 600px. This means that, if the window (e.g. the browser) is less than 600 pixels wide, the phone layout will be displayed. Otherwise, the desktop layout will be displayed.
Like our previous iFrame example, you can add parameters to the URL. For more details, see Embed Code Parameters for Views (look at the section labeled Parameters for prior versions of embedding then scroll down to the options for iFrames).
Finally, we’re using the following CSS, which appears in multiple locations, to force the content to be centered:
left: 0;
right: 0;
margin: auto;
If you can get all those pieces working, then you should be in good shape. But, as noted above, all this CSS just feels like a hack. In my personal opinion, we’d be better off using a more full-featured programming language such as JavaScript.
JavaScript Embed API v2
The structure of our JavaScript v2 code is similar to the JavaScript v2 code used for the simple fixed-size embed. It has a div at the top and a script at the bottom. The script, however, is a bit longer as it contains the logic for checking the window width then adjusting the embed width accordingly.
Like the iFrame example, I’ve created a number of variables (lines 14-20) to make it easier to edit the script. You’ll need to change the following within the script:
desktopWidth, phoneWidth, and fitBrowserPhone – Set these to the width of the desktop and phone layout, respectively, in pixels. Put “px” after the number of pixels. So, with our example, we use const desktopWidth = '1100px'; and const phoneWidth = '375px'; If you want the phone view to automatically expand the width to fit the device, then fitBrowserPhone to true.
desktopHeight and phoneHeight – Set these to the height of the desktop and phone layout, respectively, in pixels. Put “px” after the number of pixels. Be sure to make adjustments if you’re showing the toolbar or tabs. For our example, we’ll use const desktopHeight = '1627px'; and const phoneHeight = '872px';
widthThreshold – Set this to the window width at which the view should switch between desktop and phone. While measured in pixels, set this to a simple number, without the “px”. In our example, we’re using const widthThreshold = 600;
Note: I’ve also parameterized the location of the toolbar in this example, but you’ll rarely need to change that.
The following will need to be modified within the div at the top:
host_url – This is essentially the root URL of Tableau Server, Cloud, or Public. For example, for Tableau Public, you’d use https://public.tableau.com/
name – This is the “name” of the workbook we’re embedding. To get this, open the workbook on Server/Cloud/Public, select the share option then use the link option. Then extract just the workbook and sheet name (essentially the last two elements before “?:”). For example:
https://public.tableau.com/views/FleetwoodMacTheMembersandtheAlbums/FWM?:embed=y&:display_count=y&:toolbar=n&:origin=viz_share_link
becomes…
FleetwoodMacTheMembersandtheAlbums/FWM
Refer to the previous JavaScript v2 example for details on changing additional display parameters and how we’re centering the views.
JavaScript Embed API v3
The JavaScript v3 code in this example looks quite a bit different than our v3 code for a fixed-size embed because it requires us to actually write some JavaScript. That said, this looks pretty similar, in structure, to the v2 code. If you understand how the v2 code works, you’ll be able to follow this pretty closely. The variables are specified in lines 5-13. The following should be handled in the exact same way as the v2 code: widthThreshold, fitBrowserPhone, desktopWidth, desktopHeight, phoneWidth, phoneHeight. The only variable not in the v2 code is vizURL. Set this to the URL of the workbook you’re embedding. To get this, open the workbook on Server/Cloud/Public, select the share option then use the link option. Strip out everything after the first "?". For example:
https://public.tableau.com/views/FleetwoodMacTheMembersandtheAlbums/FWM?:embed=y&:display_count=y&:toolbar=n&:origin=viz_share_link
becomes…
https://public.tableau.com/views/FleetwoodMacTheMembersandtheAlbums/FWM
Refer to the previous JavaScript v3 example for details on changing additional display parameters and how we’re centering the views.
Responsive Embedding
Some dashboards are built with automatic or ranged sizing, which allows them to automatically resize to fit the page. In the best of cases, this means a single design could work on multiple device types. However, in practice, it is incredibly difficult to design a single dashboard in a way that will always be usable no matter the size. For that reason—as well as some known performance inconsistencies—I generally do not recommend this option. However, when this option is used, it allows us to leverage Responsive Web Design techniques—essentially automatically updating the content’s dimensions as the window size changes. So, as we work through these examples, one of the key goals will be to ensure that our embeds are also responsive.
For these examples, I’m going to be using a version of Tableau’s “Regional” accelerator. Specifically, I’ll be using the Global Temperatures dashboard which is based on the original work Naledi Holly for Makeover Monday. The dashboard is set to automatic sizing, but my example code will work for ranged sizing as well. All the above being said, a very short dashboard doesn’t look very good, so it’s probably a good idea for us to set a minimum height so that it’s not too squished (I’m not worrying about a minimum width because most browsers don’t resize to less than 400 pixels or so). Thus, our examples will set a minimum height. The code will never change the height to anything lower than that value.
As noted above, our goal will be to have the content fit the browser window, automatically updating as we change the window size. Here are a couple of examples of how it should look at different sizes.
IFrame
I have some great news for you! This one is super simple with an iFrame. It’s just one simple line of embed code.
Since we want the embed to size to meet the dimensions of the window, we simply set the width and height of the iFrame to 100% and it takes care of the rest. We don’t have to do anything special to get it to automatically resize as, from everything I’ve seen, it takes care of that as well. We only need to set two parameters.
min-height – This is the minimum height of the embedded dashboard, in pixels. In our example, we’re using min-height: 600px;
src – This is the URL of the workbook you wish to embed. To get this, open the workbook on Server/Cloud/Public, select the share option then use the link option. Strip out everything after the first "?". For example:
https://public.tableau.com/views/Regional_16766597857820/GlobalTemperatures?:embed=y&:tabs=n&:display_count=n&:origin=viz_share_link
becomes…
https://public.tableau.com/views/Regional_16766597857820/GlobalTemperatures
We can then add additional parameters to the URL as detailed in previous iFrame sections.
JavaScript Embed API v2
The JavaScript v2 embed code is also quite easy!
The concept is basically the same as the iFrame. We’ll set the width and height of the embed to 100% and it’ll take care of the rest. We only need to set three parameters.
minHeight – Shown in the script as viz.style.minHeight. This is the minimum height of the embedded dashboard, in pixels. In our example, we’re using viz.style.minHeight = "600px";
host_url – This is essentially the root URL of Tableau Server, Cloud, or Public. For example, for Tableau Public, you’d use https://public.tableau.com/
name – This is the “name” of the workbook we’re embedding. To get this, open the workbook on Server/Cloud/Public, select the share option then use the link option. Then extract just the workbook and sheet name (essentially the last two elements before “?:”). For example:
https://public.tableau.com/views/Regional_16766597857820/GlobalTemperatures?:embed_code_version=3&:embed=y&:loadOrderID=0&:toolbar=n&:tabs=n&:display_count=n&:origin=viz_share_link
becomes…
Regional_16766597857820/GlobalTemperatures
We can then add additional parameters to the URL as detailed in previous JavaScript v2 sections.
JavaScript Embed API v3
This one is not as simple as the others, unfortunately. I tested the 100% width and height option with v3 and, no matter what I tried, I could not get it to work consistently. In some cases, the embedded content would not automatically resize (I particularly saw this when the window grew larger rather than smaller). In other cases, it seemed to get stuck at a certain height. I’m not sure if these are by design or some bugs that haven’t been worked out yet, but I eventually gave up on the 100% method used in v2 and iFrames and had to opt for something much more complex.
The code is broken into three segments. At the top, we have a script element which defines what happens when a screen resize event occurs. We then have another script element which the creates the embedded element and loads it. Finally, we have a div object that defines the element. In general, the code is checking the window width and height, then adjusting (with a bit of padding) to fit those widths and heights.
Fortunately, though the code is longer than our other examples, it’s pretty easy to modify. You’ll need to consider the following key parameters:
minHeight – Shown in the script as window.minHeight. This is the minimum height of the embedded dashboard, in pixels. I’ve found that v3 actually seems to do a better job of limiting absurdly short embeds, so by default, I’ve set this to zero: window.minHeight = 0; However, you can change this value to whatever makes sense for you.
vizURL – Set this to the URL of the workbook you’re embedding. To get this, open the workbook on Server/Cloud/Public, select the share option then use the link option. Strip out everything after the first "?". For example:
https://public.tableau.com/views/Regional_16766597857820/GlobalTemperatures?:embed_code_version=3&:embed=y&:loadOrderID=0&:toolbar=n&:tabs=n&:display_count=n&:origin=viz_share_link
becomes…
https://public.tableau.com/views/Regional_16766597857820/GlobalTemperatures
Parameters are added via code. As an example, my code includes the use of the toolbar and hideTabs options. See previous sections for a list of complete options for v3.
Which is Best?
So now that we’ve covered some of the different embed methods and some of the pros and cons of each, let’s discuss which is best.
We’ll start with some specific considerations around iFrames. Many of our iFrame examples were easy to implement which is great, but I think I’ve also shown that, once you get past the most straightforward use cases, iFrames start to break down, forcing you to use hacky CSS techniques when it would be best to just leverage JavaScript. But there are several other potential concerns with iFrames. In recent years, they have created a lot of security concerns as hackers have invented several ways to exploit them (for a good discussion of this, see 4 IFrame Security Concerns You Should Know). There are also other potential issues related to SEO and Google Analytics (though I’ll admit that these may also be an issue with JavaScript—I’m not completely sure).
JavaScript, on the other hand is a bit more verbose, but so much more flexible. Once you step beyond the most straightforward use cases, JavaScript can be very powerful. But should you use v2 or v3? Interestingly, some of our v3 code was simpler than our v2 code, but some was not. That said, which one we use isn’t necessarily just about which one is easier. Version 3 provides several improvements, a few of which are detailed on Introducing a faster, easier way to embed Tableau into products, applications, and portals. For this reason, I intend to use the JavaScript Embed API version 3 for all of my future embeds. As with everything Tableau creates, I expect that it will keep getting better over time.
Closing
When I set out to write this blog, I had no idea how long it would be and how much time I’d have to put into it. But I’m glad I did as I learned a lot during the process. I’m hopeful this resource will help all of those non-programmers out there, like myself, to embed their content without having to be an HTML or JavaScript expert. As a reminder, my full HTML code can be found on Github, working interactive examples can be found on flerlageapps.com, and the embed code can be found on codepen.io.
Thanks for reading this series on embedding Tableau. If you have any comments or suggestions, please let me know!
Ken Flerlage, May 8, 2023
My team and I are trying to figure out if we can see web traffic stats for our dashboards that are embedded to the company's website. These dashboards are published on Tableau Public. Are you aware of any resources for this? Thank you!
ReplyDeleteYour best best would probably be to leverage something like Google Analytics on the website itself. Tableau Public only provides very high level information like total views, but if that's of interest check out our Tableau Public stats service: https://www.flerlagetwins.com/2021/03/stats-service.html
Deletegreat info but do you have tips for embedding metrics into iframes or Sharepoint? All we get is a "tableau refused to connect" error
ReplyDeleteI'd suggest posting this, with a bit more detail, on the community forums. Please feel free to tag me (be sure to note that I said it was okay to tag me).
DeleteWould it ever make sense to combine the Device Layouts and Responsive by creating two different dashboards in Tableau (one for desktop and one for mobile) and then in the embed code using 100% as the viz.style.width for both screen size cases (both sides of the threshold)? I'm thinking that way on a desktop the viz would be responsive but only down to a certain width, at which point it would use the phone layout dashboard. (This could prevent responsive desktop layouts from becoming too squished, i.e. BANs showing ### for example.) Thoughts?
ReplyDeleteYeah, I think that's a really good idea!
DeleteWhen you use the device designer within Tableau Desktop and add and edit a Phone layout, I understand that the choice of which dashboard to display happens on the Tableau Public end? Where the code above initiates that choice based on the window size?
ReplyDelete