The ShufflePoint update this week added support for JSON feeds for Google Visualization and iGoogle Gadgets. It is very exciting to finally get around to implementing this. It is definitely satisfying to leverage iGoogle and the great gadgets already available. Any gadget compatible with the Google Visualization API Gadget Gallery http://code.google.com/apis/visualization/documentation/gadgetgallery.html should work with our JSON feed.
We worked hard to get this out quickly because we believe that the combination of Google Analytics with gadgets is not only technically cool, but also will really help with the "democratization" of such mashups by allowing non-technical people to find and share insights from Google Analytics.
The iGoogle use case is pretty self explanatory. But that simplicity comes at the price of not being able to do much in terms of controlling the display. I know that being a developer means I am biased, but I much prefer to use the gadgets in the context of the Google visualization API where their full richness is exposed. So I thought it important to blog about this - starting with really simple examples and then building up some more interesting examples. The end result should be that a) you see this is not that hard, and b) you see that it is worth the effort.
At the end of the article there are links to the live sample pages.
Pattern 1: The 6 steps to a gadget
The first code sample (Listing 1) is a complete html page which shows a bar chart from a simple GAQL query of entrances by medium. The pretty-printed query is:
SELECT METRICS ga:entrances ON COLUMNS DIMENSIONS ga:medium ON ROWS BY ga:entrances DESC FROM [www.activeinterface.com] WHERE TIMEFRAME yearToDate
The resulting display is:

