My client asked me to create simple web data connector for Tableau what would fetch customer data from an external service. Sounds like an easy task, especially as data was provided in JSON format. Unfortunately server generating data doesn’t have CORS enabled so it’s impossible to fetch and process data directly.

What is this CORS all about?

“The Cross-Origin Resource Sharing standard works by adding new HTTP headers that allow servers to describe the set of origins that are permitted to read that information using a web browser.” In plain English it’s all about controlling what is the origin of information that is being parsed through web browser.

Without CORS, including potentially harmless .js file in our script, could lead malicious code (fetched from the external origin) to be run in our browser damaging our system or causing other damage.
for more information please refer to https://developer.mozilla.org/en/docs/Web/HTTP/Access_control_CORS

WDC setup

Tableau provides ready to use SDK with a lot of ready to use examples to speed up your development (http://tableau.github.io/webdataconnector/docs/). It’s recommended to follow step by step guide if it’s the first time you see this Kit or don’t have prior Javascript/coding experience.
The easy part of the project was to properly setup field structure for the Tableau Extract (Web data connectors work on Extract only currently) in self-executing function.┬áChallenge came with fetching the data. After testing couple of APIs I’ve decided to use CORS-Anywhere.HerokuApp.com as it seemed to be most stable one. As most of the free CORS third party tools offer similar functionality, it doesn’t really matter which one you choose. Picked the one which is subjectively best for you.

(function getJSONdata() {

    var d=$.Deferred();
    // Create the connector object
    var myConnector = tableau.makeConnector();

    // Define the schema
    myConnector.getSchema = function(schemaCallback) {
        var cols = [
        {
            id: "Field1",
            alias: "Field1",
            dataType: tableau.dataTypeEnum.float
        },{
            id: "Field2",
            alias: "field2",
            dataType: tableau.dataTypeEnum.float
        }
        ];

        var tableSchema = {
            id: "customerfeed",
            alias: "Customer Feed",
            columns: cols
        };

        schemaCallback([tableSchema]);
    };

    // Download the data
    myConnector.getData = function(table, doneCallback) {

    $.getJSON('http://CORS-Anywhere.HerokuApp.com/http://page-with-json.com',
            function (data) {

                var response =[];
                    //response = $.parseJSON(data.contents);
               

                response = data;               
                tableData = [];

               for (i=0;i<response.length;i++)
               {
                tableData.push({
                    "field1": response[i].field1,
                    "field2": response[i].field2
                });
                
               }

            table.appendRows(tableData);
            doneCallback();
           
            });
    
};

    tableau.registerConnector(myConnector);
 
    $(document).ready(function() {
    
     setTimeout(function(){
        tableau.connectionName = "Customer Data";
        tableau.submit();
    }, 1000);
  
     });


})();

Having that simple file there’s nothing more than pushing it to ftp and reference it as WDC in Tableau.

Seting up the WDC connector

To use this html file as a datasource, you need to navigate to Web data connectors in section in Tableau Desktop and point to file containing function above.

Your data should show as a new datasource ready to be used in Tableau!

 

Drawbacks

It’s quite clear that this solution is pushing data through external service, so therefore it’s not recommended to expose fragile data this way. In this case, processed information was available publicly so it wasn’t much of a problem.