• Skip to primary navigation
  • Skip to content
  • Skip to primary sidebar
VdoCipher: Secure Video Hosting for BusinessVdoCipher
☰
Sign Up
  • Solutions
    • E-learning
    • Enterprise
    • Developer
    • Media & Ott
    • Wordpress
    • Live Streaming
  • Features
  • Pricing
    • Video Hosting & DRM Solution
    • Live Streaming Solution
  • Live
  • Developer
  • About
    • Testimonials
    • The Company
  • Contact
Login
Sign Up

Build your Self Video Analytics Dashboard: Web, HTML5 & Embedded Video Analytics Metrics

October 29, 2025 /

Explore Advanced Video Analytics

Many businesses want to track how viewers engage with their videos – from how many times a video is played to where viewers are watching from. While professional platforms like VdoCipher offer advanced analytics out-of-the-box, it’s also possible to build a basic video analytics dashboard on your own.

In this guide you’ll:

  • Collect the core metrics most teams care about (view event, device/browser/OS, geography, watch completion, basic QoE signals).
  • Render the collected rows as JSON on the page (simple and copy-paste friendly).
  • (Optional) Export that JSON or pipe it into Google Sheets later for charts/pivots & make your own Video Analytics Dashboard.

Key Video Metrics to Track (and why they matter)

  • Device / OS / Browser
    Shows where your audience really lives (mobile vs desktop, OS/browser splits). Use this to prioritize testing and UI decisions.
  • Geographic Distribution (country)
    Helps with localization (subtitles/languages), and can surface unexpected markets.
  • Watch Completion / Average Watch %
    Measures how much of a video is typically consumed. Low percentages often point to content or onboarding issues; high percentages suggest strong engagement.
  • Page URL – The page on which video is being watched.
  • Video Duration – Total length of video.
  • Time to Start (ms) (QoE): time between the first play() and the first playing frame—good “startup delay” proxy.
  • Errors (QoE): surface MediaError codes to quickly debug real viewer failures.

Step 1 – Add a native HTML5 video

Use the stock <video> element with a self-hosted MP4 (or HLS/DASH with a JS loader if needed). Controls are on to keep things simple. This section defines the HTML structure – the <video> tag for playback, a button to trigger analytics export, and a <pre> block to show the resulting JSON.

Think of this as the “canvas” for all analytics code to act upon.

<video id="myVideo" width="640" height="360" controls>

<source src="https://www.vdocipher.com/blog/wp-content/uploads/2024/02/livestream-start.mp4" type="video/mp4">

Your browser does not support HTML5 video.

</video>

<button id="publishJson" style="margin-top:12px;">Publish Analytics JSON</button>

<pre id="analyticsJson" style="display:none;padding:10px;background:#f6f8fa;border-radius:8px;max-width:900px;overflow:auto;"></pre>

Step 2 – Start JS & Wrap everything in DOMContentLoaded including Config + tiny utils

This ensures that your script only runs after the DOM is fully loaded. By wrapping everything in a DOMContentLoaded listener, you guarantee that your script won’t fail because the <video> element hasn’t yet been rendered. Ensure, the script to be loaded

The basic utility functions are set up:

  • VIDEO_ID uniquely identifies the video (useful for tracking multiple videos).
  • analyticsRows is an array to store one JSON entry per session.
  • uid() generates a unique session identifier using browser cryptography — ensuring every view is unique.
<script>

document.addEventListener('DOMContentLoaded', () => {

const video = document.getElementById('myVideo');
const publishBtn = document.getElementById('publishJson');
const out = document.getElementById('analyticsJson');
const VIDEO_ID = 'livestream-start';
const analyticsRows = [];
const now = () => performance.now();

function uid() {
return ([1e7]+-1e3+-4e3+-8e3+-1e11)
.replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}

// Place the remaining sections **inside** this callback, in the same order.

});

</script>

Step 3 – Device, OS, and Browser detection

This section parses navigator.userAgent to detect:

  • Device type — mobile or desktop
  • Operating system — Windows, macOS, Android, etc.
  • Browser — Chrome, Firefox, Safari, Edge, etc.
    This information helps in understanding playback performance across user environments.
function getDeviceInfo() {

const ua = navigator.userAgent;
const device = /Mobi|Android|iPhone|iPad|Tablet/i.test(ua) ? 'Mobile' : 'Desktop';

let os = 'Unknown OS';

if (ua.includes('Windows')) os = 'Windows';
else if (ua.includes('Mac')) os = 'macOS';
else if (ua.includes('Android')) os = 'Android';
else if (/iPhone|iPad|iPod/.test(ua)) os = 'iOS';
else if (ua.includes('Linux') || ua.includes('X11')) os = 'Linux/Unix';

let browser = 'Unknown Browser';

if (ua.includes('Chrome') && !ua.includes('Edg/')) browser = 'Chrome';
else if (ua.includes('Edg/')) browser = 'Edge';
else if (ua.includes('Firefox')) browser = 'Firefox';
else if (ua.includes('Safari') && !ua.includes('Chrome')) browser = 'Safari';
else if (ua.includes('OPR') || ua.includes('Opera')) browser = 'Opera';
else if (ua.includes('Trident') || ua.includes('MSIE')) browser = 'Internet Explorer';

return { device, os, browser };

}

Step 4 – Country lookup via IP (minimal geo)

The code uses the free ipapi.co service to fetch the viewer’s country and country code from their IP address.

It runs asynchronously, filling in the geo fields for each analytics entry. This helps you map your audience distribution geographically.

function getGeoLocation() {

return fetch('https://ipapi.co/json/')

.then(r => r.json())

.then(d => ({

country: d && d.country_name ? d.country_name : 'Unknown',

countryCode: d && d.country_code ? d.country_code : ''

}))

.catch(() => ({ country: 'Unknown', countryCode: '' }));

}

Step 5 – Session initialization

Here, all analytics fields are initialized — creating a “session object” that represents one playback event.
It includes general metadata (timestamp, video ID, URL) and playback variables like:

  • watchPercent
  • errors
    Initially, many of these are blank and get populated as playback continues.
const session = {

timestamp: new Date().toISOString(),
sessionId: uid(),
videoId: VIDEO_ID,
pageUrl: location.href,

// engagement core

event: 'init',
completed: false,
maxTimeWatched: 0,
watchPercent: 0,
duration: null,

// device

...getDeviceInfo(),

// geo (filled async below)

country: 'Unknown',
countryCode: '',

// QoE basics kept

timeToStartMs: null,

// errors encountered

errors: []

};

// fill geo asynchronously

getGeoLocation().then(loc => {
session.country = loc.country;
session.countryCode = loc.countryCode;

});

Step 6 – Duration

Triggered by the loadedmetadata event, this section captures:

  • Total video duration

This marks the baseline video state before the user starts interacting with it.

video.addEventListener('loadedmetadata', () => {

session.duration = Math.round(video.duration || 0);

});

Step 7 – Counting a View + Measuring Startup Time

The play and playing events together record:

  • When the first “play” action occurred
  • How long it took for the first frame to appear (timeToStartMs)
    This startup delay metric reflects how quickly the video begins after user intent — critical for measuring QoE (Quality of Experience).
let firstPlayT0 = null;

video.addEventListener('play', () => {

if (session.event !== 'view') session.event = 'view';

if (firstPlayT0 === null) firstPlayT0 = now();

});

video.addEventListener('playing', () => {

if (session.timeToStartMs === null && firstPlayT0 !== null) {

session.timeToStartMs = Math.max(0, Math.round(now() - firstPlayT0));

}

});

Step 8 – Watch Progress (Max Time Watched)

The timeupdate listener continually records the furthest timestamp watched.
This enables the calculation of watch percentage, showing how much of the video the viewer actually watched before leaving.

video.addEventListener('timeupdate', () => {

if (video.currentTime > session.maxTimeWatched) {

session.maxTimeWatched = video.currentTime;

}

});

Step 9 – Completion Tracking

When the ended event fires, the session marks completed = true.
This lets you differentiate partial plays from full completions in your dataset.

video.addEventListener('ended', () => {

session.completed = true;

});

Step 10 – Error Logging

Captures playback errors using the HTML5 video.error object.
Each error is tagged with a code and a friendly name (e.g., MEDIA_ERR_DECODE).
This helps debug whether failures are due to network issues, unsupported formats, or decoding problems.

const MEDIA_ERROR_NAMES = {

1: 'MEDIA_ERR_ABORTED',

2: 'MEDIA_ERR_NETWORK',

3: 'MEDIA_ERR_DECODE',

4: 'MEDIA_ERR_SRC_NOT_SUPPORTED'

};

video.addEventListener('error', () => {

const err = video.error;

if (err && err.code) {

session.errors.push({ code: err.code, name: MEDIA_ERROR_NAMES[err.code] || 'UNKNOWN' });

} else {

session.errors.push({ code: 0, name: 'UNKNOWN' });

}

});

Step 11 – Finalizing the Session

When the viewer leaves or reloads the page, this block:

  • Calculates the watchPercent (based on duration and max time watched)
  • Pushes the finalized session data into the analyticsRows array
    Essentially, it freezes the current session snapshot into a structured record.
let stored = false;

function finalizeSessionAndStore() {

if (stored) return;

stored = true;

// compute watch %

const dur = video.duration || session.duration || 0;

const pct = dur ? Math.min(100, Math.floor((session.maxTimeWatched / dur) * 100)) : 0;

session.watchPercent = pct;

// push the row

analyticsRows.push({

timestamp: session.timestamp,
sessionId: session.sessionId,
videoId: session.videoId,
pageUrl: session.pageUrl,
event: session.event,
completed: session.completed,
watchPercent: session.watchPercent,
durationSec: video.duration,
timeToStartMs: session.timeToStartMs,
device: session.device,
os: session.os,
browser: session.browser,
country: session.country,
countryCode: session.countryCode,
errors: session.errors.map(e => `${e.name}(${e.code})`).join('|')

});

}

Step 12 – Exit Detection and Publishing JSON

The script ensures data isn’t lost:

  • It listens for pagehide, beforeunload, and visibilitychange events to call finalizeSessionAndStore() before leaving.
  • When the user clicks “Publish Analytics JSON”, it displays the analytics array as formatted JSON in the <pre>block.
    This allows anyone to instantly view the full analytics dataset on the page — no servers or APIs needed.
window.addEventListener('pagehide', finalizeSessionAndStore);

window.addEventListener('beforeunload', finalizeSessionAndStore);

document.addEventListener('visibilitychange', () => {

if (document.visibilityState === 'hidden') finalizeSessionAndStore();

});

Step 13 – Publish JSON on the page (button → pretty JSON)

if (publishBtn && out) {
publishBtn.addEventListener('click', () => {
finalizeSessionAndStore();
out.style.display = "block";
out.textContent = JSON.stringify(analyticsRows, null, 2);
});
} else {
console.warn('Missing #publishJson button or #analyticsJson output node.');
}

Example JSON row (what readers should expect)

[{

"timestamp": "2025-10-27T10:50:42.747Z",
"sessionId": "3d99ad46-a0d3-4dab-825b-a7b339b92c13",
"videoId": "livestream-start",
"pageUrl": "https://www.vdocipher.com/blog/?page_id=20104&preview=true",
"event": "view",
"completed": false,
"watchPercent": 85,
"durationSec": 7.36,
"timeToStartMs": 0,
"device": "Desktop",
"os": "macOS",
"browser": "Chrome",
"country": "India",
"countryCode": "IN",
"errors": ""

}]

Optional – JSON to Google Sheet Dashboard

  • Upload to Sheets using Extensions → Apps Script with a small script that parses JSON and inserts rows, or simply convert JSON → CSV online and import.
  • After sending our data to a Google Sheet, we can later open the sheet to view and pivot the data (or even use Google’s chart features to visualize it). You can make a separate “Dashboard” sheet within the Google Sheet that references these metrics. For example, use formulas to pull average watch % and so on for each video, and present them in a summary table. Use charts (pie charts for device or browser share, bar chart for top countries, line chart over time if you add dates, etc.) to visualize the data. Google Sheets makes it fairly easy to create these once the data is there.

Supercharge Your Business with Videos

At VdoCipher we maintain the strongest content protection for videos. We also deliver the best viewer experience with brand friendly customisations. We'd love to hear from you, and help boost your video streaming business.

Free 30-day trial →
Decorative Circle
Vishal Sharma

My expertise focuses on DRM encryption, CDN technologies, and streamlining marketing campaigns to drive engagement and growth. At VdoCipher, I’ve significantly enhanced digital experiences and contributed to in-depth technical discussions in the eLearning, Media, and Security sectors, showcasing a commitment to innovation and excellence in the digital landscape.

Filed Under: Video Analytics Video Tech Tagged With: video analytics

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

Secure Your Videos

Blog Categories

  • DRM 
  • APIs and Sample Codes
  • WordPress
  • E-learning
  • Media
  • Video Tech

Popular Posts

  • Google Widevine DRM
  • WordPress video plugin
  • Video Quality
  • Dynamic Watermarking
  • Encrypted Video Streaming
  • Video Hosting For Online Courses
  • Online Video Player
  • Apple Fairplay DRM
  • SVOD VS TVOD VS AVOD
  • Exoplayer
  • DRM

Top Recent Posts

  • Enterprise Video Platform
  • Cloud Video Platform
  • Video Player for Android
  • DRM Solution
  • Video Bitrate
  • React Native Video
  • Video Piracy
  • Learning Management System
  • AVPlayer
  • Live Streaming Websites
  • DRM Providers
  • DRM Security
  • Private Video Hosting
  • HTML5 Video Player

Schedule Demo Link
Popular Blogs
  • How many use easy video download piracy tools ?
  • Apple FairPlay DRM : Video Protection on iOS & Safari
  • 12 Video Piracy Statistics, 6 Prevention Methods
  • Elearning Video Protection from Piracy
  • Content Creator Economy Growth and other Statistics Report
  • Top 21 Education Apps In India For Online Learning
  • How To Embed Videos in WordPress A Comprehensive Guide
  • Live Streaming Platform For E-learning Media & Broadcast
  • Explained in Simple Language, 32 Key DRM Encryption Terminologies
  • Best Video Player for Android Comparison 2024
Recent Blogs
  • Build your Self Video Analytics Dashboard: Web, HTML5 & Embedded Video Analytics Metrics
  • Hotstar Tech Stack Explained – Architecture and Delivery at Scale
  • 15 Best WordPress Video Player Plugins of 2025
  • Top 12 YouTube Alternatives and Online Video Platforms Like YouTube (2025)
  • Netflix Similar Apps – Top Netflix Alternatives in 2025
  • White Label Streaming Platform Explained
  • Netflix Tech Stack Explained: CDN (Open Connect), and Microservices
  • Security Checklist to Build a Secure Streaming App
Featured Blogs
  • Online Video Player
  • Video Encryption
  • Video Protection
  • Video Hosting
  • Widevine DRM
  • Fairplay DRM
  • Video Quality
  • Online Video Platform
  • Video hosting for business
Comparison
  • VdoCipher vs Vimeo
  • VdoCipher vs Dacast
  • VdoCipher vs YouTube
  • VdoCipher vs Zoom
  • VdoCipher vs JW Player
  • VdoCipher vs Dacast Live
  • VdoCipher vs Kaltura
  • VdoCipher vs Brightcove
    Contact Us
  • Phone : +91 7619171878
  • Whatsapp : +91 7042238654
  • E-mail : support@vdocipher.com
Company
  • Home
  • Glossary
  • Features
  • About Us
  • Pricing
  • FAQs
  • Contact
Services
  • Enterprise
  • E-Learning
  • Developer
  • Healthcare
  • Live Streaming Platform
  • Video Analytics
  • Media and Entertainment
  • DRM and Antipiracy
  • APIs for Developers
  • Video Hosting
  • Video API
  • Video DRM
  • Google DRM
  • DRM License Server
  • Custom Video Player
  • Play Integrity
Countries Served
  • Secure Video Hosting in USA
  • Secure Video Hosting in India
  • Secure Video Player in Brazil
  • Secure Video Streaming in UK
  • Secure Video Streaming in Saudi Arabia
  • Video Encryption in Spain
  • Video Encryption in Italy
  • Protected Video Streaming in Indonesia
  • Encrypted Video Player in Canada
  • Protected Video Streaming in Australia
  • Encrypted Video Player in Germany
  • Video DRM for Sri Lanka
  • Video DRM for Middle East
  • DRM Encryption for Europe
  • DRM Encryption for Asia
  • DRM Solutions for Japan
  • DRM Solutions for UAE
  • DRM Software for Chile
  • DRM Software for Russia

Copyright © 2025 VdoCipher. All rights reserved.

  • Terms
  • Privacy Policy