{"id":28455,"date":"2021-04-14T17:26:58","date_gmt":"2021-04-14T17:26:58","guid":{"rendered":"http:\/\/Capture-Video-Analytics-in-Gatsby.js-Sites"},"modified":"2023-11-24T08:41:40","modified_gmt":"2023-11-24T16:41:40","slug":"capture-video-analytics-in-gatsby-js-sites","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/","title":{"rendered":"Capture Video Analytics in Gatsby.js Sites"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>Video presentations currently deliver robust user experiences on different platforms. Because of this, it\u2019s often chosen as a go-to medium for sharing presentations, including product, educational, and entertainment content, among others.<\/p>\n<p>How do you track the data from engagements on your video content?<\/p>\n<p>This post discusses how to implement and collect video analytics data from a video on a website built with Gatsby.js. We\u2019ll utilize the Cloudinary video player to render remote videos and handle analytics on them.<\/p>\n<p>Gatsby.js is a Reactjs-based technology for building fast static sites and single-page applications.<\/p>\n<h2>Sandbox<\/h2>\n<p>We completed this project in <a href=\"https:\/\/codesandbox.io\/s\/mj-4-video-analytics-ftvnl\">a Codesandbox<\/a>, and you can fork it to get running.<\/p>\n<\/div>\n\n\n  <div class=\"wp-block-cloudinary-code-sandbox \">\n    <iframe\n      src=\"https:\/\/codesandbox.io\/embed\/mj-4-video-analytics-ftvnl?theme=dark&amp;codemirror=1&amp;highlights=&amp;editorsize=50&amp;fontsize=14&amp;expanddevtools=0&amp;hidedevtools=0&amp;eslint=0&amp;forcerefresh=0&amp;hidenavigation=0&amp;initialpath=%2F&amp;module=&amp;moduleview=0&amp;previewwindow=&amp;view=&amp;runonclick=1\"\n      height=\"500\"\n      style=\"width: 100%;\"\n      title=\"Capturing video analytics in Gatsby.js sites\"\n      loading=\"lazy\"\n      allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\"\n      sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n    ><\/iframe>\n  <\/div>\n\n\n<div class=\"wp-block-cloudinary-markdown \"><h2>Prerequisites and Installation<\/h2>\n<p>For this project, knowledge of JavaScript and React.js is required. The knowledge of Gatsby.js is pleasant to have, but isn\u2019t needed.<\/p>\n<p>To get started, we install the gatsby-cli globally and create a new Gatsby project using NPM &#8211; 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\u2019ll use the default starter.<\/p>\n<p>If you already have a Gatsby project running, you can skip this Gatsby installation step. In the desired directory for our project, we run:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    npm install -g gatsby-cli &amp;&amp; gatsby <span class=\"hljs-keyword\">new<\/span> video-site\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>This command creates a Gatsby project called <code>video-site<\/code>, using the default starter.<\/p>\n<p>We will utilize the Cloudinary video player to <a href=\"https:\/\/cloudinary.com\/glossary\/video-rendering\">render video<\/a> 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.<\/p>\n<p>We proceed to install the required dependencies with:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">    npm install --save gatsby-plugin-google-analytics cloudinary-core cloudinary-video-player\n<\/code><\/span><\/pre>\n<p><code>cloudinary-core<\/code> and <code>cloudinary-video-player<\/code> are required dependencies to render the video player. Also, <code>gatsby-plugin-google-analytics<\/code> adds the google analytics tracking script to our pages.<\/p>\n<blockquote>\n<p>Gatsby-plugin-google-analytics uses the universal analytics tracking code from Google Analytics. This plugin isn\u2019t compatible with the latest gtag.js tracking code and ID. Also, the cloudinary-video-player module isn\u2019t compatible (as of the time of writing) with the current gtag analytics system.<\/p>\n<\/blockquote>\n<p>We\u2019ll proceed to add the gatsby-plugin-google-analytics configuration to the gatsby-config.js file located in the project\u2019s root directory.<\/p>\n<p>We include the plugin configuration with<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-built_in\">module<\/span>.exports = {\n      <span class=\"hljs-attr\">siteMetadata<\/span>: {\n        <span class=\"hljs-attr\">title<\/span>: <span class=\"hljs-string\">`Gatsby Default Starter`<\/span>,\n        <span class=\"hljs-attr\">description<\/span>: <span class=\"hljs-string\">`Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`<\/span>,\n        <span class=\"hljs-attr\">author<\/span>: <span class=\"hljs-string\">`@gatsbyjs`<\/span>,\n      },\n      <span class=\"hljs-attr\">plugins<\/span>: &#91;\n       <span class=\"hljs-comment\">\/\/ other plugin configurations go in here<\/span>\n        {\n          <span class=\"hljs-attr\">resolve<\/span>: <span class=\"hljs-string\">`gatsby-plugin-google-analytics`<\/span>,\n          <span class=\"hljs-attr\">options<\/span>: {\n            <span class=\"hljs-attr\">trackingId<\/span>: <span class=\"hljs-string\">\"UA-111204936-2\"<\/span>,\n            <span class=\"hljs-attr\">head<\/span>: <span class=\"hljs-literal\">true<\/span>\n          }\n        }\n      ],\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>We specified the Google Analytics tracking ID obtained from our Google Analytics property settings. Also, we included the <code>head<\/code> property that adds the analytics tracking code within the head tags of our HTML code.<\/p>\n<p>One more required configuration is the exclusion of the cloudinary-video-player module during Gatsby\u2019s build process. The module requires the <code>window<\/code> API, which isn\u2019t available during our site\u2019s optimized build creation.<\/p>\n<p>We exclude the module in the gatsby-node.js file in the project\u2019s root directory using the <code>setWebpackConfig<\/code> API.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-comment\">\/\/ gatsby-node.js<\/span>\n    <span class=\"hljs-keyword\">const<\/span> path = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'path'<\/span>)\n    exports.onCreateWebpackConfig = <span class=\"hljs-function\">(<span class=\"hljs-params\">{ stage, loaders, actions }<\/span>) =&gt;<\/span> {\n      actions.setWebpackConfig({\n        <span class=\"hljs-attr\">resolve<\/span>: {\n          <span class=\"hljs-attr\">modules<\/span>: &#91;path.resolve(__dirname, <span class=\"hljs-string\">'src'<\/span>), <span class=\"hljs-string\">'node_modules'<\/span>],\n        },\n      })\n      <span class=\"hljs-keyword\">if<\/span>(stage === <span class=\"hljs-string\">\"build-html\"<\/span>){\n        actions.setWebpackConfig({\n          <span class=\"hljs-attr\">module<\/span>:{\n            <span class=\"hljs-attr\">rules<\/span>: &#91;\n              {\n                <span class=\"hljs-attr\">test<\/span>: <span class=\"hljs-regexp\">\/cld-video-player\/<\/span>,\n                <span class=\"hljs-attr\">use<\/span>: loaders.null()\n              }\n            ]\n          }\n        })\n      }\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>First, we added the <code>src<\/code> directory to the list of directories. Webpack will check for modules to resolve. Then, we checked the build process stage if it\u2019s in the \u2018build-html\u2019 stage before applying a rule to the <code>cld-video-player<\/code> module. This rule excludes the module during the build using a <em>null<\/em> loader.<\/p>\n<h2>Video player creation<\/h2>\n<p>In <em>src\/components,<\/em> we create a file named video-player.js, which would house the video player component. First, we import all required dependencies with:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> React, { useEffect } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>\n    <span class=\"hljs-keyword\">import<\/span> cloudinary <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"cloudinary-core\"<\/span>\n    <span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">\"cloudinary-video-player\/dist\/cld-video-player.js\"<\/span>\n    <span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">\"cloudinary-video-player\/dist\/cld-video-player.min.css\"<\/span> \n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Next, we create a function component for the video player, which returns an HTML <code>&lt;video\/&gt;<\/code> element with an id.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> VideoPlayer = <span class=\"hljs-function\">(<span class=\"hljs-params\">{ publicId }<\/span>) =&gt;<\/span> {\n    \n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">maxWidth:<\/span> \"<span class=\"hljs-attr\">500px<\/span>\" }}&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">video<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">{<\/span>\"<span class=\"hljs-attr\">cl-vp<\/span>\"} \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n      )\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>This component accepts a prop of <code>publicId<\/code>, which will eventually be passed the publicId of a video, stored on Cloudinary.<\/p>\n<p>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 \u201ccl-vp\u201d which is already rendered by the component.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">let<\/span> cld = cloudinary.Cloudinary.new({ <span class=\"hljs-attr\">cloud_name<\/span>: <span class=\"hljs-string\">\"chuloo\"<\/span>, <span class=\"hljs-attr\">secure<\/span>: <span class=\"hljs-literal\">true<\/span> })\n      useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n        <span class=\"hljs-comment\">\/\/ create a new cloudinary instance with config<\/span>\n        <span class=\"hljs-keyword\">let<\/span> vidPlayer = cld.videoPlayer(<span class=\"hljs-string\">\"cl-vp\"<\/span>, {\n          <span class=\"hljs-attr\">loop<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">controls<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">autoPlay<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">width<\/span>: <span class=\"hljs-number\">500<\/span>,\n          <span class=\"hljs-attr\">playedEventPercents<\/span>: &#91;<span class=\"hljs-number\">10<\/span>, <span class=\"hljs-number\">50<\/span>, <span class=\"hljs-number\">90<\/span>],\n          <span class=\"hljs-attr\">analytics<\/span>: {\n            <span class=\"hljs-attr\">events<\/span>: &#91;\n              <span class=\"hljs-string\">\"play\"<\/span>,\n              <span class=\"hljs-string\">\"pause\"<\/span>,\n              <span class=\"hljs-string\">\"ended\"<\/span>,\n              <span class=\"hljs-string\">\"percentsplayed\"<\/span>,\n              <span class=\"hljs-string\">\"error\"<\/span>,\n              <span class=\"hljs-string\">\"volumechange\"<\/span>,\n              <span class=\"hljs-string\">\"mute\"<\/span>,\n              <span class=\"hljs-string\">\"unmute\"<\/span>,\n              <span class=\"hljs-string\">\"qualitychanged\"<\/span>,\n              <span class=\"hljs-string\">\"seek\"<\/span>,\n              <span class=\"hljs-string\">\"fullscreenchange\"<\/span>\n            ]\n          }\n        })\n      }, &#91;publicId, cld])\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>To obtain your cloud_name, you need to <a href=\"https:\/\/cloudinary.com\/signup\">create an account on Cloudinary<\/a> and get the cloud name value from your Cloudinary dashboard.<\/p>\n<p>In the snippet above, we specified multiple video player and analytics options. You can find <a href=\"https:\/\/cloudinary.com\/documentation\/video_player_api_reference\">all options on Cloudinary<\/a>. Cloudinary-video-player sends all events triggered, along with event parameters, to our Google Analytics dashboard. You can also find the <a href=\"https:\/\/cloudinary.com\/documentation\/video_player_api_reference#events\">list of trackable events on Cloudinary<\/a>.<\/p>\n<p>Lastly, in the  <code>VideoPlayer<\/code> component\u2019s <code>useEffect<\/code> function, we specify the video source, which is the publicId of the video on Cloudinary.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">    <span class=\"hljs-selector-tag\">vidPlayer<\/span><span class=\"hljs-selector-class\">.source<\/span>(<span class=\"hljs-selector-tag\">publicId<\/span>)\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In the site\u2019s home page, we render the component in the <code>IndexPage<\/code> component located in <code>src\/pages.index.js<\/code> by updating it with:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> { VideoPlayer } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/video-player\"<\/span>\n    \n    <span class=\"hljs-keyword\">const<\/span> IndexPage = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> (\n      <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Layout<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">SEO<\/span> <span class=\"hljs-attr\">title<\/span>=<span class=\"hljs-string\">\"Home\"<\/span> \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Hi people<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Welcome to your new Gatsby site.<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Now go build something great.<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">VideoPlayer<\/span> <span class=\"hljs-attr\">publicId<\/span>=<span class=\"hljs-string\">{<\/span>\"<span class=\"hljs-attr\">video-blog<\/span>\/<span class=\"hljs-attr\">cockerels<\/span>\"} \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Link<\/span> <span class=\"hljs-attr\">to<\/span>=<span class=\"hljs-string\">\"\/page-2\/\"<\/span>&gt;<\/span>Go to page 2<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Link<\/span>&gt;<\/span> <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">br<\/span> \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Link<\/span> <span class=\"hljs-attr\">to<\/span>=<span class=\"hljs-string\">\"\/using-typescript\/\"<\/span>&gt;<\/span>Go to \"Using TypeScript\"<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Link<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Layout<\/span>&gt;<\/span><\/span>\n    )\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>With this, the home page looks like this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_8D6AA6A819BDE290A1B1EB6ECCC42E722430196879A7EA341680D31DA266ED1D_1616420236653_image.png\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"740\" height=\"722\"\/><\/p>\n<h2>Data Visualization on Google Analytics<\/h2>\n<p>To send the data to Google Analytics, we need to deploy the site and specify the URL in Google Analytics. We deployed our <a href=\"https:\/\/silly-beaver-022c88.netlify.app\/\">sample site to Netlify<\/a> from GitHub in a few clicks, and you can find the URL here.<\/p>\n<blockquote>\n<p>The gatsby-plugin-google-analytics plugin doesn\u2019t send data to Google analytics in development. A production build is required. You can also create a production build using the <code>gatsby build<\/code> command and run it locally using <code>gatsby serve<\/code>.<\/p>\n<\/blockquote>\n<p>On Google Analytics, we go to the <em>Events<\/em> menu under the <em>Realtime<\/em> side-menu to see the data stream in real-time.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_8D6AA6A819BDE290A1B1EB6ECCC42E722430196879A7EA341680D31DA266ED1D_1616420981111_video-analytics.gif\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"480\" height=\"376\"\/><\/p>\n<p>On the site, we can use event handlers to manage the events triggered by the video, using the <code>on()<\/code> 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 \u2018pause\u2019 event, and trigger a function once emitted.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    vidPlayer.on(<span class=\"hljs-string\">'pause'<\/span>, <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">\"Why did you pause me\"<\/span>)) \n    vidPlayer.on(<span class=\"hljs-string\">'mute'<\/span>, sendLightMessage())\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>These events will also be sent to Google Analytics regardless.<\/p>\n<h2>Summary<\/h2>\n<p>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.<\/p>\n<p>Check out the following valuable resources<\/p>\n<ul>\n<li>\n<a href=\"https:\/\/www.gatsbyjs.com\/plugins\/gatsby-plugin-google-analytics\/\">Gatsby-plugin-google-analytics<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/developers.google.com\/analytics\/devguides\/collection\/upgrade\/analyticsjs\">Upgrading Google Analytics snippet to Gtag<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/cloudinary.com\/documentation\/video_player_api_reference\">Cloudinary video player reference<\/a>\n<\/li>\n<\/ul>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":28456,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[378,134,382,246,371,303],"class_list":["post-28455","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-gatsbyjs","tag-guest-post","tag-player-video","tag-react","tag-under-review","tag-video"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Capture Video Analytics in Gatsby.js Sites<\/title>\n<meta name=\"description\" content=\"Track analytics on your video content on Gatsby.js sites using Google analytics on the Cloudinary video player\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Capture Video Analytics in Gatsby.js Sites\" \/>\n<meta property=\"og:description\" content=\"Track analytics on your video content on Gatsby.js sites using Google analytics on the Cloudinary video player\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2021-04-14T17:26:58+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-11-24T16:41:40+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1681924484\/Web_Assets\/blog\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2-jpg?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"3999\" \/>\n\t<meta property=\"og:image:height\" content=\"2666\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Capture Video Analytics in Gatsby.js Sites\",\"datePublished\":\"2021-04-14T17:26:58+00:00\",\"dateModified\":\"2023-11-24T16:41:40+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/\"},\"wordCount\":7,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924484\/Web_Assets\/blog\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2.jpg?_i=AA\",\"keywords\":[\"GatsbyJS\",\"Guest Post\",\"Player Video\",\"React\",\"Under Review\",\"Video\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2021\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/\",\"url\":\"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/\",\"name\":\"Capture Video Analytics in Gatsby.js Sites\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924484\/Web_Assets\/blog\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2.jpg?_i=AA\",\"datePublished\":\"2021-04-14T17:26:58+00:00\",\"dateModified\":\"2023-11-24T16:41:40+00:00\",\"description\":\"Track analytics on your video content on Gatsby.js sites using Google analytics on the Cloudinary video player\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924484\/Web_Assets\/blog\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924484\/Web_Assets\/blog\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2.jpg?_i=AA\",\"width\":3999,\"height\":2666},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Capture Video Analytics in Gatsby.js Sites\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Capture Video Analytics in Gatsby.js Sites","description":"Track analytics on your video content on Gatsby.js sites using Google analytics on the Cloudinary video player","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/","og_locale":"en_US","og_type":"article","og_title":"Capture Video Analytics in Gatsby.js Sites","og_description":"Track analytics on your video content on Gatsby.js sites using Google analytics on the Cloudinary video player","og_url":"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/","og_site_name":"Cloudinary Blog","article_published_time":"2021-04-14T17:26:58+00:00","article_modified_time":"2023-11-24T16:41:40+00:00","og_image":[{"width":3999,"height":2666,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1681924484\/Web_Assets\/blog\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2-jpg?_i=AA","type":"image\/jpeg"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/"},"author":{"name":"","@id":""},"headline":"Capture Video Analytics in Gatsby.js Sites","datePublished":"2021-04-14T17:26:58+00:00","dateModified":"2023-11-24T16:41:40+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/"},"wordCount":7,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924484\/Web_Assets\/blog\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2.jpg?_i=AA","keywords":["GatsbyJS","Guest Post","Player Video","React","Under Review","Video"],"inLanguage":"en-US","copyrightYear":"2021","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/","url":"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/","name":"Capture Video Analytics in Gatsby.js Sites","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924484\/Web_Assets\/blog\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2.jpg?_i=AA","datePublished":"2021-04-14T17:26:58+00:00","dateModified":"2023-11-24T16:41:40+00:00","description":"Track analytics on your video content on Gatsby.js sites using Google analytics on the Cloudinary video player","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924484\/Web_Assets\/blog\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924484\/Web_Assets\/blog\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2.jpg?_i=AA","width":3999,"height":2666},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/capture-video-analytics-in-gatsby-js-sites\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Capture Video Analytics in Gatsby.js Sites"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924484\/Web_Assets\/blog\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2\/cbafbcff2f0a523d91f16c5bccf8579fe63e5a7a-3999x2666-1_28456989c2.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28455","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=28455"}],"version-history":[{"count":3,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28455\/revisions"}],"predecessor-version":[{"id":31884,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28455\/revisions\/31884"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/28456"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=28455"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=28455"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=28455"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}