YouTube video tracking in GA4 works two ways. Enhanced measurement sends video_start, video_progress (at 10%, 25%, 50% and 75%) and video_complete for embedded YouTube players that have the JavaScript API enabled. Google Tag Manager's YouTube Video trigger gives you the same signals with your own thresholds, your own event names and a fix for embeds that don't have the API switched on.
If your videos sit in a plain iframe that loads with the page, enhanced measurement might be all you need. If they load late, sit behind a cookie banner, or hide behind a click-to-play thumbnail, it will quietly report nothing. And "nothing" looks exactly like "nobody watched".
- Enhanced measurement only tracks YouTube embeds with JS API support, which means
enablejsapi=1in the iframe URL. Page builders don't add it by default. - The GTM YouTube Video trigger can add the API parameter for you. It only works if a YouTube video or the IFrame API script is on the page when GTM loads.
- Click-to-play facades and CMP placeholders create the iframe later. That's where both methods lose plays.
video_startandvideo_progressare reserved GA4 event names. Pick your own names in GTM, and switch off the enhanced measurement toggle so you don't count twice.youtube-nocookie.comreduces cookies before playback. It doesn't make the embed consent-free.
What GA4 tracks by itself
Enhanced measurement lives in Admin > Data streams > your web stream > Enhanced measurement. The Video engagement toggle sends three events:
video_startwhen playback beginsvideo_progresswhen the video passes 10%, 25%, 50% and 75% of its durationvideo_completewhen it ends
Each one carries video_current_time, video_duration, video_percent, video_provider, video_title, video_url and visible. Video provider, Video title and Video URL show up as ready-made dimensions in GA4. The rest need custom definitions, more on that below.
The catch is one line in Google's documentation: these events fire "for YouTube embedded videos that have JS API support enabled". In plain terms, the iframe src needs enablejsapi=1.
A standard copy-paste embed from YouTube's Share > Embed menu doesn't include it. WordPress oEmbed doesn't add it. Most page builders don't either.
So the default case on a typical site is this: toggle on, tracking off.
Enhanced measurement vs the GTM YouTube Video trigger
| Enhanced measurement | GTM YouTube Video trigger | |
|---|---|---|
| Setup | One toggle | Trigger + tag, 30-45 minutes |
Needs enablejsapi=1 |
Yes, you add it yourself | Can add it for you (checkbox) |
| Progress points | Fixed: 10, 25, 50, 75% | Your choice: percentages or seconds |
| Pause, seek, buffering | No | Yes, optional |
| Event names | video_start, video_progress, video_complete |
Your own, like yt_start |
| Videos added after page load | Unreliable | Works if a video or the IFrame API is present at GTM load |
| Filter which videos | No | Yes, Some Videos with conditions |
| Change history | None | Container versions |
My take: for a blog with two embedded talks, the toggle plus enablejsapi=1 is fine. For a course platform, a product page with demo videos, or anything where a view counts as a lead signal, I build it in GTM.
Why the numbers vanished: a story about a facade
Ola runs marketing for a language school in Gdańsk. Her course landing pages each have a 90-second preview video, 18 pages in total.
Last spring the site moved to a new theme, and GA4 video_start events dropped from about 600 a month to zero. The team assumed the new videos were worse. They spent two weeks reshooting one of them.
YouTube Studio told a different story. The playback location report (embedded in external websites) showed roughly 2,300 views over the same three months, flat.
The new theme used a click-to-play facade, a static thumbnail with a play button. No iframe exists until someone clicks.
When they do, the theme injects an iframe with autoplay=1 and no enablejsapi. Enhanced measurement never had a player to talk to. The GTM trigger wouldn't have helped either, because no video and no IFrame API script were on the page when GTM loaded.
The fix took an hour. I switched off the theme's "load video on click" option, so the pages use a normal iframe with loading="lazy", and ticked the API checkbox in the GTM trigger.
Her CMP already reloads the page after consent, so the iframe is there when GTM loads. She gave up a bit of page speed on those 18 pages. For her, worth it.
In the following month GA4 showed 2,140 yt_start events against about 2,280 embedded views in YouTube Studio. Close enough. The reshoot wasn't needed.
How to set up YouTube video tracking in GA4 with GTM
Step 1: Enable the built-in Video variables
Variables > Built-In Variables > Configure, then tick everything under Videos: Video Current Time, Video Duration, Video Percent, Video Provider, Video Status, Video Title, Video URL, Video Visible. They read keys like gtm.videoPercent that the trigger pushes. Without the trigger, they're empty. (The GTM variables guide explains why.)
Step 2: Create the YouTube Video trigger
Triggers > New > Trigger Configuration > YouTube Video. Then:
-
Capture: tick Start, Complete and Progress. Leave "Pause, Seeking, and Buffering" off unless someone will actually read that data. It's noisy.
-
Progress: choose Percentages and enter
10, 25, 50, 75, 90. I add 90 because plenty of people close a video during the end screen and never trigger Complete. -
Advanced: tick Add JavaScript API support to all YouTube videos. GTM appends
enablejsapi=1to the player URL. Google warns it reloads a video that's already playing when GTM loads, so watch autoplay hero videos. -
Enable this trigger on: the default is Window Load. Google's March 2019 release notes recommend DOM Ready for YouTube triggers, while the help page tip (clearly copied from the scroll trigger) says Window Load. I use DOM Ready.
-
This trigger fires on: All Videos, or Some Videos with a condition like Video URL contains your channel's video IDs.
One detail from the docs worth knowing: thresholds fire only the first time they're reached. If someone drags the scrub bar from 5% to 80%, the 10, 25, 50 and 75% events don't fire.
Step 3: Create the GA4 event tag
Tags > New > Google Analytics: GA4 Event. Event name: yt_{{Video Status}}. Video Status holds the action that fired the trigger, so you get yt_start, yt_progress and yt_complete. Check the exact values in Preview before you build reports on them.
Parameters:
video_title={{Video Title}}video_url={{Video URL}}video_percent={{Video Percent}}video_current_time={{Video Current Time}}video_duration={{Video Duration}}video_provider={{Video Provider}}visible={{Video Visible}}
I reuse Google's parameter names on purpose, so the built-in Video title and Video URL dimensions can pick them up. Confirm that in an Exploration before you trust it.
Why not just name the event video_start? Because Google's event naming rules list video_start and video_progress as reserved names for web streams. If you've read my piece on how to track link clicks in GA4 with GTM, it's the same lesson as with click.
Step 4: Turn off the enhanced measurement toggle
If GTM owns video tracking, switch off Video engagement in enhanced measurement. Otherwise the same play shows up twice, as video_start and as yt_start.
Duplicates: the report that showed more starts than visitors
Sebastian works for an industrial pump manufacturer in Bielsko-Biała. Their product pages carry 3-minute demo videos, and sales wanted to know who watched them. An agency set up the GTM trigger. Nobody touched the enhanced measurement toggle.
Three months later Sebastian's Looker Studio report showed 1,412 video starts a month on product pages that got 690 sessions. His filter was "event name contains start". It summed video_start from enhanced measurement and yt_start from GTM.
On top of that, every product page had a muted, autoplaying background clip at the top. It counted as a start for every visitor, and GTM's API checkbox reloaded it, which fired a second one.
Fix: toggle off, the background clip excluded with a Some Videos condition on its Video URL, and the report filter changed to an exact event name. Starts dropped to 655 a month. Lower, and finally believable.
I'll be blunt: if your video starts are higher than your sessions on the same pages, don't celebrate. Something fires twice.
When tracking fails, and the EU consent problem
Here are the failure modes I see most, in one place:
| Symptom | Likely cause | Fix |
|---|---|---|
| Zero video events, ever | No enablejsapi=1 in the iframe |
Tick the GTM API checkbox, or add the parameter in the embed |
| Zero events on pages with thumbnails | Click-to-play facade creates the iframe late | Turn the facade off, or inject the iframe with enablejsapi=1 and use a custom IFrame API listener |
| Events only after a page reload | CMP blocks the iframe, injects it after consent | Reload the page on consent, or use a custom IFrame API listener |
| Starts but no progress | Live stream, or viewers leave in the first seconds | Live streams have no fixed duration, so percentages mean nothing. Check Video Duration in Preview |
| Double starts | Toggle and GTM both on | Pick one owner |
Now the consent part, because in the EU it matters more than the tracking.
A YouTube embed isn't neutral. The moment the iframe loads, the visitor's browser talks to Google's servers.
That's why most CMPs, Cookiebot and similar tools included, block YouTube iframes until the visitor accepts a marketing or external media category. They swap the iframe for a placeholder and inject the real one after consent. For tracking, that's the same problem as a facade: the iframe appears after GTM has loaded.
What about youtube-nocookie.com? YouTube calls it privacy-enhanced mode. It cuts back cookies before playback, which is good. It does not make the embed consent-free. The browser still connects to Google on page load, and once the video plays, YouTube can store data in the browser. I treat nocookie embeds exactly like regular ones in the CMP. Whether your trigger picks up nocookie embeds is something to verify in Preview on your own site, not something to assume.
The GA4 side is separate. Your yt_ events still respect Consent Mode. With analytics_storage denied, Basic mode sends nothing and Advanced mode sends cookieless pings. My Consent Mode v2 guide covers the difference.
Testing and registering the parameters
Open Preview and play a video. In the Tag Assistant event list you'll see YouTube Video events (in the data layer, gtm.video). Check three of them: start, one progress point, complete.
In the Variables tab, Video Status, Video Percent and Video Title should be filled. An empty Video Title usually means the API isn't connected yet.
Then GA4 Admin > DebugView. Your yt_start should arrive with all seven parameters. If it shows in Preview but not DebugView, consent is the first suspect. The GA4 debug mode guide walks through the other usual causes.
Last, register what you'll report on. Admin > Data display > Custom definitions:
video_percentas an event-scoped custom dimension, so you can build a 10/25/50/75/90 drop-off tablevideo_durationandvideo_current_timeas custom metrics, unit of measurement Seconds, if you want average watch time- Nothing else unless someone asks. A standard property has 50 event-scoped custom dimensions and they run out.
Data appears from the moment you register. Not retroactively.
Frequently asked questions
Does GA4 track YouTube videos automatically?
Only if enhanced measurement's Video engagement toggle is on and the embed has JS API support, meaning enablejsapi=1 in the iframe URL. Then GA4 sends video_start, video_progress at 10/25/50/75% and video_complete. Without the API parameter, nothing is tracked.
Why is video_start not showing in GA4?
The three usual causes: no enablejsapi=1 on the embed, an iframe that's created after page load (facades, CMP placeholders), or consent blocking the GA4 tag. Check the iframe src first, then Preview, then consent.
Can I track YouTube videos that load after the page loads? With GTM, yes, as long as at least one YouTube video or the YouTube IFrame API script is on the page when GTM loads. If neither is there, late videos are missed. A page reload after consent or a custom IFrame API listener solves it.
Should I use enhanced measurement or GTM for video tracking? GTM, if video views matter to your business. You choose the thresholds, event names and which videos to track, and every change is versioned. Use enhanced measurement only for simple sites, and never both for the same videos.
Is youtube-nocookie.com GDPR-compliant without consent? I wouldn't rely on it. Privacy-enhanced mode reduces cookies before playback, but the browser still connects to Google servers on load, and data can be stored once the video plays. Treat it like a normal YouTube embed in your CMP.
Can I track Vimeo videos with the same trigger? No. The GTM YouTube Video trigger only handles YouTube. Vimeo needs its own player API listener, usually from a community template in the Template Gallery.
Next steps
Open one of your pages with a video and inspect the iframe. No enablejsapi=1 in the src? Then enhanced measurement has reported zero plays for that embed since the day it went live, whatever the toggle says.
Then decide who owns video tracking, GTM or the toggle, and switch the other one off. Build the trigger, test start, progress and complete in Preview, and register video_percent today so next month's report has a drop-off curve.
If you'd like someone to check your video, consent and enhanced measurement setup in one pass, the free GTM audit does exactly that. For ongoing GA4 checks that notice when a theme update kills your video events, see GA4 monitoring.
Sources and further reading - Enhanced measurement events (Google Analytics Help) - YouTube video trigger (Tag Manager Help) - YouTube embedded player parameters: enablejsapi (YouTube for Developers) - Event naming rules (Google Analytics Help)
Are your video plays reaching GA4 at all?
The free GTM audit checks your YouTube triggers, enhanced measurement settings and consent setup, and tells you which embeds GA4 never sees.
Start Free GTM Audit