{"id":33610,"date":"2024-05-02T07:00:00","date_gmt":"2024-05-02T14:00:00","guid":{"rendered":"https:\/\/cloudinary.com\/blog\/?p=33610"},"modified":"2024-05-01T15:48:16","modified_gmt":"2024-05-01T22:48:16","slug":"gathering-analytics-videos-uploaded-to-cloudinary","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary","title":{"rendered":"Gathering Analytics for Your Videos Uploaded to Cloudinary"},"content":{"rendered":"\n<p>Have you ever wondered how your videos are doing once you upload them to <a href=\"https:\/\/cloudinary.com\/\">Cloudinary<\/a>? Knowing who&#8217;s watching, from where, and how they engage with your videos can be super helpful. It&#8217;s like getting a sneak peek into your audience&#8217;s likes and dislikes, helping you make even cooler videos in the future.&nbsp;<\/p>\n\n\n\n<p>In this blog post, we&#8217;ll dive into how you can gather all these insights, or as the tech folks call it, analytics, for your videos on Cloudinary. We&#8217;ll also introduce <a href=\"https:\/\/posthog.com\/\">PostHog<\/a>, a versatile analytics tool, to demonstrate how to extend these insights beyond Cloudinary and enrich your analytics capabilities across different platforms. And we&#8217;ll do all of this using <a href=\"http:\/\/next.js\">Next.js<\/a>.<\/p>\n\n\n\n<p>While Cloudinary will handle the video management, PostHog will provide us with the detailed insights we need. It will seamlessly integrate with our Next.js framework to ensure we&#8217;re not just uploading videos but also understanding how our audience receives them.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Getting Started<\/strong><\/h2>\n\n\n\n<p>There are a few things we need to set up. Don&#8217;t worry. It&#8217;s all pretty straightforward.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/cloudinary.com\/users\/register_free\"><strong>Cloudinary account<\/strong><\/a>. If you haven&#8217;t already, sign up for a Cloudinary account. It&#8217;s where all our videos will live and be managed.<\/li>\n\n\n\n<li><a href=\"https:\/\/us.posthog.com\/login\"><strong>PostHog account<\/strong><\/a>. Sign up for PostHog, too. This is where we&#8217;ll gather all the analytics on our videos.<\/li>\n\n\n\n<li><a href=\"https:\/\/nextjs.org\/docs\"><strong>Next.js App Router<\/strong><\/a>. Make sure you&#8217;ve got the Next.js App Router setup. That&#8217;s where our app will hang out. We could use the regular pages router, but for this demo, let&#8217;s stick with the App Router to stay on the cutting edge.<\/li>\n\n\n\n<li><a href=\"https:\/\/next.cloudinary.dev\/installation\"><strong>Next-Cloudinary package<\/strong><\/a>. Grab the next-cloudinary package. It&#8217;s a handy tool that makes integrating Cloudinary into our Next.js app a breeze.<\/li>\n\n\n\n<li><a href=\"https:\/\/www.npmjs.com\/package\/posthog-js\"><strong>PostHog-JS package<\/strong><\/a>. To seamlessly integrate PostHog analytics into our Next.js app, we&#8217;ll also need the posthog-js package. This will allow us to track and analyze how users interact with our videos directly from our app.<\/li>\n<\/ul>\n\n\n\n<p>With our Cloudinary and PostHog accounts ready, it&#8217;s time to kick things off by setting up our Next.js app. Let&#8217;s start with this command:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-tag\">npx<\/span> <span class=\"hljs-selector-tag\">create-next-app<\/span><span class=\"hljs-keyword\">@latest<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><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\n\n<p>This will get the ball rolling. You&#8217;ll see a few prompts asking for details about your new app. Here&#8217;s what you need to do:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Name your app<\/strong>. Pick a cool name that resonates with your project.<\/li>\n\n\n\n<li><strong>Enable app router<\/strong>. Make sure to turn this feature on; it&#8217;s crucial for navigating our app.<\/li>\n<\/ul>\n\n\n\n<p>The other steps are optional and entirely your choice. In my case, I went with TypeScript and Tailwind CSS as well.<\/p>\n\n\n\n<p>Once our app is scaffolded, the next step is to beef it up with some necessary packages. Run the following command to install both <strong>next-cloudinary<\/strong> for easy Cloudinary integration in our app:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-wrap-lines\">npm install next-cloudinary<\/code><\/span><\/pre>\n\n\n<p>Once you have these ready, there&#8217;s one more step: setting up environment variables in your Next.js app. These variables will securely store key information needed for our app to communicate with Cloudinary and PostHog:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME<\/code>. This is your Cloudinary cloud name, a unique identifier for your Cloudinary account.<\/li>\n\n\n\n<li><code>NEXT_PUBLIC_POSTHOG_KEY<\/code>. Your PostHog project API key is essential for sending data to PostHog.<\/li>\n\n\n\n<li><code>NEXT_PUBLIC_POSTHOG_HOST<\/code>. The PostHog server URL. For most users, this will be <strong>https:\/\/app.posthog.com<\/strong>.<\/li>\n<\/ul>\n\n\n\n<p>And just like that, we&#8217;re ready to dive into the fun part: building our app!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Adding Analytics to Our Videos<\/strong><\/h2>\n\n\n\n<p>Now that we\u2019re done with our environment and dependencies, it&#8217;s time to dive into the core of our project: integrating video content with analytics. We&#8217;ll start by building a video player component in our Next.js app that uses Cloudinary for video management.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Creating our Video Player Component<\/strong><\/h3>\n\n\n\n<p>First, let&#8217;s set up the component where our videos will live. In the root of your Next.js app, navigate to the <code>App<\/code> directory and create a new folder named <code>components<\/code>.<\/p>\n\n\n\n<p>Inside the <code>components<\/code> folder, create a new file for our component and name it <code>VideoPlayer.tsx<\/code> (or just <code>jsx<\/code>, depending on if you didn\u2019t choose typescript). This component will utilize the <code>next-cloudinary<\/code> package to render videos stored in Cloudinary.<\/p>\n\n\n\n<p>When working with Next Cloudinary, especially in the app directory, it&#8217;s essential to mark the parent page or component as a Client Component. This ensures that our Cloudinary components run on the client side, where they can fully access the browser&#8217;s capabilities.<\/p>\n\n\n\n<p>To avoid marking an entire page as a Client Component, which might not always be desirable, we can create a simple wrapper. This wrapper acts as a Client Component, enveloping other components and allowing them to run client-side. Here&#8217;s how we set up our VideoPlayer component with these considerations in mind:<\/p>\n\n\n<pre class=\"wp-block-code\" 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-comment\">\/\/ This directive ensures our component is treated as a Client Component<\/span>\n<span class=\"hljs-string\">\"use client\"<\/span>;\n\n<span class=\"hljs-comment\">\/\/ Importing the CldVideoPlayer component from next-cloudinary<\/span>\n<span class=\"hljs-keyword\">import<\/span> { CldVideoPlayer } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next-cloudinary\"<\/span>;\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">VideoPlayer<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-comment\">\/\/ Rendering the Cloudinary video player with our desired dimensions and video source<\/span>\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\">className<\/span>=<span class=\"hljs-string\">\"absolute top-1\/2 left-1\/2 transform -translate-x-1\/2 -translate-y-1\/2 h-&#91;50vh] w-&#91;50vw]\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CldVideoPlayer<\/span>\n        <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"rounded-lg shadow-xl\"<\/span>\n        <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"1920\"<\/span>\n        <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"1080\"<\/span>\n        <span class=\"hljs-attr\">controls<\/span>\n        <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"samples\/sea-turtle\"<\/span>\n      \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n  );\n}\n\n<span class=\"hljs-comment\">\/\/ Exporting VideoPlayer for use across our application<\/span>\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> VideoPlayer;\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\n\n<p>With this simple component, we can display any video stored in our Cloudinary account by specifying the <code>src<\/code> attribute. We&#8217;re using a sample video for this demo, but feel free to replace <code>samples\/sea-turtle<\/code> with the path to your video in Cloudinary.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Integrating Analytics<\/strong><\/h3>\n\n\n\n<p>Cloudinary offers a straightforward solution to gather analytics on your video content with minimal effort. By simply adding <code>analytics<\/code> property to our <code>CldVideoPlayer<\/code> component, Cloudinary automatically begins to track various metrics associated with our videos. This feature is incredibly useful for obtaining a quick overview of video performance without complex integration.<\/p>\n\n\n\n<p>Here&#8217;s how to enable analytics within our VideoPlayer component:<\/p>\n\n\n<pre class=\"wp-block-code\" 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-string\">\"use client\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { CldVideoPlayer } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next-cloudinary\"<\/span>;\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">VideoPlayer<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\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\">className<\/span>=<span class=\"hljs-string\">\"absolute top-1\/2 left-1\/2 transform -translate-x-1\/2 -translate-y-1\/2 h-&#91;50vh] w-&#91;50vw]\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CldVideoPlayer<\/span>\n        <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"rounded-lg shadow-xl\"<\/span>\n        <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"1920\"<\/span>\n        <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"1080\"<\/span>\n        <span class=\"hljs-attr\">controls<\/span>\n        <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"samples\/sea-turtle\"<\/span>\n        <span class=\"hljs-attr\">analytics<\/span> \/\/ <span class=\"hljs-attr\">Enables<\/span> <span class=\"hljs-attr\">Cloudinary<\/span>'<span class=\"hljs-attr\">s<\/span> <span class=\"hljs-attr\">built-in<\/span> <span class=\"hljs-attr\">analytics<\/span>\n      \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n  );\n}\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> VideoPlayer;\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\n\n<p>By adding <code>analytics<\/code>, Cloudinary starts to collect and analyze data related to the video. You can access these insights directly within your Cloudinary dashboard, providing a convenient and straightforward way to monitor your video content&#8217;s performance.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1712623823\/Blog-Gathering_Analytics_for_Your_Videos_Uploaded_to_Cloudinary-1.png\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1712623823\/Blog-Gathering_Analytics_for_Your_Videos_Uploaded_to_Cloudinary-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Using PostHog<\/strong><\/h3>\n\n\n\n<p>While Cloudinary&#8217;s built-in analytics provide valuable insights into video performance, integrating PostHog into our app will offer a deeper dive into user interactions and behaviors.<\/p>\n\n\n\n<p>To kick off PostHog integration, we&#8217;ll start by setting up a dedicated provider to manage PostHog&#8217;s functionality across our app.<\/p>\n\n\n<pre class=\"wp-block-code\" 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-comment\">\/\/ Ensures the code runs client-side where PostHog can access browser features<\/span>\n<span class=\"hljs-string\">'use client'<\/span>;\n\n<span class=\"hljs-comment\">\/\/ Imports necessary PostHog functionalities<\/span>\n<span class=\"hljs-keyword\">import<\/span> posthog <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'posthog-js'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { PostHogProvider } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'posthog-js\/react'<\/span>;\n\n<span class=\"hljs-comment\">\/\/ Initializes PostHog only if running in a browser environment<\/span>\n<span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-keyword\">typeof<\/span> <span class=\"hljs-built_in\">window<\/span> !== <span class=\"hljs-string\">'undefined'<\/span>) {\n    posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY || <span class=\"hljs-string\">\"\"<\/span>, {\n        <span class=\"hljs-attr\">api_host<\/span>: process.env.NEXT_PUBLIC_POSTHOG_HOST,\n    });\n}\n\n<span class=\"hljs-comment\">\/\/ Defines a function that wraps children components with PostHogProvider<\/span>\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">CSPostHogProvider<\/span>(<span class=\"hljs-params\">{ children }: {children: React.ReactNode}<\/span>) <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">PostHogProvider<\/span> <span class=\"hljs-attr\">client<\/span>=<span class=\"hljs-string\">{posthog}<\/span> <span class=\"hljs-attr\">apiKey<\/span>=<span class=\"hljs-string\">{process.env.NEXT_PUBLIC_POSTHOG_KEY}<\/span>&gt;<\/span>\n            {children}\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">PostHogProvider<\/span>&gt;<\/span><\/span>\n    );\n}\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\n\n<p>Afterwards, import the <code>CSPostHogProvider<\/code> component in your <code>app\/layout.js<\/code> file and wrap your app with it.<\/p>\n\n\n<pre class=\"wp-block-code\" 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-comment\">\/\/ app\/layout.js<\/span>\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'.\/globals.css'<\/span>\n<span class=\"hljs-keyword\">import<\/span> { CSPostHogProvider } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'.\/providers'<\/span>\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">RootLayout<\/span>(<span class=\"hljs-params\">{ children }<\/span>) <\/span>{\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">html<\/span> <span class=\"hljs-attr\">lang<\/span>=<span class=\"hljs-string\">\"en\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CSPostHogProvider<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">body<\/span>&gt;<\/span>{children}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">CSPostHogProvider<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">html<\/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\n\n<p>With PostHog ready to go in our app, we can now add a layer of analytics to our VideoPlayer component. This step involves capturing key video interaction events like play, pause, and end, and sending this data to PostHog for insightful analysis.<\/p>\n\n\n\n<p>Let&#8217;s refine our VideoPlayer component to include PostHog event tracking:<\/p>\n\n\n<pre class=\"wp-block-code\" 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-string\">\"use client\"<\/span>;\n\n<span class=\"hljs-keyword\">import<\/span> { CldVideoPlayer } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next-cloudinary\"<\/span>;\n<span class=\"hljs-comment\">\/\/ Imports the PostHog library<\/span>\n<span class=\"hljs-keyword\">import<\/span> posthog <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"posthog-js\"<\/span>;\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">VideoPlayer<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n    &lt;div className=<span class=\"hljs-string\">\"absolute top-1\/2 left-1\/2 transform -translate-x-1\/2 -translate-y-1\/2 h-&#91;50vh] w-&#91;50vw]\"<\/span>&gt;\n      <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CldVideoPlayer<\/span>\n        <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"rounded-lg shadow-xl\"<\/span>\n        <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"1920\"<\/span>\n        <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"1080\"<\/span>\n        <span class=\"hljs-attr\">controls<\/span>\n        <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"samples\/sea-turtle\"<\/span>\n        <span class=\"hljs-attr\">analytics<\/span>\n        <span class=\"hljs-attr\">onPlay<\/span>=<span class=\"hljs-string\">{({<\/span> <span class=\"hljs-attr\">player<\/span> }) =&gt;<\/span> {\n          \/\/ Captures and sends a 'video played' event to PostHog when the video is played\n          posthog.capture(\"video played\", {\n            currentTime: player.currentTime(),\n          });\n        }}\n        onPause={({ player }) =&gt; {\n          \/\/ Captures and sends a 'video paused' event to PostHog when the video is paused\n          posthog.capture(\"video paused\", {\n            currentTime: player.currentTime(),\n          });\n        }}\n        onEnded={({ player }) =&gt; {\n          \/\/ Captures and sends a 'video ended' event to PostHog when the video finishes playing\n          posthog.capture(\"video ended\", {\n            currentTime: player.currentTime(),\n          });\n        }}\n      \/&gt;<\/span>\n    &lt;<span class=\"hljs-regexp\">\/div&gt;\n  );\n}\n\nexport default VideoPlayer;<\/span><\/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\n\n<p>In this updated component, we&#8217;ve added event handlers for the<strong> <\/strong><code>CldVideoPlayer's onPlay<\/code>, <code>onPause<\/code>, and <code>onEnded<\/code> events. Each handler captures the video&#8217;s current time when the event occurs and sends this information to <code>PostHog<\/code> using the<strong> <\/strong><code>posthog.capture<\/code> method. This allows us to track how users interact with our videos.&nbsp;<\/p>\n\n\n\n<p>Now, just pop over to our PostHog dashboard, set up a new insight, and watch our analytics work their magic!<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1712623823\/Blog-Gathering_Analytics_for_Your_Videos_Uploaded_to_Cloudinary-3.png\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1712623823\/Blog-Gathering_Analytics_for_Your_Videos_Uploaded_to_Cloudinary-4.png\" alt=\"\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Wrapping Up<\/strong><\/h2>\n\n\n\n<p>And there you have it! Getting a grip on how viewers interact with our videos is super important for making content that really connects. Every step, from getting everything set up to keeping an eye on how videos are played, has helped us get smarter about what our audience likes and doesn&#8217;t like.<\/p>\n\n\n\n<p>We&#8217;ve learned that turning on analytics in Cloudinary is a breeze, and sending that data over to tools like PostHog is just as easy. These insights are invaluable for refining content strategies and enhancing user experiences. Happy analyzing!<\/p>\n\n\n\n<p>If you found this blog post helpful and want to discuss it in more detail, head over to the <a href=\"https:\/\/community.cloudinary.com\/\">Cloudinary Community forum<\/a> and its associated <a href=\"https:\/\/discord.com\/invite\/cloudinary\">Discord<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Have you ever wondered how your videos are doing once you upload them to Cloudinary? Knowing who&#8217;s watching, from where, and how they engage with your videos can be super helpful. It&#8217;s like getting a sneak peek into your audience&#8217;s likes and dislikes, helping you make even cooler videos in the future.&nbsp; In this blog [&hellip;]<\/p>\n","protected":false},"author":87,"featured_media":33698,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[310],"class_list":["post-33610","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-video-player"],"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>Capturing Video Analytics With Cloudinary: A Next.js Guide<\/title>\n<meta name=\"description\" content=\"Gather analytics for your videos in a Next.js app. Integrate analytics &amp; track user interactions with your videos to enhance content strategy &amp; improve UX.\" \/>\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\/gathering-analytics-videos-uploaded-to-cloudinary\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Gathering Analytics for Your Videos Uploaded to Cloudinary\" \/>\n<meta property=\"og:description\" content=\"Gather analytics for your videos in a Next.js app. Integrate analytics &amp; track user interactions with your videos to enhance content strategy &amp; improve UX.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2024-05-02T14:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1713378687\/Analytics_video_upload_cloudinary-blog\/Analytics_video_upload_cloudinary-blog.jpg?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"2000\" \/>\n\t<meta property=\"og:image:height\" content=\"1100\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"melindapham\" \/>\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\/gathering-analytics-videos-uploaded-to-cloudinary#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary\"},\"author\":{\"name\":\"melindapham\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\"},\"headline\":\"Gathering Analytics for Your Videos Uploaded to Cloudinary\",\"datePublished\":\"2024-05-02T14:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary\"},\"wordCount\":1221,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1713378687\/Analytics_video_upload_cloudinary-blog\/Analytics_video_upload_cloudinary-blog.jpg?_i=AA\",\"keywords\":[\"Video Player\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2024\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary\",\"url\":\"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary\",\"name\":\"Capturing Video Analytics With Cloudinary: A Next.js Guide\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1713378687\/Analytics_video_upload_cloudinary-blog\/Analytics_video_upload_cloudinary-blog.jpg?_i=AA\",\"datePublished\":\"2024-05-02T14:00:00+00:00\",\"description\":\"Gather analytics for your videos in a Next.js app. Integrate analytics & track user interactions with your videos to enhance content strategy & improve UX.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1713378687\/Analytics_video_upload_cloudinary-blog\/Analytics_video_upload_cloudinary-blog.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1713378687\/Analytics_video_upload_cloudinary-blog\/Analytics_video_upload_cloudinary-blog.jpg?_i=AA\",\"width\":2000,\"height\":1100},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Gathering Analytics for Your Videos Uploaded to Cloudinary\"}]},{\"@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\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\",\"name\":\"melindapham\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"caption\":\"melindapham\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Capturing Video Analytics With Cloudinary: A Next.js Guide","description":"Gather analytics for your videos in a Next.js app. Integrate analytics & track user interactions with your videos to enhance content strategy & improve UX.","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\/gathering-analytics-videos-uploaded-to-cloudinary","og_locale":"en_US","og_type":"article","og_title":"Gathering Analytics for Your Videos Uploaded to Cloudinary","og_description":"Gather analytics for your videos in a Next.js app. Integrate analytics & track user interactions with your videos to enhance content strategy & improve UX.","og_url":"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary","og_site_name":"Cloudinary Blog","article_published_time":"2024-05-02T14:00:00+00:00","og_image":[{"width":2000,"height":1100,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1713378687\/Analytics_video_upload_cloudinary-blog\/Analytics_video_upload_cloudinary-blog.jpg?_i=AA","type":"image\/jpeg"}],"author":"melindapham","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary"},"author":{"name":"melindapham","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9"},"headline":"Gathering Analytics for Your Videos Uploaded to Cloudinary","datePublished":"2024-05-02T14:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary"},"wordCount":1221,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1713378687\/Analytics_video_upload_cloudinary-blog\/Analytics_video_upload_cloudinary-blog.jpg?_i=AA","keywords":["Video Player"],"inLanguage":"en-US","copyrightYear":"2024","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary","url":"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary","name":"Capturing Video Analytics With Cloudinary: A Next.js Guide","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1713378687\/Analytics_video_upload_cloudinary-blog\/Analytics_video_upload_cloudinary-blog.jpg?_i=AA","datePublished":"2024-05-02T14:00:00+00:00","description":"Gather analytics for your videos in a Next.js app. Integrate analytics & track user interactions with your videos to enhance content strategy & improve UX.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1713378687\/Analytics_video_upload_cloudinary-blog\/Analytics_video_upload_cloudinary-blog.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1713378687\/Analytics_video_upload_cloudinary-blog\/Analytics_video_upload_cloudinary-blog.jpg?_i=AA","width":2000,"height":1100},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/gathering-analytics-videos-uploaded-to-cloudinary#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Gathering Analytics for Your Videos Uploaded to Cloudinary"}]},{"@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":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9","name":"melindapham","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","caption":"melindapham"}}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1713378687\/Analytics_video_upload_cloudinary-blog\/Analytics_video_upload_cloudinary-blog.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/33610","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\/87"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=33610"}],"version-history":[{"count":3,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/33610\/revisions"}],"predecessor-version":[{"id":33700,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/33610\/revisions\/33700"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/33698"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=33610"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=33610"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=33610"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}