Tutorials
intermediate
No code

Get started with Mapbox Boundaries

Prerequisite

Familiarity with front-end development and access to Mapbox Boundaries.

Note

Access to the Mapbox Boundaries tilesets is controlled by Mapbox account access token. If you do not have access on your account, contact Mapbox sales to request access to Boundaries tilesets.

Mapbox Boundaries is a family of vector tilesets that serve various data visualization needs. With Boundaries, you can connect your own tabular data with a managed set of geographical features representing various types of boundaries such as administrative divisions or postal code areas.

This tutorial introduces the key concepts you need to understand when working with Mapbox Boundaries including how to:

  • Add Boundaries to a style template
  • Use the metadata lookup tables
  • Create a basic data visualization

image of the Mapbox Boundaries tileset in x-ray mode

Getting started

There are a few things you will need before you get started:

  • Access to Mapbox Boundaries. Access is controlled by your Mapbox account access token. To request access to Mapbox Boundaries, contact Mapbox sales.
  • Mapbox Boundaries lookup tables. These JSON & CSV files are delivered to you when you buy access to Boundaries and provide extra information about features that is not directly available in the vector tiles.
  • Mapbox GL JS version 1.6.0 or newer. If you want to integrate Boundaries v3 into an existing application, you may need to upgrade your version of Mapbox GL JS.
  • A text editor. Use the text editor of your choice for writing HTML, CSS, and JavaScript.

About Mapbox Boundaries

There are a few key concepts to get familiar with as you start working with Mapbox Boundaries.

  • Data types. Mapbox Boundaries data is categorized into several broad types based on the functions the boundaries serve, such as administrative or postal. See the vector tile reference for a list of supported data types and their definitions.
  • Data levels. Within each data type, features are organized into a hierarchy of different numbered levels. Typically, larger-numbered levels will nest under smaller-numbered levels. For example in the United States, counties (admin level 2) are subdivisions of states (admin level 1), which are subdivisions of the country (admin level 0). The number of levels available will differ by country and data type.
  • Tileset IDs. Mapbox Boundaries are stored as vector tiles and distributed via the Mapbox Vector Tiles API, with unique tilesets for each combination of data type and level. Tileset IDs for Boundaries tilesets are in the form mapbox.boundaries-{type}{level}-{version}. See the vector tile reference for a full list of all the available tileset IDs.
  • Feature IDs. Each feature has a numeric identifier that is unique across all the Mapbox Boundaries tilesets.
  • Feature lookup tables. Mapbox Boundaries vector tiles contain feature shapes and IDs, but most of the other parts of the data are only available as separate JSON or CSV files. To make full use of Mapbox Boundaries you will need to work with a combination of vector tilesets, the provided lookup tables, and your own custom data. We'll cover what this means in more detail later in this tutorial.

Create a map

You will create a map using Mapbox GL JS.

Open your text editor and create a new file named index.html. Set up this new HTML file by pasting the following code into your text editor. This code creates the structure of the page. This code imports Mapbox GL JS in the <head> of the page. The Mapbox GL JS JavaScript and CSS files allow you to use Mapbox GL JS functionality and style.

There is a <div> element with the ID map in the <body> of the page. This <div> is the container in which the map will be displayed on the page.

<!DOCTYPE html>
<html>

<head>
  <meta charset='utf-8' />
  <title>Mapbox Boundaries Tutorial</title>
  <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
  <!-- Import Mapbox GL JS -->
  <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.js'></script>
  <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.css' rel='stylesheet' />
  <style>
    body {
      margin: 0;
      padding: 0;
    }
    #map {
      position: absolute;
      top: 0;
      bottom: 0;
      width: 100%;
    }
  </style>
</head>

<body>

  <div id='map'></div>
  <script>
    // Be sure to use a token from an account that has access to Boundaries
    mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';

    var map = new mapboxgl.Map({
      container: 'map', // The container ID
      style: 'mapbox://styles/mapbox/light-v10', // The map style to use
      center: [-99.9, 45.1], // Starting position [longitude, latitude]
      zoom: 2 // Starting zoom level
    });
  </script>

</body>

</html>

Add a Boundaries layer

Now you have a basic map template set up, but you still need to add Mapbox Boundaries to the map. To do this, use map.addSource to add a Boundaries tileset to the map, then use map.addLayer to apply a style to the data.

Here is an example adding the admin-1 polygon tileset and styling it with a basic fill.

map.on('load', function() {

  // Add source for admin-1 Boundaries
  map.addSource('admin-1', {
    type: 'vector',
    url: 'mapbox://mapbox.boundaries-adm1-v3'
  });

  // Add a layer with boundary polygons
  map.addLayer(
    {
      id: 'admin-1-fill',
      type: 'fill',
      source: 'admin-1',
      'source-layer': 'boundaries_admin_1',
      paint: {
        'fill-color': '#CCCCCC'
      }
    },
    // This final argument indicates that we want to add the Boundaries layer
    // before the `waterway-label` layer that is in the map from the Mapbox
    // Light style. This ensures the admin polygons will be rendered on top of
    // the
    'waterway-label'
  );
});

Add a worldview filter

The Mapbox Boundaries tilesets provide multiple worldview options in each tileset. That means that there are multiple versions of certain features, each intended for a different audience. Filters on each style layer determine which worldview you show.

You should add a worldview filter to every Boundaries layer you add to a map. Since you might add more Boundaries layers to this project later, it makes sense to define the filter as a variable. Here's what the JavaScript code looks like with that added:

map.on('load', function() {

  // Add source for admin-1 Boundaries
  map.addSource('admin-1', {
    type: 'vector',
    url: 'mapbox://mapbox.boundaries-adm1-v3'
  });

  var worldviewFilter = [
    "any",
    ["==", "all", ["get", "worldview"]],
    ["in", "US", ["get", "worldview"]]
  ];

  // Add a layer with boundary polygons
  map.addLayer(
    {
      id: 'admin-1-fill',
      type: 'fill',
      source: 'admin-1',
      'source-layer': 'boundaries_admin_1',
      filter: worldviewFilter,
      paint: {
        'fill-color': '#CCCCCC'
      }
    },
    // This final argument indicates that we want to add the Boundaries layer
    // before the `waterway-label` layer that is in the map from the Mapbox
    // Light style. This ensures the admin polygons will be rendered on top of
    // the
    'waterway-label'
  );
});

You now have a map style with Mapbox Boundaries that's ready to have custom data joined into it.

Feature lookup tables

Each boundary feature is indexed in a lookup table. Lookup tables are designed to be used locally in your application. User data can be joined to Mapbox Boundaries in your application to create a visualization, such as a choropleth map of unemployment by state.

The lookup tables are organized by data type and level and are provided in both JSON and CSV format. The different formats contain the same information; you can use whichever one is better suited to your workflow.

About feature lookup tables

The Mapbox Boundaries lookup tables include this metadata about each polygon and point feature:

  • id: a string identifier for the feature that is globally unique within a worldview. For most functionality that deals with the vector tiles you should use feature_id instead.
  • feature_id: the integer ID used for each feature in the vector tiles. It can be used for data-joins with Mapbox GL JS's feature state. Like id, it is globally unique within a worldview.
  • type: the data type (for example admin, postal, or stats). See the Boundaries vector tile reference for a full list of values and definitions.
  • level: a numeric value between 0 and 5 to represent the level of boundaries within the type. (Note: different data types have different level ranges available.)
  • layer: a shortened concatenation of type and level with feature's administrative (adm), postal (pos), or statistical (sta) hierarchy and level (0-5). For example, administrative level 1 would have a level of adm1.
  • worldview: used to display alternate boundary data depending on regional map display requirements. See the Boundaries vector tile reference for an explanation of possible values.
  • unit_code: the country-specific identifier for the feature, such as postcode or FIPS code.
  • name: local feature name.
  • name_en: an English translation or Latin transliteration of the local name. Generally only provided when name is in a non-latin script, otherwise may be null.
  • names: an array that contains additional translations or aliases for the feature name. May be null.
  • description: a text qualifier of the level respective to each country's boundary hierarchy. For example, US admin-1 boundaries have a description of states while Italian admin-1 boundaries have a description of regions.
  • wikidata_id: the associated Wikidata ID for the boundary. May be null, as not all features can be directly associated with Wikidata entities.
  • source_date: recency of boundary data.
  • iso_3166_1_alpha_3: the ISO 3166-1 alpha-3 country code for the feature's parent country or territory.
  • iso_3166_1: the ISO 3166-1 alpha-2 country code for the feature's parent country or territory.
  • parent_1: the id of the level-1 parent of a feature, if any.
  • parent_2: the id of the level-2 parent of a feature, if any.
  • parent_3: the id of the level-3 parent of a feature, if any.
  • parent_4: the id of the level-4 parent of a feature, if any.
  • z_min: minimum zoom level at which a polygon feature appears in a tileset.
  • centroid: An approximate central point of the feature's polygon as an array of [longitude, latitude].
  • bounds: an array of the features bounding box as [minlong, minlat, maxlong, maxlat].
  • polytilesetname: tileset ID for the tileset containing the feature's polygon. See the reference documentation for more details.
  • polylayername: name of the source-layer within the polygon tileset containing the feature.
  • pointtilesetname: tileset ID for the tileset containing the feature's point. See the reference documentation for more details.
  • pointlayername: name of the source-layer within the point tileset containing feature.

Sample workflow

The feature lookup tables are designed to be used alongside the Mapbox Boundaries tilesets. A typical workflow for a business intelligence application is:

  1. You have a data source containing information that is associated with one or more geographic attributes. For example demographics associated with county names, or sales data associated with postal codes.
  2. You make a query from the application data store to get the data points you are interested in as well as an appropriate geographic attribute. Additionally aggregate those results to the geographic level you are interested in if necessary, for example grouping individual sales to sum total sales per postal code or county.
  3. Join your query results to Mapbox Boundaries feature IDs using metadata in the feature lookup table. Joining to standardized codes such as postal, FIPS, or NUTS codes (available in the unit_code metadata property) is the most straight-forward option. Joining by name may require some normalization of your data or a tolerance for alternate spellings.
  4. Aggregate your data based on the joined feature IDs. For example sum individual sales data grouped by the feature IDs of the Mapbox Boundaries postal codes.
  5. Generate a Mapbox GL layer from the Mapbox Style Specification to create a visual from query results.
  6. The visual style definition works the same across all Mapbox GL products, including Mapbox GL JS on the web, and Mapbox GL Native on iOS, Android, macOS, and Qt.

Example

Read the Visualize the USA’s economic recovery with client-side data joins blog post, which illustrates how the steps in the sample workflow can work in your application.

Next steps

Learn more about how you can use Mapbox Boundaries:

  • Point-in-polygon query with Mapbox Boundaries: Determine what polygons exist at a single point using the Mapbox Tilequery API.
  • Data-joins with Mapbox Boundaries: The data-join technique involves inner joins between local data, such as the unemployment rate by US state, to vector tile features, such as admin boundaries in Mapbox Boundaries, using data-driven style notation.
  • Extend Mapbox Boundaries: You can extend Mapbox Boundaries with any custom data you need for your application. This could mean adding school district, city, market, or property boundaries to your application — all with the same performance and API features of the native product.
Was this page helpful?