How to get postcodes from Google Places and Google Maps with JavaScript

November 30, 2020

A post by Will Mayger
Twitter . Instagram

Learn how to get postcodes from Google Places and Google Maps with JavaScript.

It almost feels like sometimes there are hidden features(not clearly documented) in the Google Places API.

They can often be very time consuming and difficult to find and understand, but that is where this article comes in.

This post will help when it comes to geocode addresses and the ability to get the postcode from the Google Places Api.

This will walk you through using postcodes with the Google Places Api with a JavaScript solution that you can copy and make use of.

If you have ever used the Google Places Autocomplete Service, or the details API method, both of which are part of the Google Maps Service, then you may have wondered how to get postcodes from google places and Google Maps.

Turns out, it is possible in more than one way!

In this post we will be using the JavaScript Google Places API along with ReactJS and react hooks.

Let’s start by looking into why this issue is so vague and not well documented.

The problem with postcodes

If you are from the UK, you are pretty used to postcodes being a unique reference for a road, or even house/block of flats.

This is not actually the norm, and for the most part, in and out of Europe, postcodes actually cover a much larger area than just one road or house.

Because postcodes outside the UK cover a much larger area they have less impact in addresses when compared to the impact they have in the UK.

It is pretty common on UK based sites where you can just enter your postcode and then select the house number to be able to find your address, but this is only possible because the postcode covers a small area.

When you consider this you can understand why they have not clearly been documented in the Google Places JavaScript API.

So where can I expect to see postcodes in Google Places?

You won’t find a clear reference to postcodes in the documentation, but you will see hints.

Regardless, you are looking for something called “Geocoding”, which is basically just turning a string into a set of geographical coordinates.

Now the Google Places JavaScript Api provides us with a more granular way to use this.

For the purposes of this blog post we will only be looking at the PlacesService.getDetails Google Places JavaScript Api Method, however you will probably be able to apply this to many of the other methods provided by Google Places.

The getDetails method will accept a place_id and some other fields(options) which you can see here in the PlaceDetailsRequest as well as a callback which will be called asynchronously.

The place_id is a reference used by Google for each “place” which can be any location.

If you are wondering where you can get a place_id from, an example would be the Google Places Autocomplete Service.

The Autocomplete Service will return an array of predictions which each contain a place_id.

If you want to read more about the Autocomplete Service and how to get the address from a string or postcode with the Google Places Api, I have a guide on how you can use it here: How to make and use a Google autocomplete react hook.

After you have your place_id, you can either leave the fields property empty to return all fields which is is not recommended because you will have to pay for each service you end up using or you can enter each field/property as a string in the array to ensure you only use what you need.

You can find all the valid properties here: PlaceResult

Now, we only care about finding the postcode, so we are going to make use of the property address_components, which if you dig a bit further you will see that it returns a GeocoderAddressComponent response.

The GeocoderAddressComponent response will contain an array of objects that contain two strings: long_name, and short_name as well as an array of types.

Now if we dig just a little bit deeper we will find a list of the potential types here, and you will notice that one of them is finally a postal_code.

So, we have now found out how we can get access to the postcode in the Google Places Service docs.

So how would that look in our JavaScript/React code?

Getting the postcode from Google Places (Solution)

If you haven’t already, you will need to get an API key from Google which you can get here

Now before we can start coding we need to add the following script to the <head> of our HTML to access the Google Places Api:

<script
  type="text/javascript"
  src="//maps.googleapis.com/maps/api/js?key=YOUR_API_KEY_GOES_HERE&language=en&libraries=places"
></script>

Okay we are ready to start consuming the Google Places Api to get our postcode!

Let’s take a look at the JavaScript code we need to get the postcode from the Places Api:

export const getPlacesPostCodeById = async placeId =>
  new Promise((resolve, reject) => {
    if (!placeId) reject("placeId not provided")

    try {
      new window.google.maps.places.PlacesService(
        document.createElement("div")
      ).getDetails(
        {
          placeId,
          fields: ["address_components"],
        },
        details => {
          let postcode = null
          details?.address_components?.forEach(entry => {
            if (entry.types?.[0] === "postal_code") {
              postcode = entry.long_name
            }
          })
          return resolve(postcode)
        }
      )
    } catch (e) {
      reject(e)
    }
  })