The comments annotate the six steps to getting a gadget using the visualization API. These steps are now individually explained.
step 1: specify a data provider
This line is where you specify where the data will be retrieved. The single parameter to this function is a URL which you can get from the ShufflePoint query tool [INFO: goto "Google Gadgets" tab, select "Visualization Gadget Provider", and click "Generate"] .
step 2: set the query
This is where you can put a GAQL query to select metrics and dimensions of interest. Not much to say about it other than you can either hand-code it into a page or you can copy and paste it from the query tool. Note that any double quotes in the query will have to be escaped (e.g.: SELECT METRICS \"this is a literal\" …)
step 3: send the query to the provider
It is at this point that the request goes out to the provider. In this code sample, the result is handled by an anonymous function which is the parameter to the send function.
step 4: get the data returned by the provider
This step gets the data table with our query result. Much of the richness and power of the visualization API exists within this data table. Subsequent samples will explore this class further.
step 5: create the gadget to receive the data
Different visualization gadgets are created with different functions. The gadget constuctors take as a parameter a page element into which the gadget will render itself. You must load the packages for the gadgets you indent to use. I will typically only load the gadgets which will be used subsequently in that page because I assume that that is more efficient in terms of memory and startup time.
step 6: draw the chart
The last step is to direct the chart to draw itself. The draw method takes two parameters. The first is the data table. The second (empty in this sample) is a set of chart options.
So that, in a nutshell, is how one would write a web page to draw a chart (or table) using ShufflePoint and the Google Visualization API. Everything else is an elaboration on this pattern.
Pattern 2: Eliminating the anonymous function
Some people find those anonymous functions too weird. Listing 2 shows the pattern for using the visualization API with a named callback function.
Also shown in this example are some of the chart options which can be set using the second parameter to the chart.draw() function. The documentation includes for each gadget the list of available configuration options. For example, the bar chart configuration options are given at http://code.google.com/apis/visualization/documentation/gallery/barchart.html#Configuration_Options. Further down on that page are listed the methods and events exposed by the bar chart. For example, you can get an onmouseover event when the user mouses over a bar, and a select event when the user clicks on a bar or legend entry.
Pattern 3: Two gadgets on a page
Placing two gadgets on one page is mostly a cut and paste operation. In Listing 3 there are two charts - one for pageviews and one for visits. The visits chart has bars stacked by continent. To have two dimensions in a chart like this, you GAQL query must have a dimension on the columns and on the rows axis. The query for the second chart is:
SELECT DIMENSIONS ga:continent ON COLUMNS BY ga:visits DIMENSIONS ga:medium ON ROWS FROM [www.activeinterface.com] WHERE METRICS ga:visits TIMEFRAME yearToDate
The resulting display is:

When adding the second chart, I first moved the data provider URL into a variable since it is the same for both gadgets. In this sample, the gadgets are both rendering into the same div element. If you wish to have more control over the placement and layout of your charts, you can give each gadget its own div element.
Listing 4 has the second chart in the page replaced with a table gadget. The Google Table is a really cool and, I think, underappreciated gadget. In a subsequent sample I will explore this gadget further. The table gadget supports some nice interactivity, such as row mouseover highlight, row selection, and column resorting.

Having a table and a chart together showing the same result table can be very effective. And using the even handler on the table, it is simple to make the chart resort when the user clicks the table columns. The result is that the sorting is kept consistent between the table and the cart. Listing 5 has the full example. The key addition is the registering of an anonymous event handler for the sort:
google.visualization.events.addListener(table, 'sort',
function(event) {
dataTable.sort([{column: event.column, desc: !event.ascending}]);
chart.draw(dataTable, {width: 600, height: 300, is3D: false, reverseAxis: false, title: 'Visit metrics by continent', legend:'right'} );
});

Pattern 4: Multiple charts mixed with web content on a page
A well-designed web or printed page may have lots of copy with a couple floating chart elements referenced within the copy. For this example, I am going to use the Google Image Chart instead of the vector chart gadget. The image charts have some advantages over the gadgets. First, they just look better. Second, they really are images - so there is no issue with their display on smartphones, and the user can copy and paste the images into Word or PowerPoint docs. The downside is the loss of interactivity.
Displaying an image chart is admittedly more work than displaying a gadget. All of the information which describes the chart must be specified in the IMG element SRC attribute. The final URL can look pretty scary. Here is the URL generated for the sample page.
http://chart.apis.google.com/chart?cht=bhg&chs=320x240&chds=0,500&chd=t:113.000,113.000,122.000,127.000,143.000,159.000,160.000,221.000,227.000,424.000&chxt=x,y&chxr=0,0,500&chtt=New visits for top 10 states&chxl=|0:|0|100|200|300|400|500|1:|California|New York|Texas|Pennsylvania|Illinois|Washington|Florida|Virginia|Massachusetts|New Jersey&chco=336798|336798|336798|336798|336798|336798|20cb27|336798|336798|336798&chbh=a,6,6
You would not be hand-crafting such an URL. Instead, you will end up developing some fairly generic JavaScript code for turning a datatable into such an URL. In Listing 6, the function createImageChartUrl() does just that. The HTML has an IMG element with no SRC specified. The function builds an image chart URL and then assigns the SRC attribute. Having the alt attribute as "Please wait..." is a good way to convey to the user that something is happening.
The resulting display is (note: this is an image - see links at bottom of posting for live samples):

This great looking chart is being created on the fly from a GAQL query against the Google Analytics API. I like gadgets, but I have to admit that most of my Google charting uses image charts because they look so good.
Pattern 5: derived tables and calculations
The final pattern I want to share in this article is about leveraging the data table object. This object was cracked open a little bit in the previous sample since I had to iterate the table rows while building the chart URL. But the datatable has many more capabilities. Several of them will be used in the example I will now share.
My objective with this page is a table which shows the change in the value of a metric from one time period to another. For this example, I use a query which shows visitor browser for 2007 and for 2008:
SELECT DIMENSIONS ga:year ON COLUMNS DIMENSIONS ga:browser ON ROWS FROM [www.activeinterface.com] WHERE METRICS ga:newVisits TIMEFRAME 2007-01-01:2008-12-31
The page in Listing 7 has two tables. The first has all the rows returned from the query along with the addition of two columns with computed percentages. The second table has the top 5 browser by 2008 percentage and another column showing the change in percent from 2007 to 2008.
Some key points to note from the JavaScript. First, you will observe here extensive use of the Google datatable object's methods. The query returns a table with variable name "data". This table is then augmented with two additional columns using the datatable addColumn() method. In the loop which computes the percentages, the new columns are populated with values and formatted values using setValue() and setFormattedValue() respectively.
Another key pattern employed here is the creation of second datatable named data2. This datatable is created from scratch and will be the source data for the final display (note that in the sample I also display the first table just for reference. Normally only the second table would be shown). Since I want only the top 5 browser by percent, I have to use another datatable method getSortedRows() which returns an array of the row indexes for the first table. This method takes a sortColumns parameter which has an overloaded type. I pass in an object which says sort descending by the 3rd (2008 percent) column.
Also note in this table the use of a ColorFormat object to color the change text red or green depending on the sign. There are many useful formatters available in the Google Visualization API. The are documented here.

Summary
This article was admittedly pretty heavy on the technical side. The goal was two-fold. First, show what can be done with gadgets and image charts. Second, provide ShufflePoint users with a how-to reference for doing some typical gadget programming tasks.
Live samples
Listing 1 : Entrances by Medium
Listing 2 : Callback instead of anonymous function
References
http://code.google.com/apis/chart/
Google Chart API (image charts)
http://code.google.com/apis/visualization/documentation/gallery.html
Google Visualization API gadget gallery
http://code.google.com/apis/visualization/documentation/reference.html
Google Visualization API Reference
Excellent example of how easy it CAN be to get GA data in nice format on a web page.
Is anyone reading these blog posts?
You guys are doing some of the coolest GA API integration stuff out there and I'm a bit surprised it's not making more noise.
You need better marketing people :)
- Ophir
Posted by: Ophir Prusak | June 04, 2009 at 11:54 AM