mrkaluzny homepage
Tips & Tricks

How to add Google Reviews to static website?

May 3, 2020

I'm constantly improving my websites as well as my client's sites adding new features and information. Last week I focused on integrating google reviews with a static website written in react. Here's a little guide on how to do it on your own.

Google APIs

When I was researching ways to add google reviews to Clean Commit's website I first wanted to load the reviews for each website visitor using JS on the front end. Unfortunately that's impossible.

Which API to use for Google My Business reviews?

I came across 2 API's that can potentially load reviews from Google Maps business location - Google My Business API and Google Places API. The former requires a sing up and confirmation on how you'll use it. Unfortunately, it requires an additional layer of authorization and is mostly meant for applications that manage google business pages. After waiting for confirmation and testing this API I finally gave up and turned to Places API. Unfortunately, Places API only loads 5 reviews, but from what I gathered these 5 reviews randomly order (which is great for our implementation approach).

Prerequisites

Before we start this little project we'll need a couple of things beforehand:

  1. Sign up for Google Cloud Platform and create a new project
  2. Activate Places API
  3. Find your business location ID

First, two steps are straight forward, just follow the links provided. The last one is a bit trickier but fortunately, we can use Place IDs Finder, just types in your business name and you'll find the ID you're looking for.

How to handle Google Business reviews import?

Now we're ready to try out Places API. Our calls will be directed at the following URL:

https://maps.googleapis.com/maps/api/place/details/json?placeid=[PLACE_ID]&key=[API_KEY]

The output will look something like that:

{
   "html_attributions": [],
   "result": {
      "address_components": [...],
      "adr_address": "...",
      "business_status": "...",
      "formatted_address": "...",
      "formatted_phone_number": "...",
      "geometry": {},
      "icon": "https://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
      "id": "...",
      "international_phone_number": "...",
      "name": "...",
      "opening_hours": {...},
      "photos": [...],
      "place_id": "...",
      "plus_code": {...},
      "rating": 5,
      "reference": "...",
      "reviews": [...],
      "scope": "GOOGLE",
      "types": [...],
      "url": "https://maps.google.com/?cid=12209819992465647813",
      "user_ratings_total": 4,
      "utc_offset": 600,
      "vicinity": "13/7 Ijong Street, Braddon",
      "website": "https://cleancommit.io/"
   },
   "status": "OK"
}

The only problem with our calls to the API is that calling it from the front end will result in errors. Additionally, we only have 5 reviews returned each time.

I'm using React Static on that particular website, but it can also be done with Gatsby.

The way I decided to solve this issue is to call the API on each build and save reviews data in markdown file that will be used to create a static website and work with Netlify CMS.

const fs = require('fs')
const klaw = require('klaw')
const path = require('path')
const matter = require('gray-matter')
const axios = require('axios');
const yaml = require('js-yaml');
...

function getGoogleReviews() {
  console.log('=> Fetching reviews data..')
  return new Promise((resolve, reject) => {
    let reviews;
    const url = 'https://maps.googleapis.com/maps/api/place/details/json?placeid=[PLACE_ID]&key=[API_KEY]';
    axios.get(url)
    .then(res => {
      console.log('=> Reviews data fetched!')
      console.log(res.data)
      if(res.data.status == 'OK') {
        console.log('=> Saving new reviews to markdown..')
        let today = new Date('now');
        reviews = res.data.result.reviews

        // Converting reviews to netlify format
        reviews.forEach(item => {
          let content = {
            image: item.profile_photo_url,
            title: item.author_name,
            link: '',
            company: '',
            testimonial: item.text,
            rating: item.rating,
            promted: false,
            google: true,
          }
          content = yaml.safeDump(content, {delims: true})
          content = `---\n${content}\n---`
          let path = `./content/testimonials/${slugify(item.author_name)}.md`
          if (!fs.existsSync(path)) {
            fs.writeFile(path, content, err => {
              if (err) {
                console.error(err)
                return
              }
            })
          }
        })
      }
      resolve(reviews)
    })
  })
}

The function above will fetch reviews and save them in ./content/testimonials saving the file as an authors name, only saving the testimonials that are not already existing.

Then all you have to do is call that function while building the static website.

function getTestimonials() {
  getGoogleReviews();
  const items = [];
  const getFiles = () =>
    new Promise((resolve) => {
      if (fs.existsSync('./content/testimonials')) {
        klaw('./content/testimonials')
          .on('data', (item) => {
            if (path.extname(item.path) === '.md') {
              const data = fs.readFileSync(item.path, 'utf8');
              const dataObj = matter(data);
              delete dataObj.orig;
              items.push(dataObj);
            }
          })
          .on('error', (e) => {
            console.log(e);
          })
          .on('end', () => {
            resolve(items);
          });
      } else {
        resolve(items);
      }
    });

  return getFiles();
}

That's it! You can easily add reviews from Google to your website!