Collaborator8.2-Blog-CTA-Demo

How to Use Google Chart Tools with Web Applications

Google Charts makes it easy to show data visually and beautifully. You can show historical trends or by categories. Depending on the data your site gathers, you can show which users have the best reputation, which products sell best, or which topics are most active. You can display data with pie charts, bar graphs, or area charts. You could even display a map showing the importance of each country or city when looking at the number of users or the amount of time and money they spend on your site.

Want to take advantage of these cool capabilities? In this article, I show you the process.

How well is your site doing? What can you tell about your users and how they use your site? In the era of Lean Development, we developers (and our bosses and clients) want to know more about what our website is doing, how well it’s doing it, and how the users are using it. Ideally this guides us in selecting features to emphasize, where to focus development efforts, and when to perform system maintenance.

Nothing beats visualization to show us what we need to know at a glance. This is where Google Chart Tools come in: making pretty pictures out of often-dry data. The tools offer a variety of charting options, from the ubiquitous bar chart to the “geomap,” a map showing the relative importance of each country or state.

Just a little taste

Google Chart Tools can be quite powerful, but we can start with a simple chart quickly. Here is an example of the HTML and JavaScript code to create a basic pie chart:

<div id="my_chart" style="width: 500px; height: 300px">
</div>
<script type="text/javascript" src="https://www.google.com/jsapi"></script> 
<script>
   google.load("visualization", "1", {packages:["corechart"]});
   google.setOnLoadCallback(drawChart);
   function drawChart() {
    // Create and populate the data table.
    var data = google.visualization.arrayToDataTable([
      ['Flavour', 'Percent'],
      ['Apple', 17.36],
      ['Strawberry Rhubarb', 15.62],
      ['Pumpkin', 13.63],
      ['Cherry', 11.25],
      ['Blueberry', 7.53],
      ['Lemon Meringue', 6.45],
      ['Chocolate', 3.97],
      ['Chess', 1.46],
      ['Other', 7.09]
    ]);
    var options = {
      title: 'What is your favorite pie flavor?'
    };
     // Create and draw the visualization.
    new google.visualization.LineChart(
      document.getElementById('my_chart')).draw(data, options);
  }
</script> 

This gives us the following chart using data from NPR as a data source:

Google Chart - What is your favorite pie flavor?

There are two important parts in the sample above: the <div> that holds the chart, and the code that generates it.

The first script is the Google Loader, which lets you use JavaScript to decide which pieces of the various Google APIs to load, instead of having to sprinkle your page with <script> tags. Google Loader also loads the scripts asynchronously, so the whole page loads faster. In this case, we load the basic JavaScript classes, data structures, and code that implement the core aspects of visualization, and “corecharts,” a package that contains the basic chart types.

