Is your investment in video generating ad revenue, decreasing support costs, or providing an engaging end-user experience overall?
Regardless of the vertical, you’re working in, it’s important to track video engagement as accurately and descriptively as possible. For a publisher, a technical support provider, or an educational destination that offers a multitude of video content, it’s critical for understanding the effectiveness of the content that you’re producing and posting.
This post outlines specialized techniques for achieving two objectives:
As our primary objective, we’ll reorient the usual milestone approach to video tracking and provide a more accurate assessment of view time. We’ll also take advantage of custom metrics so we’re tracking video play time not just as text-based events but as numeric data. This will allow us to calculate and display play time by video, session, and user. To achieve this, we’ll take advantage of the following Google Analytics features:
The APIs for most video players provide quite a rich taxonomy for us to read and then write to our analytics tool for additional reporting opportunities, as the second objective of our enhanced video tracking. The values that we’ll read from the API and write into Google Analytics as custom dimensions include:
In Google Analytics, video tracking is normally approached as “milestones”, meaning that you generate an event in Google Analytics when the video reaches a threshold expressed as percentage duration or time viewed.
While useful, the usual milestone approach has some fundamental limitations:
We’ll address all three of these limitations below:
This adjustment is easy: we’ll send events to Google Analytics at 10% intervals instead of 25%. In this way, we’ll get a little bit closer to heartbeat frequency without overwhelming Google Analytics with event hits.
Broadly speaking, there has been a historical struggle in Google Analytics to measure user interaction/engagement after the last hit that was sent.
Let’s see how this would apply to video tracking:
To approach this challenge, we’ll take advantage of the jQuery .unload() function and the new navigator.sendBeacon.
Use the .unload() function to trigger a Google Analytics event that carries the playtime in seconds for the video time watched right before the browser exit event.
The unload event is sent to the window element when the user navigates away from the page. This could mean that the user took any of the following actions:
navigator.sendBeacon Transport Mechanism for Google Analytics
By default, analytics.js picks the HTTP method and transport mechanism with which to optimally send hits. The three options are:
The navigator.sendBeacon method is a new HTML feature created that we can use to track hits that are sent if the page is being unloaded.
Note: .unload() and navigator.sendBeacon Not Supported on All Browsers
As another enhancement to the video time tracking, we’ll pass a custom metric for elapsed video play time with the following events:
Regarding a Google Analytics custom metric for video watch time – rather than just text-based Google Analytics threshold and interaction events – will provide much greater opportunities for reporting, including play time:
Below is a simple custom report displaying the Video Play Time custom metric for the video titles, which have been recorded as an event label.
For the custom report below, we display a calculated metrics (Avg. Play Time/Session) by traffic source.
Traffic sources with high play times/session might be good candidates for increased marketing efforts.
As one of the benefits of reading from the video API ourselves, we’ll be able to tag advantage of quite a detailed back-end taxonomy. Below is the list of video-specific variables (Data Layer Attributes) you can pass along when you send video events and then use in the Google Analytics UI.
Name | Description | Example | Type |
---|---|---|---|
video_name | The display name of the video | Everybody Loves Raymond S03 E09 | String |
show_name | The name of the show | Everybody Loves Raymond | String |
genres | The style of media: fantasy, romance, comedy, science fiction, mystery,… | Comedy | String |
media_type | The type of media this art applies to: movie, show, season, episode,… | Episode | String |
episode_no | The number of the episode | E01 | String |
season_no | The number of the season | S06 | String |
premium_content | Whether the video is guarded behind login | No | String |
tv_channel | The TV channel in which the show aired | CBS | String |
certificate | The rating of the show | TV-PG | String |
language | Language of the video | English | String |
release_year | The year in which the show was first aired | 1996 | String |
video_length | The total length (in seconds) of the video | 1,200 | Number |
play_time | The total play time (in seconds) of the video | 345 | Number |
Let’s just dive straight into a few examples of how the video tracker works. Note: While we aren’t going to share the details of the tracker in this post, it is important to know that we are using the video player’s built-in API and Event Listeners.
Imagine a user is watching the 9th episode in the 3rd season of Everybody Loves Raymond. During the 20-minute video, the user performed the following actions:
Our steps for capturing these actions (along with additional descriptors) as web analytics data will include:
Event | event=”video_play” |
Description | The video began playing (either via auto-play or user click) |
Play Time | 0 |
Sample | dataLayer.push({ ‘event’: ‘video_play’, ‘event_category’: ‘video’, ‘event_action’: ‘play’, ‘event_label’: ‘Everybody Loves Raymond S03 E09’, ‘event_value’: 0, ‘non_interaction’: 0, ‘video’: { ‘video_name’: ‘Everybody Loves Raymond S03 E09’, ‘show_name’: ‘Everybody Loves Raymond’, ‘genres’: ‘Comedy’, ‘media_type’: ‘Episode’, ‘episode_no’: ‘E01’, ‘season_no’: ‘S06’, ‘premium_content’: ‘No’, ‘tv_channel’: ‘CBS’, ‘certificate’: ‘TV-PG’, ‘language’: ‘English’, ‘release_year’: ‘1996’, ‘play_time’: ‘0’, ‘video_length’: ‘120’ }, }); |
Event | event=”video_pause” |
Description | The video playback changed to paused. |
Play Time | The time duration between the last milestone and the pause event, in seconds. |
Sample | dataLayer.push({ dataLayer.push({ ‘event’: ‘video_pause’, ‘event_category’: ‘video’, ‘event_action’: ‘pause’, ‘event_label’: ‘Everybody Loves Raymond S03 E09’, ‘event_value’: 0, ‘non_interaction’: 0, ‘video’: { ‘video_name’: ‘Everybody Loves Raymond S03 E09’, ‘show_name’: ‘Everybody Loves Raymond’, ‘genres’: ‘Comedy’, ‘media_type’: ‘Episode’, ‘episode_no’: ‘E01’, ‘season_no’: ‘S06’, ‘premium_content’: ‘No’, ‘tv_channel’: ‘CBS’, ‘certificate’: ‘TV-PG’, ‘language’: ‘English’, ‘release_year’: ‘1996’, ‘play_time’: ’10’, ‘video_length’: ‘600’, }, }); |
Hit | Event | Play Time |
---|---|---|
1 | Play | 0 seconds |
2,3 | Milestone | 60 seconds each |
4 | Pause | 10 seconds |
Event | event=”video_milestone” |
Description | The video playback reached a specific percentage milestone. |
Play Time | One-tenth of the video duration. Note: In the case of the “video seek”, Play Time is calculated based on the time between the new starting position and the next milestone. |
Sample | dataLayer.push({ ‘event’: ‘video_milestone’, ‘event_category’: ‘video’, ‘event_action’: ‘10% progress’, ‘event_label’: ‘Everybody Loves Raymond S03 E09’, ‘event_value’: 0, ‘non_interaction’: 0, ‘video’: { ‘video_name’: ‘Everybody Loves Raymond S03 E09’, ‘show_name’: ‘Everybody Loves Raymond’, ‘genres’: ‘Comedy’, ‘media_type’: ‘Episode’, ‘episode_no’: ‘E01’, ‘season_no’: ‘S06’, ‘premium_content’: ‘No’, ‘tv_channel’: ‘CBS’, ‘certificate’: ‘TV-PG’, ‘language’: ‘English’, ‘release_year’: ‘1996’, ‘play_time’: ’12’, ‘video_length’: ‘600’, }, }); |
Hit | Event | Play Time |
---|---|---|
1 | Play | 0 seconds |
2 – 11 | Milestone | 60 seconds each |
Event | event=”video_seek” |
Description | Video playback was advanced forward (not backward) to a new play position. |
Play Time | The time between the last milestone and the seek event. |
Sample | dataLayer.push({ ‘event’: ‘video_seek’, ‘event_category’: ‘video’, ‘event_action’: ‘seek’, ‘event_label’: ‘Everybody Loves Raymond S03 E09’, ‘event_value’: 0, ‘non_interaction’: 0, ‘video’: { ‘video_name’: ‘Everybody Loves Raymond S03 E09’, ‘show_name’: ‘Everybody Loves Raymond’, ‘genres’: ‘Comedy’, ‘media_type’: ‘Episode’, ‘episode_no’: ‘E01’, ‘season_no’: ‘S06’, ‘premium_content’: ‘No’, ‘tv_channel’: ‘CBS’, ‘certificate’: ‘TV-PG’, ‘language’: ‘English’, ‘release_year’: ‘1996’, ‘play_time’: ’30’, ‘video_length’: ‘600’, }, }); |
Hit | Event | Play Time |
---|---|---|
1 | Play | 0 seconds |
2, 3, 4, 5 | Milestone | 60 seconds each |
6 | Seek | 49 seconds |
7 | Milestone | 55 seconds each |
Event | event=”video_unload” |
Description | The user navigates away from the page by clicking on the forward or back buttons or closing the browser/tab. |
Play Time | The time duration between the last milestone and the unload event. |
Sample | dataLayer.push({ ‘event’: ‘video_unload’, ‘event_category’: ‘video’, ‘event_action’: ‘unload’, ‘event_label’: ‘Everybody Loves Raymond S03 E09’, ‘event_value’: 0, ‘non_interaction’: 0, ‘video’: { ‘video_name’: ‘Everybody Loves Raymond S03 E09’, ‘show_name’: ‘Everybody Loves Raymond’, ‘genres’: ‘Comedy’, ‘media_type’: ‘Episode’, ‘episode_no’: ‘E01’, ‘season_no’: ‘S06’, ‘premium_content’: ‘No’, ‘tv_channel’: ‘CBS’, ‘certificate’: ‘TV-PG’, ‘language’: ‘English’, ‘release_year’: ‘1996’, ‘play_time’: ’40’, ‘video_length’: ‘600’, }, }); |
Hit | Event | Play Time |
---|---|---|
1 | Play | 0 seconds |
2 | Unload | 40 seconds each |
Once you have your API listeners set up in GTM Custom Event tags, you’re ready to configure one or more Custom Event triggers and Google Analytics tags to record the events in Google Analytics.
You can use the JavaScript Video Duration property to retrieve the length of the played video, in seconds. This duration can be the basis of the Play Time custom metric.
var video_length = document.getElementById(“myVideo”).duration;
Event | Play Time (in seconds) | Example (Video Length = 2 mins) |
---|---|---|
Play | 0 | 0 |
Pause | The time duration between the last milestone and the pause event. | 7 sec |
10% progress | Video Length / 10 | 12 sec |
20% progress | Video Length / 10 | 12 sec |
30% progress | Video Length / 10 | 12 sec |
40% progress | Video Length / 10 | 12 sec |
50% progress | Video Length / 10 | 12 sec |
60% progress | Video Length / 10 | 12 sec |
70% progress | Video Length / 10 | 12 sec |
80% progress | Video Length / 10 | 12 sec |
90% progress | Video Length / 10 | 12 sec |
100% progress | Video Length / 10 | 12 sec |
Seek | The time between the last milestone and the seek event | 30 sec |
unload | The time duration between the last milestone and the unload event | 7 sec |
In addition to the enhanced time reporting that the increased tracking frequency and custom metrics will allow, we can also report against any of the custom dimensions.
With a few relatively straightforward implementation steps – more frequent intervals for video events, additional view time through unload, a custom metric for play time, and an assortment of custom dimensions – we have achieved more accurate tracking of user engagement with video and much more flexible and descriptive reporting, which will provide better inputs for your marketing focus and content strategy.
Allaedin Ezzedin is a Senior Director at Merkle | Cardinal Path, renowned for his dedication to melding business strategies with technological innovation, particularly in the realm of digital marketing optimization. With an unwavering commitment to enhancing the digital analytics landscape, Allaedin is at the forefront of advocating for Google Analytics as a pivotal enterprise analytics solution.
As consumers become increasingly digitally savvy, and more and more brand touchpoints take place online,…
Marketers are on a constant journey to optimize the efficiency of paid search advertising. In…
Unassigned traffic in Google Analytics 4 (GA4) can be frustrating for data analysts to deal…
This website uses cookies.