Combining and visualising multiple data sources

Mark McDonald, Developer Relations
March 2014

This map demonstrates loading data from two sources: the polygons are loaded from a public Google Maps Engine table and the data values come from a live query to the US Census API. You can use the controls above the map to select a category of data to display (the "census variable"). The display is then updated to show a choropleth map shading the various US regions in proportion to the values recorded in the census.

How it works

When the map loads, it first queries the Google Maps Engine API to retrieve the polygons defining the US state boundaries and render them using the loadGeoJson method. The controls on the map are used to select a data source and then execute a query against the US Census Data API for the specified variable.

Loading polygons from Maps Engine

The Maps Engine API's Table.Features list method returns resources in standard GeoJSON format so the API response can be loaded directly using loadGeoJson. For more information on how to use Maps Engine to read public data tables, check out the developer guide.

The only trick in the code below is setting the idPropertyName for the data that is loaded. When we load the Census data we'll need a way to connect it with the Maps Engine data based on some common key. In this case we're using the 'STATE' property.

function loadMapShapes() {
  // Note that you will need to provide an API key to access this table
  map.data.loadGeoJson('https://www.googleapis.com/mapsengine/v1/tables/12421761926155747447-14043129889721455791/features' +
      { idPropertyName: 'STATE' });

Importing data from the US Census API

The US Census Bureau provides an API for querying data in a number of ways. This document will not describe the Census API, other than to say that the data is returned in JSON format. We use the state ID, provided in the 2nd column, to look up the existing state data (using the lookupId method of google.maps.Data) and update with the census data (using the setProperty method of google.maps.Data)

function loadCensusData(variable) {
  // load the requested variable from the census API
  var xhr = new XMLHttpRequest();
  xhr.open('GET', 'http://api.census.gov/data/2012/acs5/profile?get=' +
      variable + '&for=state:*&key=YOUR_API_KEY');
  xhr.onload = function() {
    var censusData = JSON.parse(xhr.responseText);
    censusData.shift(); // the first row contains column names
    censusData.forEach(function(row) {
      var censusVariable = parseFloat(row[0]);
      var stateId = row[1];

      // keep track of min and max values
      if (censusVariable < censusMin) {
        censusMin = censusVariable;
      if (censusVariable > censusMax) {
        censusMax = censusVariable;

      // update the existing row with the new data
        .setProperty('census_variable', censusVariable);

    // update and display the legend
    document.getElementById('census-min').textContent =
    document.getElementById('census-max').textContent =

Styling the data

Data can be styled through the use of a Data.StyleOptions object or through a function that returns a Data.StyleOptions object. Here we create a choropleth map by applying a gradient to each polygon in the dataset based on the value in the census data.

// set up the style rules and events for google.maps.Data

function styleFeature(feature) {
  var low = [5, 69, 54];  // color of smallest datum
  var high = [151, 83, 34];   // color of largest datum

  // delta represents where the value sits between the min and max
  var delta = (feature.getProperty('census_variable') - censusMin) /
      (censusMax - censusMin);

  var color = [];
  for (var i = 0; i < 3; i++) {
    // calculate an integer color based on the delta
    color[i] = (high[i] - low[i]) * delta + low[i];

  // determine whether to show this shape or not
  var showRow = true;
  if (feature.getProperty('census_variable') == null ||
      isNaN(feature.getProperty('census_variable'))) {
    showRow = false;

  var outlineWeight = 0.5, zIndex = 1;
  if (feature.getProperty('state') === 'hover') {
    outlineWeight = zIndex = 2;

  return {
    strokeWeight: outlineWeight,
    strokeColor: '#fff',
    zIndex: zIndex,
    fillColor: 'hsl(' + color[0] + ',' + color[1] + '%,' + color[2] + '%)',
    fillOpacity: 0.75,
    visible: showRow

In addition to the coloring, we have created an interactive element by adding events that respond to mouse activity. When you hover your mouse cursor (or finger) over a region with data, the border becomes heavier and the data card is updated with the value being touched.

// set up the style rules and events for google.maps.Data
map.data.addListener('mouseover', mouseInToRegion);
map.data.addListener('mouseout', mouseOutOfRegion);

function mouseInToRegion(e) {
  // set the hover state so the setStyle function can change the border
  e.feature.setProperty('state', 'hover');

  var percent = (e.feature.getProperty('census_variable') - censusMin) /
      (censusMax - censusMin) * 100;

  // update the label
  document.getElementById('data-label').textContent =
  document.getElementById('data-value').textContent =
  document.getElementById('data-box').style.display = 'block';
  document.getElementById('data-caret').style.display = 'block';
  document.getElementById('data-caret').style.paddingLeft = percent + '%';

function mouseOutOfRegion(e) {
  // reset the hover state, returning the border to normal
  e.feature.setProperty('state', 'normal');

This demo uses the Census Bureau Data API but is not endorsed or certified by the Census Bureau.

Send feedback about...

Google Maps APIs
Google Maps APIs