How to Track Video Engagement in GTM (YouTube, Vimeo, HTML5)
TL;DR: GTM has a built-in YouTube Video trigger that captures start, progress, pause, seek, and complete events with zero code. For Vimeo and HTML5 <video> elements, use a Custom HTML tag to load the appropriate player API, listen for playback events, and push them to the dataLayer. Create GA4 Event tags for each video source, register custom dimensions like video_title and video_percent, and analyze engagement in GA4 Explore reports.
Video is everywhere — product demos, tutorials, testimonials, background hero loops. But embedding a video is only half the story. Without engagement tracking, you have no idea whether visitors actually watch your content or scroll right past it.
Google Tag Manager supports video tracking for YouTube out of the box. Vimeo and native HTML5 players require a bit more setup, but no changes to your site code. This guide covers all three, from trigger configuration to GA4 reporting.
Does GA4 track YouTube videos automatically?
GA4's Enhanced Measurement includes basic video tracking for embedded YouTube videos. When enabled, GA4 automatically collects video_start, video_progress, and video_complete events. However, there are significant limitations:
- Only YouTube. Vimeo, Wistia, HTML5
<video>, and other players are ignored entirely. - Limited progress thresholds. Enhanced Measurement only fires at 10%, 25%, 50%, and 75%. You cannot customize these milestones.
- No pause or seek events. You cannot measure how often users pause or scrub through your videos.
- No custom parameters. You cannot attach additional metadata like video category, page section, or campaign context.
For meaningful video analytics, you need GTM triggers with custom GA4 tags. This gives you full control over which events fire, what parameters are captured, and how data appears in reports.
How do I set up YouTube video tracking in GTM?
GTM includes a dedicated YouTube Video trigger type. No custom code needed.
- Go to Triggers → New → YouTube Video.
- Select capture events:
- Start — fires when the video begins playing
- Complete — fires when the video reaches the end
- Pause — fires when the user pauses playback
- Seeking — fires when the user scrubs the timeline
- Progress — fires at percentage thresholds (e.g., 25, 50, 75)
- For Progress, set your percentages: Enter
25, 50, 75, 100in the Percentages field. You can also use time-based thresholds (e.g., every 30 seconds) for longer videos. - Check "Add JavaScript API support." This is critical. GTM needs the YouTube IFrame API to communicate with the player. This option injects the
enablejsapi=1parameter automatically. - Set the trigger to fire on All Videos or limit it to specific pages using Page Path conditions.
Important: The "Add JavaScript API support" option works only for iframes loaded after GTM initializes. If your YouTube embeds load dynamically (e.g., via lazy loading or SPA navigation), you may need to ensure the API parameter is included in the iframe src attribute directly.
What YouTube video events can GTM capture?
When the YouTube Video trigger fires, GTM populates several built-in variables automatically. Enable them under Variables → Configure → Videos:
| Variable | Description | Example Value |
|---|---|---|
{{Video Title}} | Title of the YouTube video | Product Demo 2026 |
{{Video URL}} | YouTube URL of the video | https://www.youtube.com/watch?v=abc123 |
{{Video Status}} | Current trigger action | start, pause, progress, complete |
{{Video Percent}} | Percentage of video watched | 25, 50, 75, 100 |
{{Video Duration}} | Total video length in seconds | 185 |
{{Video Current Time}} | Current playback position in seconds | 46 |
{{Video Visible}} | Whether the video is in the viewport | true / false |
{{Video Provider}} | Video platform | youtube |
These variables are essential for your GA4 Event tag parameters. They let you answer questions like "Which videos do people actually finish?" and "At what point do viewers drop off?"
How do I create a GA4 tag for YouTube video events?
With the trigger and variables ready, create the GA4 Event tag:
- Tag Type: Google Analytics: GA4 Event
- Measurement ID: Your
G-XXXXXXXXXX - Event Name:
video_engagement(or use GA4's recommendedvideo_start/video_completenames if you only track those two actions) - Event Parameters:
video_title→{{Video Title}}video_status→{{Video Status}}video_percent→{{Video Percent}}video_duration→{{Video Duration}}video_url→{{Video URL}}video_provider→youtubepage_location→{{Page URL}}
- Triggering: Your YouTube Video trigger
Why one event name with a status parameter? Using a single video_engagement event with a video_status parameter (start, pause, progress, complete) conserves your 500 event name limit. You can still filter by status in GA4 Explore reports. Alternatively, if you only care about start and complete, use GA4's recommended event names for built-in report integration.
How do I track Vimeo videos in GTM?
Vimeo does not have a built-in GTM trigger. You need a Custom HTML tag that loads the Vimeo Player SDK and pushes events to the dataLayer.
- Create a Custom HTML tag in GTM with this script:
<script src="https://player.vimeo.com/api/player.js"></script>
<script>
(function() {
var iframes = document.querySelectorAll('iframe[src*="vimeo.com"]');
var milestones = [25, 50, 75, 100];
iframes.forEach(function(iframe) {
var player = new Vimeo.Player(iframe);
var title = '';
var duration = 0;
var reached = {};
player.getVideoTitle().then(function(t) { title = t; });
player.getDuration().then(function(d) { duration = d; });
player.on('play', function() {
window.dataLayer.push({
event: 'vimeo_video',
video_status: 'start',
video_title: title,
video_provider: 'vimeo'
});
});
player.on('pause', function() {
window.dataLayer.push({
event: 'vimeo_video',
video_status: 'pause',
video_title: title,
video_provider: 'vimeo'
});
});
player.on('ended', function() {
window.dataLayer.push({
event: 'vimeo_video',
video_status: 'complete',
video_title: title,
video_percent: 100,
video_provider: 'vimeo'
});
});
player.on('timeupdate', function(data) {
var pct = Math.floor((data.seconds / duration) * 100);
milestones.forEach(function(m) {
if (pct >= m && !reached[m]) {
reached[m] = true;
window.dataLayer.push({
event: 'vimeo_video',
video_status: 'progress',
video_title: title,
video_percent: m,
video_duration: Math.round(duration),
video_provider: 'vimeo'
});
}
});
});
});
})();
</script>
- Fire this tag on All Pages (or only pages with Vimeo embeds using a Page Path condition).
- Create a Custom Event trigger with Event Name equal to
vimeo_video. - Create a GA4 Event tag identical to the YouTube tag structure, but triggered by the
vimeo_videoCustom Event. Use Data Layer Variables to capturevideo_title,video_status,video_percent, andvideo_provider.
Note: Vimeo embeds must include the parameter ?api=1 in the iframe src for the Player SDK to communicate. Most modern Vimeo embeds include this by default.
How do I track HTML5 video elements in GTM?
For native <video> elements (self-hosted MP4s, WebM files, or custom players), use the browser's built-in Media Events API via a Custom HTML tag.
<script>
(function() {
var videos = document.querySelectorAll('video');
var milestones = [25, 50, 75, 100];
videos.forEach(function(video) {
var reached = {};
var title = video.getAttribute('title')
|| video.getAttribute('data-title')
|| video.currentSrc.split('/').pop();
video.addEventListener('play', function() {
window.dataLayer.push({
event: 'html5_video',
video_status: 'start',
video_title: title,
video_provider: 'html5'
});
});
video.addEventListener('pause', function() {
if (!video.ended) {
window.dataLayer.push({
event: 'html5_video',
video_status: 'pause',
video_title: title,
video_provider: 'html5'
});
}
});
video.addEventListener('ended', function() {
window.dataLayer.push({
event: 'html5_video',
video_status: 'complete',
video_title: title,
video_percent: 100,
video_provider: 'html5'
});
});
video.addEventListener('timeupdate', function() {
if (video.duration) {
var pct = Math.floor((video.currentTime / video.duration) * 100);
milestones.forEach(function(m) {
if (pct >= m && !reached[m]) {
reached[m] = true;
window.dataLayer.push({
event: 'html5_video',
video_status: 'progress',
video_title: title,
video_percent: m,
video_duration: Math.round(video.duration),
video_provider: 'html5'
});
}
});
}
});
});
})();
</script>
Then create a Custom Event trigger (html5_video) and a GA4 Event tag just like the Vimeo setup. The dataLayer structure is intentionally consistent across all three video sources, so you can even use a single GA4 Event tag triggered by all three event names if you prefer unified reporting.
How do I track video engagement milestones (25%, 50%, 75%, 100%)?
Milestone tracking answers the most important video question: where do viewers drop off?
For YouTube, milestone tracking is built into the trigger. Set the Progress percentages to 25, 50, 75, 100 and the trigger fires at each threshold automatically.
For Vimeo and HTML5, the milestone logic lives inside the timeupdate listener (shown in the code examples above). The key pattern:
- Track which milestones have been reached using an object (
reached = {}) per video instance. This prevents duplicate events when the user scrubs back and forth. - Calculate the current percentage from
currentTime / duration * 100. - Push a dataLayer event only when a new milestone is crossed. Once
reached[25]is set totrue, the 25% event never fires again for that video instance.
Choosing your milestones. The standard 25/50/75/100 works for most cases. For long-form content (30+ minutes), consider adding 10% intervals or time-based milestones (every 60 seconds). For short videos under 30 seconds, 50% and 100% may be sufficient — firing four events for a 15-second clip generates noise without insight.
How do I analyze video data in GA4?
Once video events flow into GA4, register your custom dimensions first:
- Go to Admin → Custom definitions → Create custom dimension
- Register:
video_title,video_status,video_percent,video_provider,video_duration - Set scope to "Event" for all of them
Then build Explore reports to answer key questions:
Which videos get the most engagement? Create a Free-form report with video_title as a dimension and Event count as a metric. Filter to video_status = complete to see completion rates. Add Total users to compare engagement across audience sizes.
Where do viewers drop off? Use video_title and video_percent as dimensions. For each video, compare the event count at 25%, 50%, 75%, and 100%. A steep drop between 25% and 50% signals that the first quarter of your video hooks viewers, but the middle content loses them.
Does video engagement correlate with conversions? Create a segment of users who reached video_percent = 75 or higher, then compare their conversion rate against users who never triggered a video event. This justifies investment in video content with hard numbers.
What are common video tracking mistakes?
- Forgetting "Add JavaScript API support" for YouTube. Without this, GTM cannot communicate with the YouTube player and no events will fire. This is the most common issue when YouTube tracking "doesn't work."
- Duplicate events from autoplay. If your video autoplays, the
startevent fires on every page load. Filter autoplay starts in your reports or add a condition to check whether the play was user-initiated. - Not handling lazy-loaded videos. If videos load dynamically (infinite scroll, tab switches, SPA navigation), the initial script may not find them. Use a MutationObserver or re-run the listener script when new video elements appear.
- Scrub-back inflating progress events. Without the
reacheddeduplication object, a user scrubbing from 80% back to 20% and forward again would trigger 25%, 50%, and 75% events a second time. - Tracking background/muted videos. Hero background videos that autoplay muted are not real engagement. Use the
{{Video Visible}}variable (YouTube) or checkvideo.muted(HTML5) to exclude them. - Not registering custom dimensions in GA4. Your events reach GA4, but without registered dimensions, you cannot break down data by video title or provider in reports.
Is there a faster way to set up video tracking?
The manual setup involves creating Custom HTML tags, Data Layer Variables, Custom Event triggers, and GA4 Event tags — for each video platform separately. GTM Event Helper simplifies this:
- Click on a video element on your page
- The extension detects the video type (YouTube, Vimeo, or HTML5) automatically
- The AI Agent suggests the appropriate tracking setup with correct event names and parameters
- Click "Create in GTM" to generate all the necessary tags, triggers, and variables via the GTM API
No Custom HTML scripts to paste. No Data Layer Variable configuration. No switching between your site, GTM, and GA4 documentation to get the parameter names right.
Track video engagement across YouTube, Vimeo, and HTML5 — without custom code.
Install GTM Event HelperExternal Resources
- GTM: YouTube Video trigger
- Vimeo Player SDK documentation
- MDN: HTMLMediaElement API
- GA4: Enhanced Measurement events