[Mapzen Search](https://mapzen.com/projects/search) is a modern, geographic search service based entirely on open-source tools and open data. Use this functionality to enhance any app that has a geographic context, such as ones that help in delivering goods, locating hotels or venues, or providing local weather forecasts.
[Mapzen Search](https://mapzen.com/products/search/) is a modern, geographic search service based entirely on open-source tools and open data. Use this functionality to enhance any app that has a geographic context, such as ones that help in delivering goods, locating hotels or venues, or providing local weather forecasts.
Through a process known as [geocoding](https://en.wikipedia.org/wiki/Geocoding), Mapzen Search allows you to enter an address or the name of a landmark or business, and the service translates the result into geographic coordinates for mapping. Mapzen Search is built on [Pelias](https://github.com/pelias), an open-source geocoding project.
Through a process known as [geocoding](https://en.wikipedia.org/wiki/Geocoding), Mapzen Search allows you to enter an address or the name of a landmark or business, and the service translates the result into geographic coordinates for mapping. Mapzen Search is built on [Pelias](pelias.io), an open-source geocoding project.
In this walkthrough, you will learn how to make a map with a search box that allows you to enter addresses and place names and locate them on a map. To complete the tutorial, you should have some familiarity with HTML and JavaScript, although all the source code is provided. You also need a Mapzen Search [API key](https://mapzen.com/developers), which requires a [GitHub account](https://help.github.com/articles/signing-up-for-a-new-github-account/) for authorization. You can use any text editor and operating system, but must keep an Internet connection while you are working.
## Get ready for the tutorial
## Sign up for a Mapzen Search API key
In this tutorial, you will learn how to make a map with a search box that allows you to enter addresses and place names and locate them on a map. To complete the tutorial, you should have some familiarity with HTML and JavaScript, although all the source code is provided. You can use any text editor and operating system, but must keep an Internet connection while you are working.
To use the geocoding service, you must first get a Mapzen [API key](https://en.wikipedia.org/wiki/Application_programming_interface_key). Because the search service is shared among many users, an API key is a way to make sure that the performance is acceptable for everyone. Sign in at https://mapzen.com/developers to create and manage your API keys.
You also need a [Mapzen API key](https://mapzen.com/developers), which requires a [GitHub account](https://help.github.com/articles/signing-up-for-a-new-github-account/) for authorization.
Suggested text editor applications include [Atom - OS X, Windows, Linux](https://atom.io/); [Notepad++ - Windows](https://notepad-plus-plus.org/); [TextWrangler - OS X](http://www.barebones.com/products/textwrangler/); and [Sublime - OS X, Windows, Linux; free trial](http://www.sublimetext.com/). While you can use the apps installed with your operating system, such as Notepad or TextEdit, they do not provide the helpful indentations, code coloring and autocomplete, or text alignment options found in the other editors. For TextEdit, you must go to the Format menu and click Make Plain Text to use the plain-text version of the file. Do not use an app that applies rich formatting, such as Word or Wordpad.
### Sign up for a Mapzen API key
1. Go to https://mapzen.com/developers.
1. Go to https://mapzen.com/developers.
2. Sign in with your [GitHub account](https://help.github.com/articles/signing-up-for-a-new-github-account/). If you have not done this before, you need to agree to the terms first.
2. Sign in with your [GitHub account](https://help.github.com/articles/signing-up-for-a-new-github-account/). If you have not done this before, you need to agree to the terms first.
3. Create a new key for this project and, optionally, give it a project name so you can remember the purpose of the key.
3. Create a new key, and, optionally, give it a project name so you can remember the purpose of the key.
4. Keep the web page open so you can copy the key into the source code later.
4. Keep the web page open so you can copy the key into the source code later.
## Create an index page
## Create an HTML page
You are ready to start building your map. You will need to use a text editor to update the HTML.
You are ready to start building your web page and map.
Suggested text editor applications include [Atom - OS X, Windows, Linux](https://atom.io/); [Notepad++ - Windows](https://notepad-plus-plus.org/); [TextWrangler - OS X](http://www.barebones.com/products/textwrangler/); and [Sublime - OS X, Windows, Linux; free trial](http://www.sublimetext.com/). While you can use the apps installed with your operating system, such as Notepad or TextEdit, they do not provide the helpful indentations, code coloring and autocomplete, or text alignment options found in the other editors. For TextEdit, you must go to the Format menu and click Make Plain Text to use the plain-text version of the file. Do not use an app that applies rich formatting, such as Word or Wordpad.
The end of this walkthrough has a finished version of the HTML that you can use to check your work or review if you need to troubleshoot an error.
_Tip: The end of this page has a finished version of the code that you can use to check your work or review if you need to troubleshoot an error._
1. Start your text editor with a blank document and copy and paste the following HTML. (Note: If the text editor you are using requires you to name and save a document at the time when it is first created, call the file `index.html`.)
1. Start your text editor with a blank document and copy and paste the following HTML. (Note: If the text editor you are using requires you to name and save a document at the time when it is first created, call the file `index.html`.)
@ -65,25 +67,20 @@ Your HTML should look like this:
## Add references to CSS and JavaScript files
## Add references to CSS and JavaScript files
The Leaflet JavaScript library provides tools for building an interactive map for web and mobile devices. Leaflet is extensible, and developers have built additional tools for Leaflet maps, including the Mapzen Search geocoder plug-in.
A cascading style sheet (CSS) is used to style a webpage, including layout and fonts, and JavaScript adds functionality to the page. In your `index.html` file, you need to list the CSS and JavaScript files needed to build your page.
A cascading style sheet (CSS) is used to style a webpage, including layout and fonts, and JavaScript adds functionality to the page. In your `index.html` file, you need to list the CSS and JavaScript files required for building a page with Leaflet and the geocoder plug-in.
The [Leaflet JavaScript library](http://leafletjs.com/) provides tools for building an interactive map for web and mobile devices. Leaflet is extensible, and developers have built additional tools for Leaflet maps.
1. In `index.html`, at the bottom of the `<head>` section, add references to the Leaflet CSS and JavaScript files. You are linking to these from a remote website, rather than from a file on your machine.
The [Mapzen.js library](https://www.mapzen.com/documentation/mapzen-js/) simplifies the process of using Mapzen's maps within Leaflet. Mapzen.js contains all the Leaflet functionality, as well as additional tools for working with Mapzen maps and search.
```html
1. In `index.html`, at the bottom of the `<head>` section, add references to the Mapzen.js CSS and JavaScript files.
2. In the `<head>` section, directly after the lines you added for Leaflet, add references to the geocoder's CSS and JavaScript files. These are also being linked to on a website.
3. Save your edits and refresh the browser. The webpage should still appear empty because you have not added any code to interact with these references.
2. Save your edits and refresh the browser. The webpage should still appear empty because you have not added any code to interact with these references.
After adding these, your index.html file should look something like this.
After adding these, your index.html file should look something like this.
@ -93,23 +90,21 @@ After adding these, your index.html file should look something like this.
Note that you are linking to a website that is serving the geocoder's CSS and JavaScript, but you can also [view, download, and contribute to the source code](https://github.com/mapzen/leaflet-geocoder) if you want to access the contents of the plug-in.
Note that you are linking to a website that is serving the Mapzen.js CSS and JavaScript, but you can also [view, download, and contribute to the source code](https://github.com/mapzen/mapzen.js) if you want to access the contents of the library.
## Add a map to the page
## Add a map to the page
To display a Leaflet map on a page, you need a `<div>` element, which is a container on the page that groups elements, with an ID value. If you want to know more about initializing a Leaflet map, see the [Leaflet getting started documentation](http://leafletjs.com/examples/quick-start.html).
To display a Leaflet map on a page, you need a `<div>` element, which is a container on the page that groups elements, with an ID value. If you want to know more about initializing a Leaflet map, see the [Leaflet getting started documentation](http://leafletjs.com/examples/quick-start.html).
1. At the bottom of the `<head>` section, after the references you added in the earlier steps, add a `<style>` tag and the following attributes to set the size of the map on your webpage.
1. At the bottom of the `<head>` section, after the references you added in the earlier steps, add a `<style>` tag and the following attributes to set the size of the map on your webpage. A Leaflet map will not display unless you include a width.
```html
```html
<style>
<style>
@ -125,40 +120,40 @@ To display a Leaflet map on a page, you need a `<div>` element, which is a conta
2. At the top of the `<body>` section, add the `<div>`.
2. At the top of the `<body>` section, add the `<div>`.
```html
```html
<divid="map"></div>
<divid='map'></div>
```
```
3. Directly after the `<div>`, add this JavaScript code within a `<script>` tag to initialize Leaflet.
3. Directly after the `<div>`, add this JavaScript code within a `<script>` tag to initialize a map.
```html
```html
<script>
<script>
var map = L.map('map').setView([37.804146, -122.275045], 16);
var map = L.Mapzen.map('map', {
center: [47.61033,-122.31801],
zoom: 16,
scene: L.Mapzen.BasemapStyles.BubbleWrap
});
</script>
</script>
```
```
`L.xxxxx` is a convention used with the Leaflet API. The `setView([37.804146, -122.275045], 16)` part sets the center of the map, in decimal degrees, and the zoom level. The map is centered in Oakland, California, with a zoom level that allows you to see the streets and features of the city. Zoom levels are like map scales or resolutions, where a smaller value shows a larger area in less detail, and a larger zoom level value depicts smaller area in great detail.
`L.xxxxx` is a convention used with the Leaflet API. The `center: [47.61033,-122.31801]` parameter sets the center point of the map, in decimal degrees, at the location of a building at Seattle University.
4. Within the same `<script>` tag, start a new line and set the data source for the map. This line adds the default OpenStreetMap tiles and an attribution.
The next line sets the `zoom` level, which is like a map scale or resolution, where a smaller value shows a larger area in less detail, and a larger zoom level value depicts smaller area in great detail.
```html
The `scene: L.Mapzen.BasemapStyles.BubbleWrap` line sets the style used for the map. In this case, it is Mapzen's all-purpose stylesheet called BubbleWrap.
At this point, you have a map! You should see a map with OpenStreetMap tiles, zoom controls, and a Leaflet attribution in the bottom corner.
At this point, you have a map! You should see a map, zoom controls, and attribution in the bottom corner.
To recap how you created this, you added references to the Mapzen JS and CSS files, a map `<div>` with a declared width, and assigned the `map` value to `L.Mapzen.map`.
![Leaflet canvas map with controls and attribution](images/geocoder-osm-leaflet.png)
![Leaflet canvas map with controls and attribution](images/basic-webmap.png)
## Add the Search box
## Add the Search box
So far, you have referenced the necessary files, initialized Leaflet with a map container on the page, and added data to the map. Now, you are ready to add the Search box from the Mapzen Search plug-in.
So far, you have referenced the necessary files, initialized Leaflet with a map container on the page, and added data to the map. Now, you are ready to add the Search box.
1. Go back to the https://mapzen.com/developers page and copy your API key to the clipboard.
1. Go back to the https://mapzen.com/developers page and copy your API key to the clipboard.
2. Inside the same `<script>` tag, start a new line after the `}).addTo(map);` line. Initialize a search box with the following code and your own API key substituted for the placeholder text of `mapzen-xxxxxx`.
2. Inside the same `<script>` tag, and after the code you just added for the map, initialize a search box and add it to the map with the following code. Use your own API key substituted for the placeholder text of `mapzen-xxxxxx`.
```js
```js
var geocoder = L.control.geocoder('mapzen-xxxxxx').addTo(map);
var geocoder = L.Mapzen.geocoder('mapzen-xxxxxx');
geocoder.addTo(map);
```
```
The `mapzen-xxxxxx` text is the Mapzen Search API key; paste your own API key inside the single quotes.
The `mapzen-xxxxxx` text is the Mapzen API key; paste your own API key inside the single quotes.
3. Save your edits and refresh the browser. You should see a small magnifying glass icon in the left corner, near the zoom controls.
You are passing one parameter to the search, which is the [API key](https://en.wikipedia.org/wiki/Application_programming_interface_key) inside the single quotes. The API key is a code that uniquely identifies your developer account without providing a password. For this workshop, you are being provided with an API key. Because the search service is shared among many users, an API key is a way to make sure that the performance is acceptable for everyone.
![Search icon on the map canvas](images/geocoder-search-icon.png)
2. Save your edits and refresh the browser. You should see search box in the left corner, near the zoom controls. If your browser window is wide, the Search box is expanded by default. When you reduce the window size, the box collapses to a button. You can change this behavior in the geocoder options.
4. Click the button to display the Search box on the map. The Search box closes if you click away from it.
![Search icon on the map canvas](images/geocoder-search-icon.png)
![Expanded Search box on the map canvas](images/geocoder-search-box.png)
Your `<body>` section should look like this:
Your `<body>` section should look like this:
```html
```html
[...]
[...]
<body>
<divid="map"></div>
<script>
<script>
var map = L.map('map').setView([37.804146, -122.275045], 16);
var geocoder = L.control.geocoder('search-xxxxxx').addTo(map);
scene: L.Mapzen.HouseStyles.BubbleWrap
});
var geocoder = L.Mapzen.geocoder('mapzen-xxxxxx');
geocoder.addTo(map);
</script>
</script>
</body>
[...]
[...]
```
```
## Search for places on the map
## Search for places on the map
1. On the map, type `555 12th` in the Search box. As you type, the text automatically completes to suggest matching results.
Now, you will test your search box by finding a few locations. As you type, the text automatically completes to suggest matching results.
2. In the results list, find the entry for `555 12th Street, Oakland, CA` and click it to zoom and add a point to the map at that location. (The point is only on your map, and does not update OpenStreetMap.)
1. On the map, type `Seattle University` in the Search box.
2. In the results list, find the entry for `Seattle University` and click it to zoom and add a point to the map at that location. (The point is only on your map, and does not update OpenStreetMap.)
![Entering an address to find on the map](images/geocoder-address-search.png)
![Entering an address to find on the map](images/geocoder-address-search.png)
3. Search for other addresses or places to experiment with the search function and get an idea of the results it returns. For example, you might try looking for a point of interest in Seattle, your work address, or a city outside the United States.
If you want to [customize the geocoder plug-in behavior](https://github.com/pelias/leaflet-geocoder#customizing-the-plugin) beyond the defaults in this Walkthrough, you can set additional options in your code. For example, the Search box collapses to an icon by default, but you can specify that the text box be shown at full width. There are also options for customizing the parameters for the Mapzen Search service, such as limiting the search to the map's extent or prioritizing results near the current view. Right now, you may notice that results from around the world appear in the list.
## Customize the geocoder
Mapzen Search uses a [variety of open data sources](https://mapzen.com/documentation/search/data-sources/), including OpenStreetMap. Part of the power of open data is that anyone can change the source data and improve the quality for everyone. If you are unable to find a location, the place could be missing or incorrect in the source datasets. Mapzen is also building a comprehensive, open database of places known as [Who's on First](https://github.com/whosonfirst/whosonfirst-data) that can be publicly edited, and is working on integrating it into the geocoder.
From a technical perspective, Mapzen Search is a web service with that has various API endpoints that allow you to access web resources through a URL. Behind the scenes, the geocoder is constructing a URL with the parameters you specify and sending it to the Mapzen Search web service. The service returns [human-readable JSON](https://en.wikipedia.org/wiki/JSON), short for JavaScript Object Notation.
## Walkthrough summary
Mapzen.js provides options for customizing the way you interact with the map, and Mapzen Search is also very flexible. Now that you have a map on your page with a Search box, you can add more features to it. You need to modify the line defining the geocoder to include additional parameters.
In this walkthrough, you learned the basics of adding the Mapzen Search geocoding engine to a Leaflet map. If you want to learn more about Mapzen Search, review the [documentation](index.md).
Up to this point, you have been using the Mapzen Search [\autocomplete](https://mapzen.com/documentation/search/autocomplete/) endpoint, which searches on text as you type it. In this section, you will switch to the [\search](https://mapzen.com/documentation/search/search/) endpoint to see how it behaves. The `autocomplete` functionality helps you find partial matches, whereas `search` prioritizes exact words because it assumes you have finished typing when you perform the query.
Because the geocoder is still under development and considered experimental, if you are getting unexpected search results, please add an issue to the [Pelias GitHub repository](https://github.com/pelias/pelias/issues). The developers can investigate and decide if the problem is caused by software or data, and work to fix it either way.
If you look at your browser's developer tools console as you are doing this, you can see the query URL changes from `https://search.mapzen.com/v1/autocomplete?text=` to `https://search.mapzen.com/v1/search?text=` to reflect the `search` endpoint.
Although you will not be using it in this tutorial, [\reverse](https://mapzen.com/documentation/search/reverse/) is another common Mapzen Search endpoint. It performs reverse geocoding to find the address at a given coordinate location. You can find a listing of all the endpoints and parameters in the [Mapzen Search documentation](https://mapzen.com/documentation/search/).
1. Modify the geocoder code block so you can pass in other parameters, as shown below. Make sure your () and {} close properly.
```js
var geocoder = L.Mapzen.geocoder('mapzen-xxxxxx', {
});
geocoder.addTo(map);
```
2. Add `autocomplete: false` to specify that the Search box should not suggest potential text matches as you type. Autocomplete is enabled by default, so adding this means that you will turn it off.
```js
var geocoder = L.Mapzen.geocoder('mapzen-xxxxxx', {
autocomplete: false
});
geocoder.addTo(map);
```
3. Save your edits and refresh the browser.
4. Type `901 12th Avenue` in the Search box and press Enter. Notice now that the matching search results are not listed until you press the Enter key.
### Extra credit: View the JSON response
1. Open your browser's developer tools console. In Chrome, you can do this by clicking the menu in the corner, pointing to More Tools, and clicking Developer Tools.
2. Click the Network tab to see the Internet traffic, including the queries to the Mapzen servers.
3. Click the Headers tab for more information about the request, including the full URL. For example, the URL might look something like `https://search.mapzen.com/v1/search?text=901%2012th%20avenue&focus.point.lat=47.61032944737081&focus.point.lon=-122.31800079345703&api_key=mapzen-xxxxxx`
4. Paste this URL into a new browser tab to see the JSON response, which can be mapped.
_Tip: You can install a plug-in for your browser to display JSON in a more formatted manner. For example, JSONView is a common extension that does this for Chrome. You can search the web store for your browser to find and install applicable products._
![Search endpoint query in the browser developer console](images/developer-console.png)
To take your map even further, you can follow along with some additional Mapzen tutorials. One exercise you can try is to use [Mapzen's Tangram rendering engine](https://mapzen.com/documentation/turn-by-turn/add-routing-to-a-map/#add-a-tangram-map-to-the-frame) and vector tiles to draw the data on the map, instead of the OpenStreetMap raster tile layer you used in this walkthrough. When you get your map the way you want, you might be interested in [putting your map on the web](https://mapzen.com/documentation/tangram/walkthrough/#put-your-tangram-map-on-the-web) so you can share your work with others.
## Choose which data sources to search
## Completed HTML for this walkthrough
Mapzen Search uses a [variety of open data sources](https://mapzen.com/documentation/search/data-sources/), including OpenStreetMap. Part of the power of open data is that anyone can change the source data and improve the quality for everyone. If you are unable to find a location, the place could be missing or incorrect in the source datasets.
You can choose which data sources to search by passing a parameter for the `sources`. In addition, you need to enclose with single quotation marks any parameter names that use the dot notation (such as `boundary.country`) to make sure JavaScript can parse the text correctly.
As you were searching, you might have noticed results that looked similar. Mapzen Search does perform some elimination, but the differing data sources may still cause seemingly matching results to appear. Choosing a particular data source can reduce the occurrence of duplicated entries.
1. Within the geocoder block, add the `params:` list and a parameter for `sources:`. Be sure to add a `,` at the end of the `autocomplete: false` line.
```js
var geocoder = L.Mapzen.geocoder('mapzen-xxxxxx', {
autocomplete: false,
params: {
sources: 'osm'
}
});
geocoder.addTo(map);
```
2. Save your edits and refresh the browser.
3. Search for `901 12th Avenue` again. Try searching city names, such as `Vancouver`, as you continue to experiment with the geocoder.
## Prioritize nearby places and filter search results
Mapzen Search provides options for customizing your search parameters, such as limiting the search to the map's extent or prioritizing results near the current view. Right now, you may notice that results from around the world appear in the list.
Mapzen.js automatically provides a [focus point](https://mapzen.com/documentation/search/search/#prioritize-around-a-point) for you based on the current map view extent. You can add other parameters to filter the search results, such as to limit the results to a particular country or type of result.
1. Within the geocoder block, add add a `,` at the end of the `sources: 'osm'` line and then a parameter for `'boundary.country': 'USA'` on the next line. You need to enclose with single quotation marks any parameter names that use the dot notation (such as `boundary.country`) to make sure JavaScript can parse the text correctly.
```js
var geocoder = L.Mapzen.geocoder('mapzen-xxxxxx', {
autocomplete: false,
params: {
sources: 'osm',
'boundary.country': 'USA'
}
});
geocoder.addTo(map);
```
3. Save your edits and refresh the browser.
4. Search again for city names in the Search box. Notice that you only see results from within the United States. For example, `Vancouver` in Canada is no longer listed, but you can find the city in Washington.
5. Optionally, trying changing the `boundary.country` to another country code, such as `AUS` for Australia. There is a [specific format](https://en.wikipedia.org/wiki/ISO_3166-1) you need to use for the country code. Change the code back to `USA` when you are done.
The code you added in this section should look something like this.
```js
var geocoder = L.Mapzen.geocoder('mapzen-xxxxxx', {
autocomplete: false,
params: {
sources: 'osm',
'boundary.country': 'USA'
}
});
geocoder.addTo(map);
```
## Filter the results by type of place
In Mapzen Search, types of places are referred to as `layers`, and you can use these to filter your results. For example, if your app has an input form where your users should only be able to enter a city, you can use Mapzen Search to limit the results to show only matching city names. This is common in travel apps, such as searching for a hotel or flight, where you enter a destination city.
In this section, you will filter the results to search only addresses and venues, which include point of interest, landmarks, and businesses.
You can review the [Mapzen Search documentation](https://mapzen.com/documentation/search/search/#filter-by-data-type) to learn the types of `layers` you can use in a search.
1. Within the geocoder block, add add a `,` at the end of the `'boundary.country: 'USA'` line and then a parameter for `layers: 'address,venue'` on the next line.
```js
var geocoder = L.Mapzen.geocoder('mapzen-xxxxxx', {
autocomplete: false,
params: {
sources: 'osm',
'boundary.country': 'USA',
layers: 'address,venue'
}
});
geocoder.addTo(map);
```
2. Save your edits and refresh the browser.
3. Search for `102 Pike Street, Seattle, WA 98101` (the first Starbucks) and press Enter. Some other places you can try include `Starbucks`, `400 Broad Street` (the address of the Space Needle), `Space Needle`, and `University of Washington`.
## Tutorial summary
In this tutorial, you learned the basics of adding the Mapzen Search geocoding engine to a map using [Mapzen.js](https://mapzen.com/documentation/mapzen-js/), and making some customizations to improve the search results.
If you want to learn more about Mapzen Search, review the [documentation](https://mapzen.com/documentation/search).
Because the geocoder is still under development and considered experimental, if you are getting unexpected search results, please add an issue to the [Pelias GitHub repository](https://github.com/pelias/pelias/issues). The developers can investigate and decide if the problem is caused by software or data, and work to fix it either way.
## Completed HTML for this tutorial
You can refer to this HTML if you want to review your work or troubleshoot an error. You will need to substitute your own API key for the placeholder text in the source code.
You can refer to this HTML if you want to review your work or troubleshoot an error. You will need to substitute your own API key for the placeholder text in the source code.