Just a few weeks until the 2021 JavaScript Full-Stack Bootcamp opens.
Signup to the waiting list!
Note: uBlock Origin blocks the images on this post, because they have the
analytics
word in the path. So make sure you disable it for this page, to see the images 🖼
In this post I’m going to show some examples of using the Google Analytics API with Node.js.
- Environment variables
- Add the user to Google Analytics
- Import the Google library
- Define the scope
- The Google Analytics Reporting API
- Create the JWT
- Perform a request
- Metrics
- Common code
- Get the number of today sessions
- Get the number of today sessions coming from organic sources (Search Engines)
- Get the number of yesterday sessions
- Get the number of sessions in the last 30 days
- Get the browsers used in the last 30 days
- Get the number of visitors using Chrome
- Get the sessions by traffic source
- The Google Analytics Real Time API
Google offers a great npm package: googleapis
. We’re going to use that as the base building block of our API interaction.
Authentication is a big part of interacting with an API. Check out this post on how to authenticate to the Google APIs. In this article I’m going to assume you read that, and you know how to perform a JWT authentication.
Environment variables
Once you download the JSON Key file from Google, put the client_email
and private_key
values as environment variables, so that they will be accessible through
process.env.CLIENT_EMAIL
process.env.PRIVATE_KEY
Add the user to Google Analytics
Since we’re using the Service to Service API in these examples, you need to add the client_email
value to your Google Analytics profile. Go to the Admin panel and click User Management, either on a property or on a view.
And add the email you found in the client_email
key in the JSON file:
Import the Google library
const { google } = require('googleapis')
Remember the {}
around the google
object, as we need to destructure it from the googleapis
library (otherwise we’d need to call google.google
and it’s ugly)
Define the scope
This line sets the scope:
const scopes = 'https://www.googleapis.com/auth/analytics.readonly'
Google Analytics API defines several scopes:
https://www.googleapis.com/auth/analytics.readonly
to view the datahttps://www.googleapis.com/auth/analytics
to view and manage the datahttps://www.googleapis.com/auth/analytics.edit
to edit the management entitieshttps://www.googleapis.com/auth/analytics.manage.users
to manage the account users and permissionshttps://www.googleapis.com/auth/analytics.manage.users.readonly
to view the users and their permissionshttps://www.googleapis.com/auth/analytics.provision
to create new Google Analytics accounts
You should always pick the scope that grants the least amount of power.
Since we want to only view the reports now, we pick https://www.googleapis.com/auth/analytics.readonly
instead of https://www.googleapis.com/auth/analytics
.
The Google Analytics Reporting API
Note: you can also use the Google Analytics Reporting API to access those permissions.
It is a trimmed-down version of the Google Analytics API, offering just the scope https://www.googleapis.com/auth/analytics.readonly
and https://www.googleapis.com/auth/analytics
.
The API is slightly different than the Analytics API however in how it’s used and in which methods it exposes, so we’ll skip that.
Create the JWT
const jwt = new google.auth.JWT(process.env.CLIENT_EMAIL, null, process.env.PRIVATE_KEY, scopes)
Perform a request
Check this code:
const { google } = require('googleapis')
const scopes = 'https://www.googleapis.com/auth/analytics.readonly'
const jwt = new google.auth.JWT(process.env.CLIENT_EMAIL, null, process.env.PRIVATE_KEY, scopes)
const view_id = 'XXXXX'
async function getData() {
const response = await jwt.authorize()
const result = await google.analytics('v3').data.ga.get({
'auth': jwt,
'ids': 'ga:' + view_id,
'start-date': '30daysAgo',
'end-date': 'today',
'metrics': 'ga:pageviews'
})
console.dir(result)
}
getData()
It performs a request to the Google Analytics API to fetch the pageviews number in the last 30 days.
view_id
contains the ID of the view. Not your Google Analytics code, but the view ID. You can get that from the admin panel, by clicking View Settings on the view you want to access:
You pass this object to the request:
{
'auth': jwt,
'ids': 'ga:' + view_id,
'start-date': '30daysAgo',
'end-date': 'today',
'metrics': 'ga:pageviews'
}
In addition to the jwt object and the view id, we have 3 parameters.
metrics
: tells the API what we want to getstart-date
: defines the starting date for the reportend-date
: defines the end date for the report
This request is very simple and returns the number of pageviews occurring in the specified time period.
The returned result will be something like:
{
status: 200,
statusText: 'OK',
headers: {...},
config: {...},
request: {...},
data: {
kind: 'analytics#gaData',
id: 'https://www.googleapis.com/analytics/v3/data/ga?ids=ga:XXXXXXXXXXXXXXXXXX&metrics=ga:pageviews&start-date=30daysAgo&end-date=today',
query: {
'start-date': '30daysAgo',
'end-date': 'today',
ids: 'ga:XXXXXXXXXXXXXXXXXX',
metrics: [ 'ga:pageviews' ],
'start-index': 1,
'max-results': 1000
},
itemsPerPage: 1000,
totalResults: 1,
selfLink: 'https://www.googleapis.com/analytics/v3/data/ga?ids=ga:XXXXXXXXXXXXXXXXXX&metrics=ga:pageviews&start-date=30daysAgo&end-date=today',
profileInfo: {
profileId: 'XXXXXXXXXXXXXXXXXX',
accountId: 'XXXXXXXXXXXXXXXXXX',
webPropertyId: 'UA-XXXXXXXXXXX--XX',
internalWebPropertyId: 'XXXXXXXXXXXXXXXXXX',
profileName: 'XXXXXXXXXXXXXXXXXX',
tableId: 'ga:XXXXXXXXXXXXXXXXXX'
},
containsSampledData: false,
columnHeaders: [
{
name: 'ga:pageviews',
columnType: 'METRIC',
dataType: 'INTEGER'
}
],
totalsForAllResults: { 'ga:pageviews': '3000' },
rows: [ [ '114426' ] ] }
}
With this You can access the pageviews count in response.data.rows[0][0]
.
Metrics
This example was simple. We just asked for this data:
{
'start-date': '30daysAgo',
'end-date': 'today',
'metrics': 'ga:pageviews'
}
There is a whole lot of data we can use.
The Dimensions & Metrics Explorer is an awesome tool to discover all the options.
Those terms are two concepts of Google Analytics.
Dimensions are attributes, like City, Country or Page, the referral path or the session duration.
Metrics are quantitative measurements, like the number of users or the number of sessions.
Some examples of metrics:
- get the pageviews
ga:pageviews
- get the unique users
ga:users
- get the sessions
ga:sessions
- get the organic searches
ga:organicSearches
Let’s build some examples with those metrics.
Common code
Here is the common code used in the examples below. Put the snippet in the authorize()
callback.
'use strict'
const { google } = require('googleapis')
const scopes = 'https://www.googleapis.com/auth/analytics.readonly'
const jwt = new google.auth.JWT(process.env.CLIENT_EMAIL, null, process.env.PRIVATE_KEY, scopes)
async function getData() {
const defaults = {
'auth': jwt,
'ids': 'ga:' + process.env.VIEW_ID,
}
const response = await jwt.authorize()
/* custom code goes here, using `response` */
}
getData()
The defaults object will be reused in the examples using the spread operator, which is a handy way of handling defaults values in JavaScript.
Get the number of today sessions
const result = await google.analytics('v3').data.ga.get({
...defaults,
'start-date': 'today',
'end-date': 'today',
'metrics': 'ga:sessions'
})
console.dir(result.data.rows[0][0])
Get the number of today sessions coming from organic sources (Search Engines)
Add the filters
property:
const result = await google.analytics('v3').data.ga.get({
...defaults,
'start-date': 'today',
'end-date': 'today',
'metrics': 'ga:sessions',
'filters': 'ga:medium==organic',
})
Get the number of yesterday sessions
const result = await google.analytics('v3').data.ga.get({
...defaults,
'start-date': 'yesterday',
'end-date': 'yesterday',
'metrics': 'ga:sessions'
})
console.dir(result.data.rows[0][0])
Get the number of sessions in the last 30 days
const result = await google.analytics('v3').data.ga.get({
...defaults,
'start-date': '30daysAgo',
'end-date': 'today',
'metrics': 'ga:sessions'
})
console.dir(result.data.rows[0][0])
Get the browsers used in the last 30 days
const result = await google.analytics('v3').data.ga.get({
...defaults,
'start-date': '30daysAgo',
'end-date': 'today',
'dimensions': 'ga:browser',
'metrics': 'ga:sessions'
})
console.dir(result.data.rows.sort((a, b) => b[1] - a[1]))
[
[ 'Chrome', '994' ],
[ 'Safari', '548' ],
[ 'Firefox', '442' ],
[ 'Android Webview', '113' ],
[ 'Opera', '56' ],
[ 'Safari (in-app)', '41' ],
[ 'Edge', '36' ],
[ 'Internet Explorer', '4' ]
]
Get the number of visitors using Chrome
const result = await google.analytics('v3').data.ga.get({
...defaults,
'start-date': '30daysAgo',
'end-date': 'today',
'dimensions': 'ga:browser',
'metrics': 'ga:sessions',
'filters': 'ga:browser==Chrome',
})
console.dir(result.data.rows[0][1])
Get the sessions by traffic source
const result = await google.analytics('v3').data.ga.get({
...defaults,
'start-date': '30daysAgo',
'end-date': 'today',
'dimensions': 'ga:source',
'metrics': 'ga:sessions'
})
console.dir(result.data.rows.sort((a, b) => b[1] - a[1]))
[
[ 'google', '1343' ],
[ '(direct)', '731' ],
[ 'medium.com', '624' ],
[ 't.co', '987' ],
[ 'reddit.com', '65' ]
]
The Google Analytics Real Time API
The Google Analytics Real Time API is [May 2018] in private beta, and it’s not publicly accessible. Check this page.
Download my free Node.js Handbook
The 2021 JavaScript Full-Stack Bootcamp will start at the end of March 2021. Don't miss this opportunity, signup to the waiting list!
More node tutorials:
- An introduction to the npm package manager
- Introduction to Node.js
- HTTP requests using Axios
- Where to host a Node.js app
- Interact with the Google Analytics API using Node.js
- The npx Node Package Runner
- The package.json guide
- Where does npm install the packages?
- How to update Node.js
- How to use or execute a package installed using npm
- The package-lock.json file
- Semantic Versioning using npm
- Should you commit the node_modules folder to Git?
- Update all the Node dependencies to their latest version
- Parsing JSON with Node.js
- Find the installed version of an npm package
- Node.js Streams
- Install an older version of an npm package
- Get the current folder in Node
- How to log an object in Node
- Expose functionality from a Node file using exports
- Differences between Node and the Browser
- Make an HTTP POST request using Node
- Get HTTP request body data using Node
- Node Buffers
- A brief history of Node.js
- How to install Node.js
- How much JavaScript do you need to know to use Node?
- How to use the Node.js REPL
- Node, accept arguments from the command line
- Output to the command line using Node
- Accept input from the command line in Node
- Uninstalling npm packages with `npm uninstall`
- npm global or local packages
- npm dependencies and devDependencies
- The Node.js Event Loop
- Understanding process.nextTick()
- Understanding setImmediate()
- The Node Event emitter
- Build an HTTP Server
- Making HTTP requests with Node
- The Node fs module
- HTTP requests in Node using Axios
- Reading files with Node
- Node File Paths
- Writing files with Node
- Node file stats
- Working with file descriptors in Node
- Working with folders in Node
- The Node path module
- The Node http module
- Using WebSockets with Node.js
- The basics of working with MySQL and Node
- Error handling in Node.js
- The Pug Guide
- How to read environment variables from Node.js
- How to exit from a Node.js program
- The Node os module
- The Node events module
- Node, the difference between development and production
- How to check if a file exists in Node.js
- How to create an empty file in Node.js
- How to remove a file with Node.js
- How to get the last updated date of a file using Node.js
- How to determine if a date is today in JavaScript
- How to write a JSON object to file in Node.js
- Why should you use Node.js in your next project?
- Run a web server from any folder
- How to use MongoDB with Node.js
- Use the Chrome DevTools to debug a Node.js app
- What is pnpm?
- The Node.js Runtime v8 options list
- How to fix the "Missing write access" error when using npm
- How to enable ES Modules in Node.js
- How to spawn a child process with Node.js
- How to get both parsed body and raw body in Express
- How to handle file uploads in Node.js
- What are peer dependencies in a Node module?
- How to write a CSV file with Node.js
- How to read a CSV file with Node.js
- The Node Core Modules
- Incrementing multiple folders numbers at once using Node.js
- How to print a canvas to a data URL
- How to create and save an image with Node.js and Canvas
- How to download an image using Node.js
- How to mass rename files in Node.js
- How to get the names of all the files in a folder in Node
- How to use promises and await with Node.js callback-based functions
- How to test an npm package locally
- How to check the current Node.js version at runtime
- How to use Sequelize to interact with PostgreSQL
- Serve an HTML page using Node.js
- How to solve the `util.pump is not a function` error in Node.js