Create a Dashboard with Next.js API Routes - Google Analytics API

πŸ‘³πŸ½β€β™‚οΈ

Ekam Singh / February 18, 2020

4 min read

In this series, you will learn how to create a dashboard using Next.js API routes and integrate with third-party APIs.

Overview

Google Analytics is, by far, the most popular analytics platform. In this post, we'll look at how we can retrieve the number of page views in a specific time range programmatically.

If you're more concerned about privacy, you might consider using Fathom Analytics or SimpleAnalytics.

Note: You'll need to turn off your ad blocker for this page to work.

Getting Access to Google Analytics

To gain access to the Google Analytics API, you need to:

  • Go to the Google Developer Console.
  • Create a new project.
  • Credentials -> Create Credentials -> Service-account key.
  • Click β€œEnable APIs and services.”
  • Find "Google Analytics API" and enable it.

Since we're communicating server-to-server, we'll need a service account.

  • Go to your service accounts page.
  • Create a service account.
  • Click "Create Key" and choose JSON.

You should now have a JSON file similar to this:

{
  "type": "service_account",
  "project_id": "...",
  "private_key_id": "...",
  "private_key": "...",
  "client_email": "...",
  "client_id": "...",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://accounts.google.com/o/oauth2/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "..."
}

We use this key later to set up our client in our API Route. Okay, back to the service account. We need to delegate domain-wide authority.

  • On the table row, click Actions -> Edit.
  • Show Domain-Wide Delegation -> Enable G-Suite Domain-Wide Delegation.

Finally, we need to add our service account email to the Google Analytics account we want to use.

  • Go to the Admin panel inside Google Analytics.
  • Click "User Management."
  • Add the client_email from your service account.

That's it! πŸŽ‰ You now have access to make requests to the Google Analytics API with your service account.

Creating an environment variable

To securely access the API, we need to include the secret with each request. We also do not want to commit secrets to git. Thus, we should use an environment variable.

Since I'm deploying with Vercel, I can add the secrets via their CLI. We only need a few of the values from the JSON file. For the private key, make sure you convert the new line characters (\n) to actual new lines.

$ vc secret add -- google-private-key "-----BEGIN PRIVATE KEY-----
MIIEvQIBA
..
..
2DAVOW4c=
-----END PRIVATE KEY-----"
$ vc secret add google-client-email my-account@project.iam.gserviceaccount.com
$ vc secret add google-client-id 721877721877

To reference these values locally when using vc dev, they need to be added to your .env file.

GOOGLE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nDVOW4c=\n-----END PRIVATE KEY-----\n"
GOOGLE_CLIENT_EMAIL=my-account@project.iam.gserviceaccount.com
GOOGLE_CLIENT_ID=721877721877

Finally, we need to add the secrets to our vercel.json.

vercel.json
{
  "env": {
    "GOOGLE_PRIVATE_KEY": "@google-private-key",
    "GOOGLE_CLIENT_EMAIL": "@google-client-email",
    "GOOGLE_CLIENT_ID": "@google-client-id"
  }
}

We can now reference the secrets via process.env.GOOGLE_PRIVATE_KEY in our API route.

Note: If you have a lot of environment variables in Vercel, you might need to encrypt your service account.

Creating the API Route

Let's start by creating a new API route at pages/api/page-views.js.

export default (req, res) => {
  return res.status(200).json({});
};

To make server-side requests to Google Analytics, we can install the googleapis library.

$ yarn add googleapis

Then, we can initialize googleapis inside our API route.

import { google } from 'googleapis';

let googleAuth;

export default async (_, res) => {
  googleAuth = new google.auth.GoogleAuth({
    credentials: {
      client_email: process.env.GOOGLE_CLIENT_EMAIL,
      client_id: process.env.GOOGLE_CLIENT_ID,
      private_key: process.env.GOOGLE_PRIVATE_KEY
    },
    scopes: ['https://www.googleapis.com/auth/analytics.readonly']
  });

  const analytics = google.analytics({
    auth,
    version: 'v3'
  });

  return res.status(200).json({});
};

Finally, we want to pull statistics about our site. We'd like to know the total number of views for a given time range. To allow the API route to be re-used, let's pass the start date as a query parameter.

const startDate = req.query.startDate;

Then, we can use the same API route to fetch stats about different time ranges.

import { google } from 'googleapis';

let googleAuth;

export default async (_, res) => {
  googleAuth = new google.auth.GoogleAuth({
    credentials: {
      client_email: process.env.GOOGLE_CLIENT_EMAIL,
      client_id: process.env.GOOGLE_CLIENT_ID,
      private_key: process.env.GOOGLE_PRIVATE_KEY
    },
    scopes: ['https://www.googleapis.com/auth/analytics.readonly']
  });

  const analytics = google.analytics({
    auth,
    version: 'v3'
  });

  const startDate = req.query.startDate;
  const response = await analytics.data.ga.get({
    'end-date': 'today',
    ids: 'ga:186371021',
    metrics: 'ga:pageviews',
    'start-date': startDate
  });

  return res.status(200).json({
    pageViews: response.data.rows[0][0]
  });
};

Example

Bonus: You can cache the API route with the cache-control header.

Cache-Control: public, max-age=120, stale-while-revalidate=60

Keep Reading

Create a Dashboard with Next.js API Routes

Subscribe to the newsletter

Get emails from me about web development, tech, and early access to new articles.

- subscribers – 28 issues