export default function ShowPlacePostcode({ placeId }) {
  const [postcode, setPostcode] = useState(null)

  const handleClick = async e => {
    e.preventDefault()
    try {
      const postcode = await getPlacesPostCodeById(placeId)
      setPostcode(postcode)
    } catch (e) {
      console.error(e)
    }
  }

  return (
    <>
      <button onClick={handleClick}>Get postcode</button>
      <p>
        {postcode ? `The postcode is: ${postcode}` : "Sorry, no postcode found"}
      </p>
    </>
  )
}

As you can see, our postcode solution is the function called getPlacesPostCodeById, we are wrapping it in an explicit promise so it makes it a little easier to use in our application.

We are also making use of a try catch block which helps us to catch and handle exceptions, whenever you make an async call to a service it is worth adding in some kind of error handling like a try catch block because it can, and most likely will fail and one point or another.

We are then calling the getDetails method from the Google Places Api with a place_id and fields ['address_components']. This will then return the property, address_components, which we are looking for that contains the address and the postcode.

Where we only need to get the postcode from the location we need to filter through the results and find the one with the type of postal_code, like what is described in the Google Places Geocoding Api.

And there we have our postcode from Google Places.

Now you might be wondering, how can I get the postcode from the Google Autocomplete Service or how can I combine this with the Autocomplete Service and use it in Google maps?

Well, you can’t directly but as mentioned earlier on in this post, you can use the Autocomplete Service to get the place_id which you can then pass into the getDetails method like in the example above.

Alternative options

If, for any reason you don’t get back a postcode from Google for a certain place, don’t worry, you can still get the postcode.

Now the Google Places getDetails method, will always return the lat and lng from the place (if you specify geometry in the fields array that is).

You can use the lat and lng to get the postcode using a free reverse search service like postcodes.io.

You simply provide the lat and lng and the service will then respond with the postcodes that match those coordinates.

Here is a very quick code example:

export const getGooglePlaceById = async placeId =>
  new Promise((resolve, reject) => {
    if (!placeId) reject("placeId not provided")

    try {
      new window.google.maps.places.PlacesService(
        document.createElement("div")
      ).getDetails(
        {
          placeId,
          fields: ["geometry"],
        },
        details => {
          const lat = details?.geometry?.location?.lat() || null
          const lng = details?.geometry?.location?.lng() || null
          return resolve({
            lat,
            lng,
          })
        }
      )
    } catch (e) {
      reject(e)
    }
  })

export const getPostcodeByLatLng = async (lat, lng) => {
  if (!lat || !lng) return null
  const res = await fetch(`https://api.postcodes.io/?lon=${lng}&lat=${lat}`)
  return data?.result?.[0]?.postcode || null
}

export const getPostcode = async placeId => {
  try {
    const { lat, lng } = await getGooglePlaceById(placeId)
    return getPostcodeByLatLng(lat, lng)
  } catch (e) {
    console.error(e)
    return null
  }
}

export default function ShowPlacePostcode({ placeId }) {
  const [postcode, setPostcode] = useState(null)

  const handleClick = async e => {
    e.preventDefault()
    const postcode = await getPostcode(placeId)
    setPostcode(postcode)
  }

  return (
    <>
      <button onClick={handleClick}>Get postcode</button>
      <p>
        {postcode ? `The postcode is: ${postcode}` : "Sorry, no postcode found"}
      </p>
    </>
  )
}

If you do have the option at this point to use cloud functions or a backend, it would probably be better to call these services from it so you don’t have to worry about CORS or chaining too many asynchronous calls.

The easiest way to get postcodes in react

I am currently building a complete library for Google Places in react using both components and react hooks.

When complete you will be able to use this library to get place_ids and postcodes with ease.

I hope this article has helped create some clarity and solved any issues you have been having accessing postcodes with the Google Places JavaScript API.

Will