intermediate
JavaScript
Local search with the Geocoding API
Prerequisite
Familiarity with front-end development concepts.

The Mapbox Geocoding API allows you to perform forward geocodes, which means that a text query like University of California Berkeley gets turned into longitude and latitude coordinates. But sometimes it’s not enough to just find query results. Often, you want the geocoder to find query results that are biased toward a location, limited to a specific area, or both.

The Mapbox geocoder has built-in ranking that influences what results are returned, and in what order. (Read more about how search results are ranked in the How geocoding works guide.) You can also make your Geocoding API requests even more specific by including optional query parameters.

In this tutorial, you will use the Geocoding API’s proximity and bbox parameters to create a local search app for UC Berkeley that limits results to the Berkeley area and biases results around the campus itself.

View finished map.

Getting started

To complete this tutorial, you will need:

  • A Mapbox account and access token. Sign up for an account at mapbox.com/signup. Your access tokens are on your Account page.
  • Mapbox GL JS. Mapbox GL JS is a JavaScript API for building web maps.
  • A text editor. Use the text editor of your choice for writing HTML, CSS, and JavaScript.

Geocoding API query structure

All Mapbox API queries must specify the API being used and the API version:

https://api.mapbox.com/{api_service}/{version}

The API service used in this tutorial is geocoding and the version is v5.

https://api.mapbox.com/geocoding/v5

Calls to the Geocoding API must also include the endpoint being used, which will either be mapbox.places or mapbox.places-permanent. (mapbox.places-permanent allows for permanent storage of results and for batch geocoding, and is only available to Enterprise customers that have a license for permanent geocodes.)

The following examples use the mapbox.places endpoint.

https://api.mapbox.com/geocoding/v5/mapbox.places

Required parameters

A query to the Geocoding API must contain search text. The search text is either a text string for forward geocodes, or a set of coordinates for reverse geocodes. This forward geocoding example’s search text is San Francisco:

https://api.mapbox.com/geocoding/v5/mapbox.places/San%20Francisco.json&access_token=<your access token here>

Regardless of whether you’re performing a forward or reverse geocode, the search text needs to be followed by .json, since the response will be returned as a GeoJSON object.

Optional parameters

Now comes the fun part! The Geocoding API’s optional parameters allow you to customize your query so that you receive the results that are the most relevant to you. For the full list of the optional parameters that a forward geocoding request can use, see the Geocoding API documentation.

This tutorial will use two optional parameters that are especially useful for biasing results to a specific geographic location: proximity and bbox.

The proximity parameter

The proximity parameter allows you to bias the response in favor of results that are closer to a specified location. This ensures that the query results that are closer to this location are prioritized over ones that are further away. The parameter must be formatted as two comma-separated coordinates in longitude,latitude order. To find the coordinates of a location, you can use the Mapbox Search Playground.

# Prioritizes Peets' locations in San Francisco
https://api.mapbox.com/geocoding/v5/mapbox.places/peets.json?proximity=-122.3995752,37.7881856&access_token=<your access token here>
# Prioritizes Peets' locations in and around Berkeley
https://api.mapbox.com/geocoding/v5/mapbox.places/peets.json?proximity=-122.2727469,37.8715926&access_token=<your access token here>

Since the proximity parameter is not exclusive, it will not restrict results to an area. However, relevant results that are close to the provided coordinates will be returned before relevant results that are further away.

The bbox parameter

The bbox parameter allows you to limit results to only those contained within a supplied bounding box. Bounding boxes need to be formatted as four coordinates separated by commas, in minLon,minLat,maxLon,maxLat order.

You can use any coordinates for a bounding box, as long as they describe a box shape. To find the coordinates for a bounding box, you can use the Mapbox Search Playground.

# Search for Starbucks in the Washington DC area
https://api.mapbox.com/geocoding/v5/mapbox.places/starbucks.json?bbox=-77.083056,38.908611,-76.997778,38.959167&access_token=<your access token here>

The bbox parameter is exclusive, meaning that it will exclude any results that fall outside of the specified boundary.

Build the Geocoding API query

Now that you have seen how to use some of the Geocoding API’s optional parameters to bias results around a location and restrict results to an area, you can use them in an app. This tutorial walks you through the process of creating a simple app that restricts results to a set area, and then biases the results around a landmark. In this case, the set area will be Berkeley, California, and the landmark will be the UC Berkeley campus.

Using cURL, a Geocoding API query that uses proximity to bias results around the Berkeley campus and uses bbox to limit results to the Berkeley area would look like:

# Search text is "coffee"  
# `proximity` is set to the coordinates of the campus
# `bbox` is set to encompass Berkeley CA
https://api.mapbox.com/geocoding/v5/mapbox.places/coffee.json?proximity=-122.25948,37.87221&bbox=-122.30937,37.84214,-122.23715,37.89838&access_token=<your access token here>

Geocoding plugins and libraries

The Geocoding API’s optional parameters give you powerful ways to customize your queries, but it can be unwieldy to use raw cURL API calls in your applications. The Mapbox geocoder is available through several plugins and wrapper libraries that can help you integrate it into an app:

This tutorial uses the Mapbox GL JS Geocoder plugin.

Create your app

To create the local search app, you will create an HTML file and initialize the map. Then you will add the Mapbox GL JS Geocoder plugin and set the bbox and proximity parameters.

Once the app is running, you will use your browser’s developer tools to see how the browser interprets the Geocoder plugin’s API request.

Set up your HTML file

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 basic structure of the page.

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>Display a map</title>
  <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
  <script src='https://api.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.js'></script>
  <link href='https://api.mapbox.com/mapbox-gl-js/v0.51.0/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>

</body>
</html>

Initialize the map

Next, you will add the Mapbox GL JS code that initializes a map, which will be displayed in the <div> you created in the last step. In index.html, place the following snippet above the closing </body> tag. Make sure that you set the mapbox.accessToken variable equal to your Mapbox access token.

<script>
  mapboxgl.accessToken = '<your access token here>';
  var map = new mapboxgl.Map({
    container: 'map', // Container ID
    style: 'mapbox://styles/mapbox/streets-v10', // Map style to use
    center: [-122.25948, 37.87221], // Starting position [lng, lat]
    zoom: 12, // Starting zoom level
  });
</script>

This Mapbox GL JS code sets a style for the map, gives it coordinates on which to center, and sets a zoom level.

Save your changes. Open the HTML file in your browser to see the rendered map.

Screenshot showing a rendered Mapbox map

Add a marker to the map

Since the app that you are building will bias results around the UC Berkeley campus, the next step will be to add a marker to the map at the campus’s coordinates. Having a marker at the landmark will make its location more clear.

After the initialization code that you wrote in the last step, add the following snippet to add a marker to the map:

var marker = new mapboxgl.Marker() // initialize a new marker
  .setLngLat([-122.25948, 37.87221]) // Marker [lng, lat] coordinates
  .addTo(map); // Add the marker to the map

Save your changes and refresh the page in your browser. There will be a marker on the map at the specified coordinates.

Add the geocoder

The next step is to add a geocoder using the Mapbox GL JS Geocoder plugin. To do this, first you need to add links to the geocoder’s JavaScript and CSS to the head of the HTML file.

<script src='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v2.3.0/mapbox-gl-geocoder.min.js'></script>
<link rel='stylesheet' href='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v2.3.0/mapbox-gl-geocoder.css' type='text/css' />

Once these links have been added, you will be able to use the Mapbox GL JS Geocoder plugin in your app. Next, add the following code above the closing </script> tag in your HTML file.

map.addControl(new MapboxGeocoder({ // Initialize the geocoder
  accessToken: mapboxgl.accessToken, // Set the access token
}));

// Add the geocoder to the map
map.addControl(geocoder);

The app you are building for this tutorial limits search results to a specific location. To give your users a visual reminder of this fact, you will use the placeholder parameter in the Geocoder to set custom text to display in the search bar.

Add the following line to the plugin, after the access token:

placeholder: 'Search for places in Berkeley'

Save your changes. Refresh the page in your browser, and you will see that a geocoder search box with custom text has been added to the map. When you type a search term into the box and select a result, the map flies to that location.

Screenshot showing the Mapbox GL JS Geocoder plugin added to a map

Add the bbox and proximity parameters

Inside the map.addControl statement you added in the last step, after the placeholder parameter, add the bbox and proximity parameters.

In the Mapbox GL JS Geocoder plugin, the bbox parameter must be formatted as an array. The proximity parameter must be formatted as an object with a longitude property and a latitude property. (For more information on how to format query parameters, see the Mapbox GL JS Geocoder plugin documentation.)

With the addition of these parameters, the entire statement will look like:

var geocoder = new MapboxGeocoder({ // Initialize the geocoder
  accessToken: mapboxgl.accessToken, // Set the access token
  placeholder: 'Search for places in Berkeley', // Placeholder text for the search bar
  bbox: [-122.30937, 37.84214, -122.23715, 37.89838], // Boundary for Berkeley
  proximity: {
    longitude: -122.25948,
    latitude: 37.87221
  } // Coordinates of UC Berkeley
});

Save the HTML file and refresh the page in your browser. Now, when you enter a search into the geocoder’s search box, you will not receive any results outside of the bounding box. And the results that the geocoder returns are weighted according to their proximity to the Berkeley campus.

Place markers at selected results

The final step for creating this app is to place a marker on the map at the location of a selected search result. The logic for doing this needs to be wrapped in a map.on('load') event so that it is not triggered before the map itself has been loaded. Before the closing </script> tag, paste the following JavaScript:

