Responsive Design and Embedded Tableau Vizes – responsive_scaling_tableau.js

Web sites have to work on an incredibly wide variety of displays these days. The work to make a single page look as good as possible on all those displays often falls under the heading of “Responsive Design”.

When embedding a Tableau viz into another application, the actual “view area” for the Tableau viz is just one component of a page. In this situation, the view we pick from Tableau really needs to fill the most space of the area it has been allotted on the page. So let’s think a little more deeply about proportions and how we can best fit our embedded vizes given the tools available, and how to tie them all together to give the best possible experience to the end user, with the least effort for our Tableau viz designers.

Tableau recognizes the need for Responsive Design with a feature called Device Designer. It allows you to specify three different layouts, which are called in the system Desktop, Tablet, and Phone. These map well to the situations where you are looking at Tableau Server directly or in the Tableau phone app, and the Tableau viz is assumed to take the full width of the viewing area (and often most of the height). If different layouts exist, Tableau Server will automatically pick a layout based on the view space dimensions it detects.

However, when a Tableau viz is embedded into another page, it lives in a regular HTML div which can be styled using CSS3 and changed dynamically using JavaScript. Web designers regularly use these features to make page elements respond to changes in the viewing area (hence Responsive Design). Modern web browsers can actually scale up or down whatever is in a div without needing the content of the div to change.

Given all these capabilities, what is the best way to get our Tableau content to look its best in a page, regardless of the size or device it loads on?

Summary of Best Practices

  • Use Device Designer to specify several Dashboard layouts in different proportions
  • Use CSS / JavaScript to detect the proportions of the area allocated for the Tableau Viz, then manually control which Tableau Dashboard Device Layout is loaded
  • Use CSS3 transform-scale to maximize the fit of the chosen Device Layout to the available space on the page
  • Use break-point detection to reload the Tableau Viz using a different Device Layout once the available space would be better served by a Viz in different proportions

Now let’s dig into how to make all of this happen.

(more…)

tableau_tools 6: Final Release

This post outlines a bittersweet event: the release of tableau_tools 6, which will also be the final release of the library by me, the original author of the library. My time at Tableau has come to an end, but ownership of this blog and all of the various code will remain with Tableau. As the project has always been open-source under a permissive license, this just means that there won’t be any updates from me, but the project can continue as long as it proves useful to someone.

As always, you can install or upgrade tableau_tools from PyPi.org via pip:

pip install tableau_tools --upgrade

Note: Version 6.0.0 does break some backward compatibility (see below) and you may need to do some slight updates to code that used a 5.0.0 release, or a lot if you are still using 4.0.0.

What is different in version 6?

  • Removal of the old style TableauRestApiConnection class. Only TableauServerRest remains. No functionality is lost but you may need to update old code
  • Added an “API Version Override” so you can set what API version is being used in the URLs. Also removed a lot of “option checks” so the library remains useful even as newer versions of Tableau are released
    • Older versions of tableau_tools had fairly strict checking on options to always match what was available in a given version of the Tableau Server REST API. Unfortunately this also meant the library could get far behind if it wasn’t updated, without the ability to override and force newer versions / options. So those limitations have been removed
  • CREATE and UPDATE Site method refactoring: At some point, the number of possible options for these endpoints made it difficult to cover all the possibilities within the arguments of the method. As part of the “allow future changes” design of version 6, only the site_name and site_content_url arguments will be defined in the method, and then it will accept a Dict for all other options. You will have to check the Tableau Server REST API documentation for valid options.
  • Methods that had all of their possible Filters listed out as arguments, have been reduced down to just take a list of UrlFilter objects, and all of the checking removed. More future proofing – maybe more options will be available you’ll want to take advantage of.
  • Documentation on the basic structure and methods in the README. If anyone wants to take over maintenance, or just needs to implement something newer from a more recent API release, the documentation of the simplest pieces of the library is now available for you to build with.

Thoughts on tableau_tools vs. Tableau Server Client and tableau-api-lib

It’s 2021 (thankfully!), and you are reading this, and probably thinking – why are there multiple libraries for working with the Tableau REST API. It’s a long story, but in essence much of tableau_tools and the content on this blog covering it was written before the Tableau Server Client (TSC) library either existed or was mature enough to cover certain use cases. There is also the tableau-api-lib which is a newer implementation along the original lines of what tableau_tools started out as, and it seems fine for getting work done, but doesn’t seem to have some of the abstraction layers of tableau_tools.

