Last Updated: 2019-08-12

Developing Data Studio Community Visualizations locally

Data Studio Community Visualizations allow you to build and use your own custom visualizations in Data Studio. Throughout this document, we will call them "components".

This codelab will walk you through one configuration of a local development environment. Review the documentation to learn more about Community Visualizations.

Prerequisites

This codelab assumes that you have completed the "Get Started" codelab.

You should also watch the following videos before starting this codelab.

Introduction to Community Components

Community Visualizations: Developer Tooling Quickstart

Community Visualizations: Converting Existing Visualizations

What you'll learn

What you'll need

Setup

  1. Install node.js if you don't already have it
  2. Download the source code
  3. In your terminal, navigate to the root folder and run npm install

Source Code

The source code in the repo contains two components:

Both components can be found in the same repo:

Webpack

These components use webpack and come with two commands:

The npm run dev command starts the webpack server for local development. The npm run build command generates the files that you need to upload to your cloud environment to deploy your visualization.

Files

Let's take a look at the files you just downloaded:

This is the file structure of the sunburst-drilldown/ directory

├── README.md
├── getdata
│   ├── data
│   │   ├── DS-data-empty.json
│   │   └── DS-data.json
│   ├── getdata.js
│   ├── settings
│   │   ├── getdata.json
│   │   └── manifest.json
│   └── src
├── js
│   ├── d3-common.js
│   └── messages.js
├── package-lock.json
├── package.json
├── sunburst
│   ├── data
│   │   └── DS-data-documentation.json
│   ├── settings
│   │   ├── manifest.json
│   │   └── sunburst.json
│   ├── src
│   └── sunburst.js
├── views
└── webpack.config.js

The purpose of the getdata component is to create multiple sample datasets with Data Studio to use in local development.

Having these datasets locally reduces development time and the likelihood of errors when you upload your component to Data Studio. These datasets make it easier to test requirements of different datasets.

Run the component locally

Before deploying the component to Data Studio, run the component locally. To run the component, type the following command in your terminal:

npm run dev

Open the following page in a browser:

http://localhost:8080/getdata/index.html

You should see:

  1. Click on the download button. You will be prompted with a download window
  2. Save the file as a json file (by making sure it has the extension ".json") in sunburst/data/

The data file

Use a text editor to open the downloaded file. You should see the following JSON:

The sample data follows the object format Data Studio provides.

The JSON contains 5 keys:

This json file allows you to run the sunburst component in your local environment.

In the next section, we will briefly discuss the code included with this component.

Open the getdata/ folder:

├── getdata
│   ├── data
│   │   ├── DS-data-empty.json
│   │   └── DS-data.json
│   ├── getdata.js
│   ├── settings
│   │   ├── getdata.json
│   │   └── manifest.json
│   └── src
│       └── getdata.scss

You will see the following:

Manifest

Configuration file

For this exercise, do not change the config file.

The code

Feel free to review the component source code.

Build and deploy your code

  1. In a terminal, run: npm run build
  2. Deploy the contents of dist/getdata to your Google Cloud Storage bucket.

Once you have deployed the getdata component, add it to a Data Studio report.

Configuration

Data

In the data section of the property panel, add the dimension(s) and metric you'd like to visualize with your sunburst. For example: use the Google Analytics sample data source and add Continent and Country to "Dimension" and Pages / Session under "Metric"

The getdata component will show you the number of records in the returned data.

Style

Make style selections in the property panel. For this component, select a title color, check the "Show Legend" checkbox, and choose a color scheme for the visualization.

Once you are done, switch to view mode. Click the download button from the displayed component and save the file as DS-data-documentation.json in the sunburst/data/ folder.

Once you have downloaded the data, switch back to edit mode, change your data and style selections, and download data files until you have covered enough edge cases.

You are now ready to test the sunburst component locally.

The file structure of the sunburst diagram is similar to the getdata component. There is one additional folder: src/. This folder contains the d3.js code for the diagram, as well as a SASS (CSS) styling file.

The code for the sunburst is provided without explanation, because the focus of this codelab is the local development workflow.

In the next step, we'll discuss the sunburst.js code, which is the bridge between the d3.js library and Data Studio.

├── sunburst
│   ├── data
│   │   └── DS-data-documentation.json
│   ├── settings
│   │   ├── manifest.json
│   │   └── sunburst.json
│   ├── src
│   │   ├── d3-sunburst.scss
│   │   ├── sunburst-data.js
│   │   ├── sunburst-dimensions.js
│   │   ├── sunburst-drawBase.js
│   │   ├── sunburst-drawContent.js
│   │   ├── sunburst-filter.js
│   │   ├── sunburst-legend.js
│   │   └── sunburst-obj.js
│   └── sunburst.js

In this section we will go through the code in sunburst.js.

Local or production?

The two differences between rendering the chart in local and production environment are how data is loaded and how exceptions are rendered.

The code compares the hostname with the value of a variable called "LOCAL". Depending on this value production or development code is executed.

You will probably run the local preview using "localhost://". In that case, no code changes are needed.

If you are using 127.0.0.1 or any other domain name, please change the value of the LOCAL constant in the beginning of the script

