Capture Video Analytics in Gatsby.js Sites

Banner for a MediaJam post

William Imoh

Video presentations currently deliver robust user experiences on different platforms. Because of this, it’s often chosen as a go-to medium for sharing presentations, including product, educational, and entertainment content, among others.

How do you track the data from engagements on your video content?

This post discusses how to implement and collect video analytics data from a video on a website built with Gatsby.js. We’ll utilize the Cloudinary video player to render remote videos and handle analytics on them.

Gatsby.js is a Reactjs-based technology for building fast static sites and single-page applications.


We completed this project in a Codesandbox, and you can fork it to get running.

Prerequisites and Installation

For this project, knowledge of JavaScript and React.js is required. The knowledge of Gatsby.js is pleasant to have, but isn’t needed.

To get started, we install the gatsby-cli globally and create a new Gatsby project using NPM - a command line package manager. You can also use Yarn. Gatsby ships starters, which we use to scaffold projects quickly, and in this project, we’ll use the default starter.

If you already have a Gatsby project running, you can skip this Gatsby installation step. In the desired directory for our project, we run:

1npm install -g gatsby-cli && gatsby new video-site

This command creates a Gatsby project called video-site, using the default starter.

We will utilize the Cloudinary video player to render video from a remote content delivery network on Cloudinary. The video player is efficient as we can apply multiple optimization and transformation features to the resulting video.

We proceed to install the required dependencies with:

1npm install --save gatsby-plugin-google-analytics cloudinary-core cloudinary-video-player

cloudinary-core and cloudinary-video-player are required dependencies to render the video player. Also, gatsby-plugin-google-analytics adds the google analytics tracking script to our pages.

Gatsby-plugin-google-analytics uses the universal analytics tracking code from Google Analytics. This plugin isn’t compatible with the latest gtag.js tracking code and ID. Also, the cloudinary-video-player module isn’t compatible (as of the time of writing) with the current gtag analytics system.

We’ll proceed to add the gatsby-plugin-google-analytics configuration to the gatsby-config.js file located in the project’s root directory.

We include the plugin configuration with

1module.exports = {
2 siteMetadata: {
3 title: `Gatsby Default Starter`,
4 description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
5 author: `@gatsbyjs`,
6 },
7 plugins: [
8 // other plugin configurations go in here
9 {
10 resolve: `gatsby-plugin-google-analytics`,
11 options: {
12 trackingId: "UA-111204936-2",
13 head: true
14 }
15 }
16 ],
17 }

We specified the Google Analytics tracking ID obtained from our Google Analytics property settings. Also, we included the head property that adds the analytics tracking code within the head tags of our HTML code.

One more required configuration is the exclusion of the cloudinary-video-player module during Gatsby’s build process. The module requires the window API, which isn’t available during our site’s optimized build creation.

We exclude the module in the gatsby-node.js file in the project’s root directory using the setWebpackConfig API.

1// gatsby-node.js
2 const path = require('path')
3 exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
4 actions.setWebpackConfig({
5 resolve: {
6 modules: [path.resolve(__dirname, 'src'), 'node_modules'],
7 },
8 })
9 if(stage === "build-html"){
10 actions.setWebpackConfig({
11 module:{
12 rules: [
13 {
14 test: /cld-video-player/,
15 use: loaders.null()
16 }
17 ]
18 }
19 })
20 }
21 }

First, we added the src directory to the list of directories. Webpack will check for modules to resolve. Then, we checked the build process stage if it’s in the ‘build-html’ stage before applying a rule to the cld-video-player module. This rule excludes the module during the build using a null loader.

Video player creation

In src/components, we create a file named video-player.js, which would house the video player component. First, we import all required dependencies with:

1import React, { useEffect } from "react"
2 import cloudinary from "cloudinary-core"
3 import "cloudinary-video-player/dist/cld-video-player.js"
4 import "cloudinary-video-player/dist/cld-video-player.min.css"

Next, we create a function component for the video player, which returns an HTML <video/> element with an id.

1export const VideoPlayer = ({ publicId }) => {
3 return (
4 <div style={{ maxWidth: "500px" }}>
5 <video id={"cl-vp"} />
6 </div>
7 )
8 }

This component accepts a prop of publicId, which will eventually be passed the publicId of a video, stored on Cloudinary.

In the VideoPlayer component, we create and configure a new Cloudinary instance. Then create a video player instance mounted on the DOM element with an ID of “cl-vp” which is already rendered by the component.

1let cld ={ cloud_name: "chuloo", secure: true })
2 useEffect(() => {
3 // create a new cloudinary instance with config
4 let vidPlayer = cld.videoPlayer("cl-vp", {
5 loop: true,
6 controls: true,
7 autoPlay: true,
8 width: 500,
9 playedEventPercents: [10, 50, 90],
10 analytics: {
11 events: [
12 "play",
13 "pause",
14 "ended",
15 "percentsplayed",
16 "error",
17 "volumechange",
18 "mute",
19 "unmute",
20 "qualitychanged",
21 "seek",
22 "fullscreenchange"
23 ]
24 }
25 })
26 }, [publicId, cld])

To obtain your cloud_name, you need to create an account on Cloudinary and get the cloud name value from your Cloudinary dashboard.

In the snippet above, we specified multiple video player and analytics options. You can find all options on Cloudinary. Cloudinary-video-player sends all events triggered, along with event parameters, to our Google Analytics dashboard. You can also find the list of trackable events on Cloudinary.

Lastly, in the VideoPlayer component’s useEffect function, we specify the video source, which is the publicId of the video on Cloudinary.


In the site’s home page, we render the component in the IndexPage component located in src/pages.index.js by updating it with:

1import { VideoPlayer } from "../components/video-player"
3 const IndexPage = () => (
4 <Layout>
5 <SEO title="Home" />
6 <h1>Hi people</h1>
7 <p>Welcome to your new Gatsby site.</p>
8 <p>Now go build something great.</p>
9 <VideoPlayer publicId={"video-blog/cockerels"} />
10 <p>
11 <Link to="/page-2/">Go to page 2</Link> <br />
12 <Link to="/using-typescript/">Go to "Using TypeScript"</Link>
13 </p>
14 </Layout>
15 )

With this, the home page looks like this:

Data Visualization on Google Analytics

To send the data to Google Analytics, we need to deploy the site and specify the URL in Google Analytics. We deployed our sample site to Netlify from GitHub in a few clicks, and you can find the URL here.

The gatsby-plugin-google-analytics plugin doesn’t send data to Google analytics in development. A production build is required. You can also create a production build using the gatsby build command and run it locally using gatsby serve.

On Google Analytics, we go to the Events menu under the Realtime side-menu to see the data stream in real-time.

On the site, we can use event handlers to manage the events triggered by the video, using the on() method. For example, suppose we want to call a function once a user pauses a video. In the VideoPlayer component, we can watch for the ‘pause’ event, and trigger a function once emitted.

1vidPlayer.on('pause', console.log("Why did you pause me"))
2 vidPlayer.on('mute', sendLightMessage())

These events will also be sent to Google Analytics regardless.


In this post, we created a sample Gatsby.js site, and added Google Analytics to it, with which we track page views and events. Also, we made a video player using the Cloudinary Video player and specified events sent to Google Analytics from the video player. You can explore extending the functionality of your app using events from your videos.

Check out the following valuable resources

William Imoh

Creating tech solutions and talking about them

William is a developer, developer advocate, and product manager. When he's not working on technology, he's organizing game nights, making drinks, or playing basketball.