All of the libraries are fit for a wide number of purposes. tableau_tools is distinguished by having two main packages:

  • tableau_rest_api: Equivalent to TSC, used to send Tableau REST API commands
  • tableau_documents: Equivalent to the Tableau Document API , used for modifying the Tableau XML documents themselves

There was a time where tableau_rest_api referenced some of the tableau_documents capabilities, but there are no longer any supported versions of Tableau Server where those techniques were necessary, so either component can be used by itself.

Where is tableau_tools still a strong choice?

  • Dealing with Permissions on Tableau Server: There is a whole abstraction layer dealing with Published Content and Permissions, designed for replicating setups across many sites programmatically.
  • Login Impersonation: Necessary for exposing a restricted form of the Rest API as a web service to the browser. There is even a class designed to be used in Flask or Django just for this purpose
  • XML Document Modification: tableau_documents has more capabilities than the Document API, including updating TDSX / TWBX files with newly generated Hyper files from the Hyper API
  • Very complex searching using XPath queries on the XML results: Tableau Server REST API has a lot more filtering possible through the API than it started with, but there are still plenty of requests that need filtering on the result set, and tableau_tools has those requests built in
  • A learning tool / reference for the XML requests if you are building REST API calls in another language: The logging modes in tableau_tools can spit out the exact URL and XML of both requests and responses in a way that can be reasonably followed. Particularly for complex chains of actions, you can use tableau_tools as a prototype to double-check that your own code is doing the right thing.

If you have any of these needs in your project, then it is worth considering tableau_tools for at least some of the implementation. Otherwise, you should go with the TSC as it is more widely used, available, and supported within Tableau and the partner network.

(more…)

Tableau Localization – Controlling the assigned contentUrl with non-ASCII (extended Latin or CJK) characters in content names

Even though Tableau Server stores the “full names” of published Workbooks, Datasources and Worksheets in Unicode exactly as published, the algorithm used to create the “contentUrl” used in the URL to reference the published content is based only on the ASCII English characters. The algorithm completely drops any non-ASCII character (and a few other non-URL safe characters). If any other existing contentUrl is found, an underscore and numeral is appended at the end.

In European languages with an expanded character set beyond the ASCII characters, the algorithm results in reduced but still distinctive contentUrls. For example (in Spanish):  “Años” -> “Aos”. The risk here, depending on language, is that there may be distinct content names that are reduced to the same contentUrl, resulting in the appending of the numeral to distinguish them like: “Aos” vs. “Aos_1”.

In Chinese, Korean and Japanese (and any other fully non-Latin character sets), the names are reduced to nothing, and then a random number is assigned: “销售运营分析仪表板”-> “_0” or “_1”.

Best Practices

  1. Always publish all Published Data Sources first to a Tableau Server, before publishing Workbooks
  2. Give unique name to all Content you publish, especially Data Sources. Tableau Server allows you to use the same name if Content is in different Projects on the same Site, but this will result in the contentUrls being given “_1” or “_923304292” type endings, with no way to control or change them other than through the names you choose at publish time
  3. If your content is named using non-Latin characters, add additional ASCII text to your names to ensure distinctive and controllable content URLs. This is especially important for Chinese, Japanese and Korean (CJK) text or other fully non-Latin scripts, but also might be necessary in Latin based scripts that frequently use diacritic marks on characters to distinguish (Vietnamese comes to mind)
    1. One solution for CJK languages: Add a transliteration (Pinyin, Hepburn, etc.) in parentheses after the name in the actual script. Alternatively add a unique numeric identifier after a Workbook or Data Source Name, and number your published Worksheets within a workbook.
(more…)

Allowing Only Tableau Vizes with Unrestricted Trusted Authentication, SAML or OIDC

Editor’s Note: Huge thanks to Robin Cottiss who helped me navigate the world of authentication in Tableau as he has for so many years to be able to write this. He doesn’t have the same online presence as a lot of other Tableau wizards but I can’t say how much of my and others Tableau knowledge that is out there has either been guided by or just a straight repackaging of the hard-gained work Robin has put in.

When embedding Tableau vizes for external use, the three most common SSO mechanisms are Trusted Authentication, SAML, and OpenID Connect (OIDC).

Trusted Authentication or Trusted Tickets has two modes, which are set as server-level flags:

  • Restricted (default): A user can only see Vizes, and cannot see the full Tableau Server UI.
  • Unrestricted: Redeeming the ticket creates a full session to Tableau Server, and the user can see the full Tableau Server UI