const LOCAL = "localhost";

1 - Loading data

When developing locally, the component will try to load the dataset that we just downloaded with our getdata component. In production, it will use the ds-component library and subscribe to the data.

sunburst.js

async function sunburst() {
    if (window.location.hostname == LOCAL) {
        const theDataSet = await d3.json("./data/DS-data.json");
        draw(theDataSet);
    } else {
        dscc.subscribeToData(draw, { transform: dscc.objectTransform });
    }
}

2 - Draw Visualization

There is one more difference between the local and the development code. In production, the component uses try/catch to render error messages. During local development, the component sends error messages to the console.

function draw(data) {
    if (LOCAL) {
        drawViz(data);
    } else {
        try {
            drawViz(data);
        } catch (err) {
            renderErrorMessage(msg.errorTitle, `${msg.generalError} ${err}`);
        }
    }
}

Data Conversion

The d3 library expects the data as an array of objects, with dimensions and metrics combined. The order of the elements does not matter.

Format expected by D3.js:

[
        {
            "Continent": "Americas",
            "Country": "Grenada",
            "Pages / Session": 44
        },
        {
            "Continent": "Europe",
            "Country": "Albania",
            "Pages / Session": 21.4
        },
        {
            "Continent": "Americas",
            "Country": "Barbados",
            "Pages / Session": 18.66
        }
]

Object Format returned by Data Studio:

"DEFAULT": [
    { 
        "dimension": ["Americas", "Grenada"], 
        "metric": [44] },
    { 
        "dimension": ["Europe", "Albania"], 
        "metric": [21.4] },
    { 
        "dimension": ["Americas", "Barbados"], 
        "metric": [18.66]
    }
]

To convert the data, we use the function convertData..

The convertData function does two other things:

  1. Checks for the existence of data
  2. Combines all fields into a single array

Data Check

Data Studio initially runs the script twice, first without any data, and then a second time with data.

In this example, the script only converts the data if it exists, and otherwise displays a message that the data is loading. If you pass an empty dataset to d3, it throws an exception and the user sees a system error message.

Prepare the DOM

Data Studio renders custom components in the HTML body of an iFrame.

D3.js requires the id of the DOM object it selects. The prepareDOM() function ensures that the id of the body tag is set to "body".

const root = d3.select("body").attr("id", "body");

The function also deletes all svg tags to avoid having multiple svg elements in the viz.

If the svg elements are not removed, new elements will be added with any resize event.

d3.select("body")
        .selectAll("svg")
        .remove();

Finally we must remove the tooltip and error messages for the same reason.

d3.select("#error").remove();
d3.select("#tooltip").remove();

Tooltip

D3.js expects the HTML elements for the tooltips to exist. In a website, we could simply create it in the HTML. However, because Data Studio does not give you direct access to the iframe DOM, we use d3.js.

function createTooltip(root) {
    const tooltip = root
        .append("div")
        .attr("id", "tooltip")
        .attr("class", "tooltip");

    tooltip.append("span").attr("id", "title");
    tooltip.append("span").attr("id", "count");
}

Creating the Sunburst object

You are almost ready to call our viz object with the function drawViz(rawData)

One last thing: Check if the chart area is big enough for your visualization. If not, display some kind of message.

getWidth() and getHeight() from the ds-component library does not work in the local setup. To check the chart area, I use my own script imported from /js/d3-common.js.

If convertData returns a data object, you can call

new Sunburst(id, data);

Once a new sunburst object is created, we need to set properties of the object. For this visualization, the properties include:

// Dimensions and Metric of viz
sunburst.metricAccessor = rawData.fields.metric[0].name;
sunburst.dimensionsAccessor = [];
rawData.fields.dimension.forEach((d, i) => {
    sunburst.dimensionsAccessor[i] = d.name;
});

// Color Scheme
sunburst.colorScheme = rawData.style.arcColors.value;
sunburst.colorSchemeReversed = rawData.style.colorSchemeReversed.value;

// Font Color
sunburst.fontColor = rawData.style.fontColor.value.color;
sunburst.fontOpacity = rawData.style.fontColor.value.opacity;

// Draw Legend
sunburst.legend = rawData.style.isLegend.value;

Once all properties are set, this function renders the viz:

sunburst.draw();

Filter

Filter interactions are not covered in this codelab.

Error handling

This visualization provides some error handling for common cases. Error messages are defined in the js/ folder.

The error messages also display an icon. The icon must be defined as a svg, because external images are blocked by the Community Visualizations CSP. To learn more, look at js/messages.js and the renderErrorMessage function in js/d3-common.js.

Test locally

In your terminal, run:

npm run dev

Open your browser and navigate to:

http://localhost:8080/sunburst/index.html

You should see the sunburst diagram

Deployment

If you are satisfied with the visualization, run:

npm run build

Then, deploy the the files from your dist/sunburst/ folder to your own bucket.

If all files are uploaded and set to public, and the manifest.json file is correctly configured, add your new component to a Data Studio report. You can select dimensions, metrics and style options.

The final result should look like this:

Now, you should be able to develop your own data visualizations locally and deploy them to Data Studio.

Next steps?