YouTube video tracking in Google Tag Manager
GTM4WP 2.1.0 removed its YouTube tracker. Google Tag Manager measures YouTube playback on its own, so set up its built-in YouTube Video trigger instead, as described in the next section.
When you upgrade to 2.1.0, the plugin deletes the YouTube video events option and stops adding the enablejsapi parameter to YouTube embeds. The YouTube gtm4wp.media* events stop, and so does gtm4wp.mediaApiReady, which only the YouTube tracker pushed. Review every trigger, tag and variable in your container that reads them. The gtm4wp_youtube filter is gone too.
The rest of this page describes the tracker of GTM4WP 2.0.x, so that you can look up what an existing container reads. Where the legacy 1.x versions behaved differently, the older behavior is marked with a bold GTM4WP 1.x: lead-in.
Use the native Google Tag Manager trigger
Google Tag Manager has a YouTube Video trigger of its own. It can fire on Start, on Complete, on Pause, Seeking and Buffering, and on Progress at the percentages or seconds you list. Google maintains it, and it fills the built-in Video variables directly. In Google Tag Manager, create a trigger of type YouTube Video, tick the events you want to capture, and under Advanced tick Add JavaScript API support to all YouTube videos. GTM4WP no longer adds the enablejsapi parameter to your embeds, so the trigger needs this setting to follow every player.
If your container has triggers on the YouTube gtm4wp.media events, rebuild them on the native trigger when you upgrade to 2.1.0, because those events stop. The other players keep their gtm4wp.media events.
Turning YouTube tracking on
GTM4WP 2.0.x: open the plugin settings, go to the Media events section, expand the Media players group and check YouTube video events. The option is switched off by default. GTM4WP 2.1.0 has no such option.
Which embeds are detected
The tracker wires every iframe on the page whose src begins with https://www.youtube.com/embed. Where that iframe came from does not matter: a video in your post content, in a widget, in a footer, in a page builder template or in an archive listing is treated the same way.
GTM4WP 1.x: the tracker was only loaded when the post being viewed had a YouTube address in its own content. That dropped every embed which did not live in the main post body, so a video in a widget or a template went unmeasured. The check is gone: whether a page has a player can only be answered once the page has been built, and the plugin now asks that question in the browser instead.
Privacy enhanced embeds served from youtube-nocookie.com do not match that address and are not tracked.
The YouTube iframe API only accepts commands from a player that was embedded with enablejsapi=1, so the plugin adds that parameter together with an origin parameter. It does so twice over: once on the server when WordPress builds the embed code, and again in the browser for any player iframe that still lacks it. If the address carries a fragment, the parameters go in front of it, since anything after a # never reaches YouTube at all.
The API itself is only requested once the tracker has actually found a YouTube player on the page, so a page without one never contacts YouTube.
A video that is in the page when it loads is wired straight away. A video inserted later, for example in a popup, a lightbox or a section loaded by AJAX, needs the Track dynamically inserted players option in the Advanced group as well.
Playback states
The gtm4wp.mediaPlayerStateChange event fires with these values in the mediaPlayerState variable:
| mediaPlayerState | Fires when |
|---|---|
play | The video starts playing. |
pause | The visitor pauses the video. |
buffering | The player is buffering. |
ended | The video reaches its end. |
cued | A video has been loaded and is ready to play. |
unstarted | The player reports that the video has not started. |
unknown | The player reports a state the plugin does not recognize. |
YouTube reports no seek event of its own, so there is no seeked state here. Jumping to another position usually shows up as a buffering state followed by play.
Player events
The gtm4wp.mediaPlayerEvent event carries the name of the event in the mediaPlayerEvent variable and the accompanying value in mediaPlayerEventParam.
| mediaPlayerEvent | mediaPlayerEventParam |
|---|---|
quality-change | The playback quality the player switched to. |
ratechange | The new playback rate. |
error | The error code reported by YouTube. |
api-change | Reports that the player loaded or unloaded a module that exposes API methods. |
The gtm4wp.mediaApiReady event
YouTube is the only player that fires gtm4wp.mediaApiReady. It is pushed once per page, when the YouTube iframe API has finished loading and before any individual player is wired. No video is involved at that point, so the event carries mediaType and nothing else, and it is the one media event that does not fill the built-in Video variables.
What mediaData holds for a YouTube video
| Variable | Contents |
|---|---|
mediaData.id | The YouTube video ID. |
mediaData.author | The name of the channel that published the video. YouTube is one of only four players that report this. |
mediaData.title | The title of the video, as reported by the player. |
mediaData.url | The watch URL of the video. |
mediaData.duration | The length of the video in seconds. |
The mediaType variable is youtube in every event.
Google Tag Manager built-in Video variables
New in 2.0.0. Every YouTube media event except gtm4wp.mediaApiReady also populates the built-in Video variables of Google Tag Manager, with Video Provider set to youtube. The section on built-in Video variables explains how to enable and use them.
The cued, unstarted and unknown states have no counterpart in Google Tag Manager, so Video Status is empty for all three. Read mediaPlayerState when you need to tell them apart.
Video Visible is measured on the player iframe, so it reports whether that video was on screen when the event fired. See Video Visible on the hub page for exactly what is and is not detected.
Building a trigger in Google Tag Manager
To fire a tag when a visitor starts a YouTube video:
- Create a Data Layer Variable named
mediaPlayerState. - Create a Custom Event trigger whose event name is
gtm4wp.mediaPlayerStateChange. - Add the condition
mediaPlayerStateequalsplayto the trigger. - Attach the trigger to your tag. To send the title of the video along with it, create a second Data Layer Variable named
mediaData.title.
Use ended in place of play to measure a video that was watched to the end. To measure progress, build the trigger on gtm4wp.mediaPlaybackPercentage and add a condition on mediaPercentage instead.
Limitations
- The option was deprecated in 2.0.0 and removed in 2.1.0. Google Tag Manager measures YouTube natively.
- Privacy enhanced embeds on
youtube-nocookie.comare not detected. - The tracker claims the global
onYouTubeIframeAPIReadycallback that the YouTube API calls when it loads. Only one script on a page can own it. If another plugin or a Google Tag Manager tag has already defined it, GTM4WP stops with an error and no YouTube tracking happens at all. - There is no
seekedstate, because the YouTube API reports no seek event. - Progress is measured by asking the player for its position once a second while it plays, so a milestone can land a fraction of a second after the visitor passes it.
- There is no 100 percent milestone. Measure a full watch with the
endedstate, as described under playback percentage milestones.
Related pages
The overview of media player tracking describes the events, data layer variables and playback milestones that every player shares. See also Vimeo, the other widely used video host, and dynamically inserted players if your videos open in a popup or a lightbox.