You can also load each chart type individually if want to minimize resources on the client’s system. Loading “corecharts” means I can change chart types easily, without changing the load statement. During the exploration phase of development, I like to optimize for programmer time. This way, I can change the line

        new google.visualization.PieChart(

with

        new google.visualization.BarChart(

 

and get a different chart:

Google Chart Bar Graph - What is your favorite pie flavor?

Or

        new google.visualization.LineChart(


Google Chart Line Graph

In this case, the obvious and possibly redundant chart of choice is clearly the pie chart.

Loading data

Google Chart Tools uses a DataTable JavaScript object to hold the data to be visualized. There are a number of ways to create and populate this object.

As we saw in the example above, the easiest way is to convert an array to a DataTable. Actually, we start from an array of arrays. The first element of the array is the header line, an array of strings. Every element after that is an array of values. For our pie chart, these values are a string and a single numeric value. Other chart types (such as line or bar charts) work with more values, representing each column with a different color line or bar, or bubble, etc. The first element of each data row is the label, and it’s often a string or a timestamp.

For an example with multiple values, let’s graph the average snowfall per month in a few American cities:

var dataAsArray = [
  [‘DATA THROUGH 2002’,    ‘JAN’, ‘FEB’, … ‘NOV’, ’DEC’],
  [‘ANCHORAGE, AK’,         10.4,  11.7, …  10.8,  15.2],
  [‘DETROIT, MI’,           10.6,   9.0, …   2.7,  10.0],
  [‘KEY WEST, FL’,           0.0,   0.0, …   0.0,   0.0],
  [‘NEW YORK (JFK AP), NY’,  6.7,   7.7, …   0.3,   3.8],
  [‘TUCSON, AZ’,             0.3,   0.2, …   0.1,   0.3]
];

 

which, when put in a bar chart, gives us:

Google Chart bar graph snowfall by city

You can also create and populate the DataTable by hand. You instantiate the object with new (as you would other JavaScript objects), then use addColumn() for each column of data, and addRow() or addRows() to add the actual data. This way of specifying the data gives you more flexibility on some of the aspects of the charts generated. For example, if your data contains dates or the time of day, calling addColumn and specifying the data type makes sure the data is displayed correctly.

With this method, you can also generate the content dynamically, rather than work with a fixed dataset:

var data = new google.visualization.DataTable();
 
data.addColumn('number', 'Initial Value');
data.addColumn('number', 'Doubled');
data.addColumn('number', 'Squared');
data.addColumn('number', 'Plus 50');
 
var x;
for (x = 0; x <= 10; x++) {
  data.addRow([x, 2 * x, x* x, x+50]);
}

which gives us:

Google Chart waterfall graph

Finally, the most powerful way to populate the DataTable object is to load it from a remote source, using AJAX. Unfortunately, pulling the data from AJAX requires a little bit of work; there is no simple method you can call and let the magic happen, so you need to write a bit of code.

AJAX, as you already know, means “Asynchronous JavaScript and XML.” There’s the dreaded word:  asynchronous. Asynchronous programming isn’t always easy. It almost always requires callbacks, which can get confusing. In the examples so far, we already use a callback, to tell the Google API to fire off the drawChart() function once all the library pieces are loaded.

Now, we have to insert a step between that moment and when we draw the chart. In this new step, we load the data we want to use through an AJAX call, and pass the data to our drawChart() method.

<script>
  google.load("visualization", "1", {packages:[geochart"]});
  google.setOnLoadCallback(loadFromAJAX);
 
 
  function loadFromAJAX() {
    var xhr = new XMLHttpRequest();
    xhr.open( 'GET', 'countryPopulation.json', true);
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    xhr.onreadystatechange=function(){
      if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 0)){
        var dataFromJSON = JSON.parse(xhr.responseText);
        drawChart(dataFromJSON)
      } else if( xhr.readyState === 4 && xhr.status !== 200 ){
        document.getElementById('my_chart').innerHTML = "Error loading data: " + xhr.statusText;
      } else {
        // loading... Display message to user
        document.getElementById('my_chart').innerHTML = "Loading... “
      }
    };
    xhr.send(null); // we're not adding any data to our request - it's a simple GET
  }
 
  function drawChart(dataObject) {
    var data = new google.visualization.DataTable();
    data.addColumn("string", "Country");
    data.addColumn("number", "Population in millions");
    data.addRows(dataObject);
 
    // Create and draw the visualization.
    new google.visualization.GeoChart(
      document.getElementById('my_chart')).draw(data, null);
  }
 
</script>

If you are testing this code by loading the HTML file from your own computer, without using a Web server, you may not be able to load the JSON file without jumping through some hoops. Some browsers do not let you load files through AJAX when the document is loaded locally. If you are using Chrome, you must start it from the command line with the --allow-file-access-from-files parameter to get around the restriction. With Internet Explorer, you need to change

new XMLHttpRequest()”

with

new ActiveXObject("MSXML2.XMLHTTP.6.0");”

to get the same result. Safari and Firefox let you load the document happily, but they do not set the xhr.status to 200 (which makes sense; seeing how the document wasn’t loaded with HTTP, it should probably not return an HTTP code).

This is why I checked that xhr.status is either 200 or 0 in the onreadystatechange function/callback. Normally, you only want to proceed with drawChart if the status is 200, but we’re just playing with our chart for now, so we can relax the rules a bit, right?

The last step to make this work is a data file called countryPopulation.json which looks like

[
  ["China", 1354],
  ["India", 1210],
  ["United States", 315],
  ["Canada", 35]
]

and we get this very pretty picture:

 

JSON data into the DataTable ourselves, the actual format is not that important. We only need to write the code that turns our format into calls to build the DataTable. One common format has metadata at the top level of the JSON object, and an array that holds the data. In that case, the call to draw the chart would look like

drawChart(dataFromJSON.results)

Why would you want to go through all this trouble to fetch data through AJAX? You can just generate it into your HTML page with JSP, PHP, etc., so why the extra trouble? It all depends on the nature of the data. If all you have is a flat data file that’s never updated, then the only reason to use AJAX is because you like doing the programming equivalent of playing in the mud: It’s messy, but it’s fun. Where it becomes useful is when the data is dynamic. You could, for example, have files representing your company’s sales over the last 10 years, and you load the file corresponding to the year the user selected. Another advantage is that by fetching data through AJAX instead of loading a whole new page (which you would have to do with JSP or PHP), the response is much faster if you load additional files of data, say in response to user interaction.

Where using AJAX gets even more powerful is when, instead of loading a file, you call a web service that generates the data for you, likely from a database. That service may take parameters to refine the data, such as a date range, or the flavour of cupcakes sold, or the demographics of the user who tried a new feature on your site.

There is one more way to load data into your chart: You can get the data from the cloud. You can query a Google Spreadsheet or other data sources that support the Chart Tools Datasource protocol. That is beyond the scope of this article; see the documentation for details.

Back end support for AJAX calls

If you have control of the application’s back end, you can devise the web service that generates the data to be as powerful as you need. When deciding what to graph, consider the data you already have, and the data you can collect. Ask yourself how you may arrange that data to tell a story, or try to find fun questions to ask of it. If you recently implemented a new feature to send email reminders to users, who has set up more reminders, men or women? Younger or older users? Do users with a gmail.com address spend more money on your site than users with a hotmail.com or yahoo.com address? You may find that you want to record more information about your users’ behaviour, but you can likely start with what you have. Once your boss or client sees what you can do, it will be easier to get additional development approved.

When crafting the database queries to answer those questions, make sure you set up some reasonable default date ranges. That way, if the user did not ask for a specific time frame, you don’t tally all the data ever gathered, much of which is probably not relevant anymore. Also consider your tables and indexes; your schema may benefit from an index that starts with the date/timestamp you query on. You usually want the timestamp as the first (or only) column in that index, since that lets the database exclude the most data faster. This is particularly relevant as time goes on, since you’ll have more and more data.

If your queries use more than one table, be sure to optimize for the join condition too. The speed of execution of the queries becomes more important as more people use your cool new charts more often. As in all things, however, consider the place of these queries in the whole system, and optimize for the overall good of the system.

To group data per day of the week or hour of the day, you need to refer to your database’s date handling functions; they tend to differ between database engines. For example, in MySQL, I found out which days were more lucrative for my clients with

select dayofweek(date), sum(amount) from transaction group by dayofweek(date);

Manipulating data on the client side

You don’t have access to the back end to create a data service? You don’t want to spend your server’s precious cycles computing data for pretty pictures? You just don’t have enough data to bother? That’s okay; you can also process the data on the client side.

The DataTable object in the previous examples is the basic object used to represent chart data. It is a mutable list of rows of data, with each row organized in columns of predefined format. You can add columns and rows programmatically or change the values in the cells (at a specific row and column). Redraw your chart to show the changes.

The DataView object is another way to pass data to the chart. Like a database view, it represents a specific “take” on the data in a DataTable. You can use the DataView to hide columns or rows, to filter the rows, or to sort them. You can also use a DataView to add computed columns. For example, tally the results of a bake sale where the students decided on the price of the baked goods. Given a DataTable with the number of items sold and the money earned by each student, you can also chart the items’ unit price. We can choose to display only the students who sold at least 10 items, by first getting a list of the matching rows (from the DataTable) using the getFilteredRows() method, and passing it to the DataView’s setRows() method.

While you can modify an existing DataTable to add computed columns and perform other manipulations, using the DataView lets you leave the original data unchanged. To add controls next to the chart to change filter options or to hide and show columns, you can just create a new view and redraw the chart. It also means that you do not need to duplicate all the data each time you change the chart’s parameter. Your users (or at least their browsers) will feel better for it.

Another way in which you can effectively manipulate the data is by adjusting the axes on your chart. By default, the Google Chart Tools find the best range for the axes by looking at all the data being charted, and making sure it all fits nicely. But you can override that setting by providing minimum and maximum values for the axis, or by requesting that a logarithmic scale be used, if the data warrants it.

In our bake sale example, if we were to chart the total amount earned by students on the same scale as the unit price, we would barely see the unit price, as it’s so small. What we can do is set up a second axis, and assign each data series (each column) to one axis or the other.

Our last example shows some of these client-side manipulations:

    <script>
    google.load("visualization", "1", {packages:["corechart"]});
    google.setOnLoadCallback(drawChart);
 
    function drawChart() {
 
        var dataAsArray = [
           ["Student", "# items sold", "$ earned"],
           ['Alice', 40, 40],
           ['Bob', 20, 20],
           ['Catherine', 10, 30],
           ['Danny', 5, 50],
           ['Eva', 20, 20],
           ['Felipe', 50, 25],
           ['Gwen', 7, 15],
           ['Henry', 25, 25]
        ];
 
        var dataTable = google.visualization.arrayToDataTable(dataAsArray);
 
        var dataView = new google.visualization.DataView(dataTable);
        var computeUnitCost = function(dataTable, rownum) {
            // Compute $ earned divided by # item sold. DataTable columns are 0-based indexes
            return dataTable.getValue(rownum, 2) / dataTable.getValue(rownum, 1)
        }
        // 0-based indexes
        dataView.setColumns([0, 1, 2, {calc: computeUnitCost, type:'number', label: "Unit cost"}])
 
        // filter the rows to only take students who sold at least 10 items
        dataView.setRows(dataTable.getFilteredRows([{column:1, minValue: 10}]))
 
        var options = {
            title: "Bake sale results",
            vAxes: { 0: {logScale: false},
                     1: {logScale: false}},
            series: {0: {targetAxisIndex: 0},
                     1: {targetAxisIndex: 0},
                     2: {targetAxisIndex: 1}},
        };
 
        // Create and draw the visualization.
        new google.visualization.ColumnChart(
                document.getElementById('my_chart')).
                draw(dataView, options);
    }
 
    </script> 

Google Chart bar graph bake sale results

Presentation Options

We have seen a few of the chart types available. You should look at the documentation and the playground to see all the options.

There are two implementation styles. All the ones I showed you use SVG or VML to create the chart. That is, the chart code modifies your document’s DOM to display the chart. This makes it possible to interact with the DOM elements in the chart to show additional information. Chart types using this implementations are those Google recommends and maintains.

The other implementation style, “images,” gathers all the data, and uses it to call a Google service to generate an image file representing the chart. ImageBarChart, ImageLineChart, and ImageCandlestickChart are examples of this implementation style. Google officially deprecated them last year, but they remain available. If you really want to use these charts, review their deprecation policy first.

You can style your chart by selecting its size and color (or colors), and passing those as entries in the options object you pass to the chart’s draw() method. Each chart type also has other parameters that can be tweaked, such as the location of the chart legend, or the part of the world visible on the GeoChart. Refer to the documentation for each chart type for the complete list of options it accepts.

With all these options, what will you chart? More importantly, what will it tell you about your site? It wouldn’t be the first time that a little bit of visualization confronts long held, yet inaccurate beliefs!

About the author:

Nancy Deschênes has been developing for the Web for more than 15 years. In that time, she has worn many hats, acting at times as a front-end developer, database specialist, and (her favorite) application architect. She has used several technologies, mostly Java and the Spring MVC framework, but has recently spent most of her time using the Grails framework. She is the technical co-founder of myTurn.com, a platform for online rental of physical goods.

See also:











Comments

  1. Erich Zolmann says:

    You might want to consider the elephant in the room when you use any Google free service. The free charting tools are bait for Google to obtain more URLs for their web crawler.  
     
    There are massive privacy concerns un addressed here.

  2. Każdy spośród nas zetknął się z faktem, doradzam zapoznanie się z
    faktem.

  3. Bardzo fajowy post, drobiazgowe zapisy polecam wszystkim
    literaturę

  4. I’m not that much of a internet reader to be honest but your
    blogs really nice, keep it up! I’ll go ahead and bookmark your site to come back in the future.
    Many thanks

Speak Your Mind

*