Getting the Best Places in Town With the Google Maps API
If you’re anything like me, you’ve probably asked yourself this question at some point in your life, the one nobody has the answer for: Where/what should we eat? Since I’m a developer, I decided I’d had enough and would let computers give me some suggestions. That’s when the idea came to ask Google Maps to list out the top restaurants/bars/anything else nearby so we’d have an easier time choosing.
Luckily, the Google Maps API has the ability to do just that with the combination of its Places API. So today, I would like to show you how you can do the same.
The very first step in this endeavor is to receive an API key.
Retrieving the API Key
The API key will be used to make calls for the different APIs. To get an API key, head over to your Google Cloud Platform dashboard. Select a project or create a new one if you haven’t started one already.
Head over to the menu button and choose the Credentials tab under API & Services.
Click on the Create Credentials button and your newly created API key will pop up.
It’s a good idea to restrict your API key before you use it in a production environment to avoid unexpected expenses and prevent quota theft. You can set up restrictions in the APIs & Services menu under the Credentials tab.
Note that in order to use Google Cloud services, you might have to link your project to a billing account. Fortunately for us, the Google Maps API is still free to use up to a $200 monthly usage. That equals to about 28,000 calls per month. To learn more about pricing, visit the Pricing & Plans or the Pricing Table section on Google Cloud.
If you’d prefer reading Google’s step by step tutorial on how to get an API key, you can refer to their own documentation.
Setting Up the Places API
In order to get information about places on the map, we’re going to use the Places API. To be able to use it, you’ll need to enable it in your Cloud Platform Console.
Go to the project you’ve just created, click on the navigation menu, and choose the Library option under API & Services. You’ll be greeted with the following page:
Search for “Places API” and select enable. Just like for the Google Maps API, the Places API’s nearby search function — which we will use — is free up to 5,000 calls per month.
Now that you’re all set and done from the administrative side, we can jump into coding.
Setting Up the Project
Create a new folder and add the following index.html
file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Getting the best places in town</title>
</head>
<body>
<ol id="places"></ol>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"></script>
<script src="places.js"></script>
</body>
</html>
We won’t have an actual Google Maps map as we’re going to display the results in an ordered list. You also want to include the API library, and don’t forget to replace YOUR_API_KEY
with your actual API key. We’ll also make use of the Places API — you need to specify this as a query string. This is what &libraries=places
is suppose to do.
I also created a places.js
where our own implementation will go. You can add that to the project folder as well. And this is all we need. Everything else will go inside the places.js
file.
Getting Some Results
Before we can start fetching results, we need to create some variables:
const request = {
location: new google.maps.LatLng(51.5287352, -0.3817841),
radius: 5000,
type: ['restaurant']
};
const results = [];
const places = document.getElementById('places');
const service = new google.maps.places.PlacesService(places);
service.nearbySearch(request, callback);
We’re going to store everything inside a results
array, and we also get a reference to the places
element. But the interesting part here is the request
and the service
we have created. The service will take care of requesting the places. You can pass in any DOM element to PlacesService
; it doesn’t have to be a Google Maps object. If you still want to display the results on a map, you need to change the places
variable to the following:
const places = new google.maps.Map(document.getElementById('places'), {
center: {lat: 51.5287352, lng: -0.3817841},
zoom: 10
});
Once we have the service
, we can call the nearbySearch
method with a request
object along with a callback
function. The three main things we need to specify inside the request are:
- A location: The coordinates are created from latitude and longitude values. It takes in a
google.maps.LatLng
object. - A radius: Representing the circle’s radius in meters, its middle being the lat-lng position. The maximum value here can be 50,000.
- A type array: The type of place we’re looking for. Since we’re hungry, we want restaurants to be returned. For a full list of supported types, you can refer to the documentation on the Google Maps Platform.
The coordinates are pointing to London. To get the coordinates for a city, simply go to maps.google.com and search for the city. The lat lang coordinates will appear in the address bar:
We also have a callback function that we haven’t defined yet, so let’s do that right now!
const callback = (response, status, pagination) => {
if (status == google.maps.places.PlacesServiceStatus.OK) {
results.push(...response);
}
if (pagination.hasNextPage) {
setTimeout(() => pagination.nextPage(), 2000);
} else {
displayResults();
}
}
The three things that the callback expects are a response
object where everything the service returns will be stored, astatus
representing the success or failure of the call, and an optional pagination object.
By default, each query to the service returns 20 results. However, it’s possible to extend it to 60 split across three pages. This is why we have to use pagination. The pagination.nextPage
function will call this callback
function again.
You may have also noticed that the call to the pagination function is wrapped inside a setTimeout
. This is because you must wait at least two seconds before the next page of results is available. This also means that since it takes time to fetch all the results, ideally you would display some kind of loading indicator to show the user that something is going on in the background.
Now if the service returned everything, pagination.hasNextPage
will cease to exist making us jump to the else block, where we finally display the results. I outsourced the code here into a different function just so we have some sort of separation.
Display Everything
The displayResults
function will be really simple. Let’s see what we have:
const displayResults = () => {
results.filter(result => result.rating)
.sort((a, b) => a.rating > b.rating ? -1 : 1)
.forEach(result => {
places.innerHTML += `<li>${result.name} - ${result.rating}</li>`;
});
}
First, we need to filter the list of results. There might be cases where the rating is missing. In that case, we won’t know if the place is trustworthy. By simply saying…
result => result.rating
…we tell JavaScript to include results only that contains a rating. If result.rating
is undefined, it will be omitted from the result set.
Next, we need to sort it based on the rating so we get the best options to choose from at the very top. Lastly, we can display their name and their rating in a forEach
loop.
It’s important to mention that from a performance perspective this isn’t the best way to manipulate the DOM in each loop of the forEach
. One alternative would be to create the string inside the loop and add it to the DOM only once the loop has finished.
Now if you head back to the browser and refresh the page, you should see 60 results (in case every result had a rating) ordered by rating, with the highest rated being on top.
Summary
Having this tool in your pocket guarantees that you’ll never have to starve again. All that’s left to do is to create a fancy user interface so you can select the city dynamically with a chosen radius and a chosen place type.
As always, you can reach the whole project on my GitHub at the places repo. Feel free to tweak it and let me know your suggestions in the comments️. Now it’s time to go and eat something.
Rocket Launch Your Career
Speed up your learning progress with our mentorship program. Join as a mentee to unlock the full potential of Webtips and get a personalized learning experience by experts to master the following frontend technologies: