Combining and visualising multiple data sources

This map demonstrates loading data from two sources: the polygons are loaded from a GeoJSON file 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 loads a GeoJSON file containing 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.

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

function loadMapShapes() {'states.json', { 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 does 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();'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'mouseover', mouseInToRegion);'mouseout', mouseOutOfRegion);

 * Responds to the mouse-in event on a map shape (state).
 * @param {?google.maps.MouseEvent} e
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 + '%';

 * Responds to the mouse-out event on a map shape (state).
 * @param {?google.maps.MouseEvent} e
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