SAML and OpenID Connect always create a full session, so they work like Unrestricted Tickets.

Additionally, Restricted Trusted Tickets (the default Trusted Authentication mode) also disables:

  • Custom Views
  • Subscriptions
  • Alerts
  • Other interactions with Web Edit, Ask Data, etc.

Many customers would prefer to have a session started with any of the three SSO mechanisms, that allows all the Viz features, but doesn’t let the user ever get to the full Tableau Server UI. Is it possible?

(more…)

Quick Explanation of Row Level Security in Tableau

There’s a great Whitepaper which really goes in depth on how to configure Tableau for Row Level Security, but sometimes it’s nice to have a quick overview that cuts right to the chase. Over a lot of years of explaining how it works, I hope this will outline the standard way of implementing RLS in Tableau in a way that helps you get results as quickly as possible.

Row Level Security is the process of securely filtering data down so a user only see what they should once they are looking at a data source. You could call it “User Data Filtering” just as easily. In essence, you are limiting the returned rows – hence “row level security”.

(more…)

Automating tsm commands in a shell script or cron job on Linux

One of the great advantages of tsm is that it is a fully functioning shell / command-line system that works the same on Linux or Windows. Finding the commands to do what you want to do in Tableau – that’s the easy part these days. But both Windows and Linux have their own quirks, especially when you want to fully automate a process. This post discusses how to get things working on Linux – if you need to automate on Windows, take a look here.

Shell scripting on Linux, particularly when you want to schedule using cron, have a lot more quirks than you’d think at first glance. It’s very common for the same set of commands you just typed in to not work at all when you put them in a shell script. And even then it may still fall over when run via cron. To run tsm commands from a script, we have to make sure our environment is always specified correctly.

(more…)

Forcing Tableau to Re-Query without using Refresh

This question was brought by my fantastisch colleague Timo Tautenhahn, who runs tableaufans.com. He was seeing some performance issues with using the Refresh commands in the JS and Extensions API, but not encountering the issues when changing a filter, which also was causing a new query to the database

In essence, whatever happens when the Refresh command fires off involves more steps than just re-querying. So the question is: what can force a re-query without the Refresh commands?

Solution: Add an Integer Tableau Parameter to a Custom SQL query that doesn’t actually affect the logic of the Query

You can have your own fun coming up with logical statements that are always true, but you don’t need anything more complex than:

SELECT * FROM table t WHERE [Tableau Parameter] = [Tableau Parameter]

As long as you change the value of the parameter to something you haven’t used yet within the session, each change should force a query refresh without using the Refresh action. Simply incrementing up from zero is enough to make it work.

(more…)

Embedding with Tableau Online – 2020 Edition

Given all the updates to Tableau Online over the last few years, now seems like as good of time as any to review over when Tableau Online works for embedding Tableau.

What do I mean by embedding in this case? Specifically, to display Tableau visualizations in another web application, without the customer being aware of Tableau Online as a separate entity from the rest of the web application.

(more…)

Attribute-Based Row Level Security in Tableau, a Working Technique

Tableau has the most flexibility for doing Row Level Security filtering using what is termed the “Standard Method”: a JOIN between a Data Table and an Entitlements table. The basic assumption, as seen in the RLS Whitepaper, is that this Entitlements table exists in the same database at the Data Table. This is a very narrow assumption, that is only true for a small subset of real deployments.

In many environments and applications, there is no “Entitlements” table within the same logical database as the Data table. In fact, there may be no “Entitlements table” that can be reached at all — entitlements can be retrieved somehow, but they may be in any number of forms.

The most common request I see is to pass a set of Attributes (lists or arrays) of values directly into a Tableau report at run-time. The rest of the post will describe a flexible and generic method for making this possible in a secure way. It builds upon the baseline of the PostgreSQL/Python environment in the using a Web Service as a Data Source post, but is even simpler.

(more…)

Trusted Tickets Best Practice Implementation

For a variety of reasons, Trusted Authentication / Trusted Tickets is often the best choice for SSO into a Tableau Server. Trusted Authentication actually establishes a Tableau Session in the browser, so you can use it once to establish SSO for a whole browser session.

In this post, I’ll describe a best practice method for implementing the Session-Level Sign-O and provide a small JavaScript file with actual implementation of all the concepts.

You can find the auth_helpers.js file on GitHub with all the code necessary for this process (except for the back-end Trusted Tickets request, which you need to build in your own web application environment).

(more…)