// After the map style has loaded on the page,
// add a source layer and default styling for a single point
map.on('load', function() {
  map.addSource('single-point', {
    type: 'geojson',
    data: {
      type: 'FeatureCollection',
      features: []
    }
  });

  map.addLayer({
    id: 'point',
    source: 'single-point',
    type: 'circle',
    paint: {
      'circle-radius': 10,
      'circle-color': '#448ee4'
    }
  });

  // Listen for the `result` event from the Geocoder
  // `result` event is triggered when a user makes a selection
  //  Add a marker at the result's coordinates
  geocoder.on('result', function(e) {
    map.getSource('single-point').setData(e.result.geometry);
  });
});

Save the HTML file and refresh the page in your browser. When you perform a search and select a result, a marker will be placed at the result’s coordinates.

View the API call in developer tools

To see what’s going on behind the scenes when you use the Mapbox GL JS Geocoder plugin, you can view the raw API call using your browser’s developer tools. This can be useful for debugging a query if the returned results are not what you expect.

  1. Load the page you created in this tutorial in your browser, or refresh it if it’s already open.
  2. Open the browser’s developer tools. (In Chrome, you can do this by typing command + option + i or command + option + j.)
  3. Type a text phrase into the app’s geocoder search bar and select a result. (The example below is for the search term “coffee”.)
  4. Click on the Network tab.
  5. In the Filter search bar, type in “geocoding”. This will narrow the list of network calls down to those made by the Mapbox Geocoding API.
  6. You will likely see more than one Geocoding API call in the list, each representing a different stage of the search text. Click on the option that has the complete search text (for example, “coffee” instead of “coff”).
  7. In the Request URL section, you will see a request that is extremely similar to the cURL API request that you created in the Build the Geocoding API query section of this tutorial:
https://api.mapbox.com/geocoding/v5/mapbox.places/coffee.json?access_token=<your access token here>&proximity=-122.259%2C37.872&bbox=-122.30937%2C37.84214%2C-122.23715%2C37.89838&limit=5

The difference between the query returned by the browser and the one you created earlier is that this one also includes the limit parameter, with the default value of 5 passed in.

Finished product

Congratulations! You have just completed a local search app that, when a user enters a query into the Geocoder search box, biases the results around the UC Berkeley campus and excludes any results that are located outside the Berkeley area.

View finished map.

The final HTML file will look like the following:

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8' />
    <title>Display a map</title>
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
    <script src='https://api.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.js'></script>
    <link href='https://api.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.css' rel='stylesheet' />
    <script src='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v2.3.0/mapbox-gl-geocoder.min.js'></script>
    <link rel='stylesheet' href='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v2.3.0/mapbox-gl-geocoder.css' type='text/css' />
    <style>
        body {
          margin: 0;
          padding: 0;
        }

        #map {
          position: absolute;
          top: 0;
          bottom: 0;
          width: 100%;
        }
    </style>
</head>
<body>

  <div id='map'></div>

<script>
  mapboxgl.accessToken = 'pk.eyJ1IjoiZXhhbXBsZXMiLCJhIjoiY2lqbmpqazdlMDBsdnRva284cWd3bm11byJ9.V6Hg2oYJwMAxeoR9GEzkAA';
  var map = new mapboxgl.Map({
    container: 'map', // Container ID
    style: 'mapbox://styles/mapbox/streets-v10', // Map style to use
    center: [-122.25948, 37.87221], // Starting position [lng, lat]
    zoom: 12, // Starting zoom level
  });

  var marker = new mapboxgl.Marker() // Initialize a new marker
    .setLngLat([-122.25948, 37.87221]) // Marker [lng, lat] coordinates
    .addTo(map); // Add the marker to the map

  var geocoder = new MapboxGeocoder({ // Initialize the geocoder
    accessToken: mapboxgl.accessToken, // Set the access token
    placeholder: 'Search for places in Berkeley', // Placeholder text for the search bar
    bbox: [-122.30937, 37.84214, -122.23715, 37.89838], // Boundary for Berkeley
    proximity: {
      longitude: -122.25948,
      latitude: 37.87221
    } // Coordinates of UC Berkeley
  });

  // Add the geocoder to the map
  map.addControl(geocoder);

  // After the map style has loaded on the page,
  // add a source layer and default styling for a single point
  map.on('load', function() {
    map.addSource('single-point', {
      type: 'geojson',
      data: {
        type: 'FeatureCollection',
        features: []
      }
    });

    map.addLayer({
      id: 'point',
      source: 'single-point',
      type: 'circle',
      paint: {
        'circle-radius': 10,
        'circle-color': '#448ee4'
      }
    });

    // Listen for the `result` event from the Geocoder
    // `result` event is triggered when a user makes a selection
    // Add a marker at the result's coordinates
    geocoder.on('result', function(ev) {
      map.getSource('single-point').setData(ev.result.geometry);
    });
  });
</script>
</body>
</html>

Next steps

There are a lot of things you could do to build this app out more. You could: