Easily create interactive maps from data in Google Spreadsheets. Supports Google Maps, Leaflet, Mapbox, MapQuest, etc.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



Mapsheet.js makes an interactive map out of a Google Spreadsheet. It depends on Tabletop.js and whatever map provider you're using (supports Leaflet, Google Maps, Mapbox (which is basically Leaflet!), and MapQuest).

It is also dead simple.

Optional but fun: Mapsheet supports Handlebars for info window templates.

So how do I do this?

First, you make a published Google Spreadsheet. You can find out how to do this in the Tabletop docs. The only columns you actually need are latitude and longitude. We're also friendly enough to allow lat, lng, long, any probably anything else you can think of.

A pretty full-fledged example might be: let's say you have some restaurants you'd like to map, and you want some info to show up in a popup when you click on the marker. Here goes nothing:

    <!-- We'll need to include Google Maps, Handlebars for templating, and jQuery for general futzing about -->
    <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.min.js"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

    <!-- Tabletop.js for accessing Google Spreadsheets and Mapsheet.js for mapping, of course -->
    <script type="text/javascript" src="tabletop.js"></script>
    <script type="text/javascript" src="mapsheet.js"></script>

    <!-- This is where the map will go -->
    <div id="map"></div>

    <!-- Let's make the map not too big -->
      #map {
        width: 600px;
        height: 500px;

    <!-- This is the popup you'll get when you click a marker. 
         {{these}} are columns in your spreadsheet -->
    <script id="popup-template" type="text/x-handlebars-template">
      <img src="{{image}}">
      <p>{{location}} in {{neighborhood}}</p>

    <!-- Okay, time to do this! -->
    <script type="text/javascript">
      $(document).ready( function() {       
        // Make sure the spreadsheet is published!
        var published_spreadsheet_url = 'https://docs.google.com/spreadsheet/pub?key=0AmYzu_s7QHsmdGNzMnkwbXRyVmdyZGdrWVRoMWRKVGc&output=html'; 

        // Let's get the popup template and compile it using Handlebars
        var source   = $("#popup-template").html();
        var template = Handlebars.compile(source);

        // OK, now let's make the map
        var map = Mapsheet({
          key: published_spreadsheet_url,
          element: "map",
          popupTemplate: template

Most of the code is just including libraries! And if you'd like to map pet stores or murder scenes instead? Just make a different spreadsheet, change the URL, and edit the popup template. Voila: a brand new map.


The Moving Parts

Mapsheet itself

Initialization options

When you initialize Mapsheet you have plenty of options to pick through. key and element are the only two required parameters, though! I've tried to note the ones that are provider-specific.

key is the URL to the published Google Spreadsheet you're dealing with

element is the id of the element that's going to become the map. You can also pass in an element.

click is a callback for when a marker is clicked. this is the default this, the first parameter is the event and the second is the Mapsheet.Point (check the examples!)

fields is an array of columns to display in the info window if you don't feel like using a template. Check the examples!

map is the map, if you feel like rendering it without using a Mapsheet provider.

popupContent is a function that returns content for the info window popup. It's passed the Tabletop model for the given row. It overrides both fields and popupTemplate.

popupTemplate is the id of a Handlebars template that will be used for the info window that pops up when you click the marker on the map. You can also provider the compiled template instead.

provider is the provider of the map service. I detail the providers a bit more below, but your options are


markerOptions are passed through to the marker, and are used for things like specifying marker shadows and other very-specific-to-the-provider details.

titleColumn is the column that you'd like to use as the title of the point (e.g., the name of the place). This is only important if using fields, or if you want hover effects for MapQuest or Google.

callback is the callback for when the map has been successfully drawn. It will be passed two objects: the mapsheet object and the tabletop object. See the Tabletop.js docs if you'd like more info on that part.

callbackContext provides the context of the callback, if necessary.

proxy passes right through to Tabletop.

markerLayer is the layer that you'd like to render your markers on (not supported by Google)

layerOptions are options passed passed to the marker layer if you want a custom backing map, or specify attribution, etc (Leaflet only)


.map() is the rendered map

.points is an array of Mapsheet.Point objects



.model is the Tabletop model of the row the marker is associated with

.longitude() is the longitude, pulled from a column named lng, long or longitude

.latitude() is the latitude, pulled from a column named lat or latitude

.title() gets the title of the marker - this column is set through titleColumn

.coords() gives you the marker's [ lat, lng ]

.get(name) returns the value of the given column. Not that it matters to you, but: Multi-word and capitalized things, like 'Web URL' are fixed up in an attempt to successfully read from tabletop, i.e. converted into lowercase with spaces removed (Web URL turns into weburl).

.content() uses popupContent, popupTemplate, or titleColumn and fields to create content for the info window popup

.isValid() returns true if latitude() and longitude() both return valid floats

.marker returns the raw marker (from Google or MapQuest etc)


Must respond to .initialize(id) and .drawPoints(pointsArray).

Their constructor sets up the options, initialize draws the map, and drawPoints puts the points on it and auto-fits the zoom and bounds.


Google Maps as Mapsheet.Providers.Google (default)

Leaflet (using MapQuest tiles by default, but supports CloudMade, etc) as Mapsheet.Providers.Leaflet (be sure to include the CSS)

MapBox as Mapsheet.Providers.MapBox

MapQuest as Mapsheet.Providers.MapQuest

Customizing Your Map

Styling info windows

All of the info boxes live inside of a <div class='mapsheet-popup'></div>, so feel free to apply styles to .mapsheet-popup h3, etc

Customizing the map itself (roads, water, etc)

You'll need to pick a provider that allows map customization

CloudMade has a billion styles over at their map style editor, you'll just have to check out the cloudmade.html example. You need an API key, but it ain't tough beyond that.

MapBox could also work for you, especially if you have a lot of stuff going on.

Custom Markers

I think it's really stupid that, generally speaking, providers make it so tough to have custom-colored markers. So I tried to make it easy!

Custom markers are supported for Google Maps, Leaflet, and MapBox (to varying degrees).


Custom color: Add a hex color column in your spreadsheet to customize the color of each marker.

Custom icon: If you want to an specify icon for each point, add an icon url column in your spreadsheet. You'll probably want to make it the full path, i.e. http://blahblah.com/images/icons/blah.png

Custom default icon: If want every point to have the same marker, just not the default, you can pass a default icon URL through markerOptions, typically as iconUrl

Custom icon + shadows: Check the examples/leaflet-with-marker-customization.html example, it's complicated.

Provider support

Google Maps: custom colors, custom icons, custom default icon

MapBox: custom icons

Leaflet: custom icons, custom icons + shadows, custom default icon

General notes on using colored/custom icons

If you're unsure of what hex colors are, pop on over to http://www.colorpicker.com or Wikipedia - they're just strings of numbers/letters like FF36A2 that end up as colors.*

When you customize your icons using Leaflet, you'll probably want to pass some markerOptions as well to make sure everything lines up nicely. markerOptions: { iconSize: [32, 37], iconAnchor: [16, 37] } works for the icons from the Map Icons Collection. Read more on the Leaflet site.

Using other Leaflet tile providers

Leaflet defaults to serving tiles from MapQuest, because it's free, and doesn't require an API key. If you'd like to use CloudMade or something instead, you'll need to make some changes. You'll need to pass in a mapOptions along the lines of the following

	mapOptions: {
		subdomains: 'abc',
		tilePath: 'http://{s}.tile.cloudmade.com/{apikey}/{styleId}/256/{z}/{x}/{y}.png',
		styleId: 1930,
		apikey: 'Your CloudMade API Key',
		attribution: 'An appropriate credit line without MapQuest'

And then you should be all set!


There are a lot of examples in /examples, check them out!

If you're looking for the least complicated one, check out fields.html. It isn't too customizable but it gets the job done. leaflet-with-marker-customization.html is the zaniest of the bunch.



Hi, I'm Jonathan Soma. I run the Brooklyn Brainery, and make all sorts of nonsense.


Fix up the docs to actually be nice and pleasant

Don't show popups if there's no content in the popup

Replace the sample map with some quality, dedicated sample maps

Callbacks callbacks everywhere

Notes about styling your infoboxes