JWPlayer video tracking using Google Tag Manager

Last updated on June 29, 2015

JWPlayer is one the most known video players (if not the most one) and today we’re going to learn how to track it using GTM (Google Tag Manager). This time we’re going to use an agnostic dataLayer pushes instead of the ones that we usually use for Google Analytics. 

We’ll be using one tag, one trigger and one variable, and in the next list we’re resuming all the events that our code will be able to track:

  • Video Plays
  • Video Pauses
  • Video Completions
  • Video Progress (Percentages to be tracked can be easily defined in the first line of the code)
  • Video Mute and UnMute
  • Video FullScreen On and FullScreen Off
  • Video Errors

As we said before we’re going to use a tool agnostic dataLayer pushes instead of focusing in the almost standard event tracking model from Google Analytics. The following object will be our video tracking data model:

    "event": "video",
    "player_id": {{VIDEO_ID}},
    "interaction": {{VIDEO_ACTION}},
    "video_url": {{VIDEO_URL}},
    "duration": {{VIDEO_DURATION}},
    "width": {{PLAYER_WIDTH}},
    "height": {{PLAYER_HEIGHT}},
    "position": {{VIDEO_CURRENT_POSITION}},
    "resolutions": {{AVAILABLE_VIDEO_QUALITIES}}, // an array
    "volume": {{PLAYER_VOLUME}},
    "player_type": {{PLAYER_TYPE}} // html5 or flash

Most important data is the event, the interacction and the video_url (as used of the most video tracking scripts), but this time we’ll be adding some extra to the dataLayer pushes to be able to track more details info if we want to.

Let’s start creating our needed configuration on Google Tag Manager. First thing that we’re going to need is to have a variable that is going to tell us if there’s any jwplayer available in the current page. We don’t want our tracking code to be injected in the page if we don’t have any video on it, do we?.



Now it’s time to configure the trigger that is going to fire our tracking tag, so we’ll be using the previously created variable, and a second condition to trigger the tracking tag after the DOMReady event:



Let’s configure the tracking tag, after the screenshoot you’ll find the full code so you can copy & paste it:


Tag Code

Now all the video interactions info will be pushes to the dataLayer so you’ll have all that info available to send your events to Google Analytics or any other tool you like.
Any suggestion, new tracking idea, feedback will be welcome, just leave a comment.


  1. Hello David,

    We just started with GTM and we are trying alot of new things. This is definitly tricky to implement but we are going to give a try.

    Did you personalize the javascript code yourself?

    We will let you know later how it went. Thanks for this 🙂

  2. Yesenia Chappell
    July 22, 2015

    in the screenshot for the variable you show “jwplayer” but in the screenshot for the trigger you show “isJWPlayerAvailable”. Is this a typo?

    • July 22, 2015

      it’s not. You need to create a variable in GTM ( named in my example as IsJWPlayerAvailable, you can name it however you want ) that read the global javascript variable named “jwplayer”.

  3. Yesenia Chappell
    July 24, 2015

    Thank you for your quick reply. I’ve completed this setup and everything is working ok except that the .onPlay action is adding a new event every time the visitor click on the play icon (which is supposed to do). However, this is inflating the real number of views a video has. Is it possible to add in the logic to only count the first time the onPlay is called?

    Example: For one video, if I click play, pause, play, pause, play pause; the results show 3 plays for the video. The more accurate number should be only one for that visitor.

    Please let me know if you can provide some insights here.

    Thanks in advance for your help.

  4. Yesenia Chappell
    July 28, 2015

    I just added a filter on the trigger to only send ‘play’ when the currentPosition was less than 3 seconds. Basically, only the first time ‘play’ is hit.

    Thanks for this coding. It helped me a lot to understand more GTM and the extra options it has to implement.

  5. marcelo
    August 5, 2015


    Thanks for the guide, it was really useful.

    One question: how can i send all that info to Google Analytics as an event?

    Thanks in advance,

  6. Lee
    August 26, 2015

    This is lovely, David, thank you.

    One question for you – it’s more valuable for us to pull in the video’s title instead of its URL.

    getplaylistItem().file works just fine, but if I use getplaylistItem().title instead it always returns undefined.

    If I leave .title or .file off, it will pull everything available and dump it into the data layer… and even here I see things like description, title, mediaid all as “undefined”. Whereas everything else (duration, position, this.id, interaction, file) all display data just fine, as you’ve identified above.

    I’m totally at a loss and JWPlayer support is pretty much nonexistent. Do you have any light you might be able to shed on this issue?

    Much thanks!

    • August 26, 2015

      Without seeing the pages where the player is I can’t say much. To bring some idea, if you’re directly loading a video file there won’t a title for it as it won’t be defined anywhere.

      Can you please mail me with the player URL so I can take a quick look to it?

      • Lee
        August 26, 2015

        Wow, that was a fast reply. I’m emailing you now – the site hasn’t launched yet (goes up tomorrow or Monday) so I can’t put it out here publicly.

  7. Philip
    August 28, 2015

    Are you using the datalayer because JWplayer does not support Google Tag Manager. So far, I’ve tested JW7 and have not seen any events. I was on the verge of experimenting with JW7 and Google Analytics. But I prefer to continue using GTM.

    • August 29, 2015

      I’m using a dataLayer to have an agnostic way to track the player, all info is pushed into the dataLayer, so you can fire any tool within Google Tag Manager.

      Please check if dataLayer pushes are being sent typing “dataLayer” into the browser console, if they’re there, you’re missing to setup your tags and triggers.

  8. Philip
    August 28, 2015

    One other question David. To validate that the event is fired, does Real-Time Events work? So far, it has not for us.


    • August 29, 2015

      If you configured GTM for sending events based of the current values sent to the datalayer it should. If you’re following the post example you should have some event tag that is fired on the event “video” . Take in mind that category and action are needed values on a event type tag.

    • August 31, 2015

      So you were directly sending the ga() commands into the code?, I think it’s better to use the in-build tags for firing the events, to avoid future problems.

  9. Dan
    September 9, 2015

    What would a smpale trigger be to fire off the event to pass data via the event I setup.

  10. J
    October 9, 2015

    Hi David,

    I tried your instructions but it’s not working for me. When I click on my JWPlayer video, the event trigger doesn’t fire to get the information on my click. Any idea?


  11. Tom Smith
    October 13, 2015

    Great script – all events firing apart from the onTime – do I need to amend the script above at all?

  12. James
    October 16, 2015

    Hi David,

    Great tutorial – one question though. What version of JW player does this support? 6 or 7?


  13. October 26, 2015

    Hi David,

    I tried a lot to your instructions but it isn’t working for me also. However when I click on JWPlayer video present on my website, the event trigger fired to get the information. But still Google Analytics is still unable to track the videos. Suggest me please what I need to do.

    If you wish I can show you each and every step (via screencast) that, has been done to track the same.

    Thanks in Advance

  14. Martin
    December 18, 2015

    Hi David,

    Problem: only some browsers sending data to dataLayers. I’ve tried personally – no dataLayer push, but I see that other users are pushing dataLayers, also events rules calling GA tags.
    JWP – 6.12 with ads

    • January 14, 2016

      I tried it and It seems to be workign for me. Do you see any errors on your console? Mail me the page to see if I can see anything.

  15. January 6, 2016

    This may be a silly question but would I replace the properties of this function? …haystack, key, needle

    function findObjectIndexById(haystack, key, needle)

    • January 14, 2016

      well, why would you need to change them? it’s a function I use to find an index name inside an object, but feel free to change them as long as you change their references inside the function.

  16. Arejay
    January 7, 2016

    I’ve followed the steps and the plays and buttons are all tracking correctly. But it is not tracking the percentage played. Am I supposed to configure the section below to get the percentage played to be tracked?

    var i = 0;
    // Define at which percentages you want to fire an event
    var markers = [1,2,3,4,5,10,25,50,70,75,90];
    var playersMarkers = [];

    • January 14, 2016

      Arejay, what JWPlayer version are you using ?. it should work out of the box …

  17. Yannick
    April 13, 2016

    Hi David,

    thanks for that! I have a somewhat strange problem; I followed your instructions quite scrupulously.

    When I use the GTM debugger, I see the JWPlayer Tracking Tool firing only when there is a jwplayer (following your trigger where the variable “jwplayer” is not undefined).

    However, nothing is added to the data layer when I interact with the player, and no error message shows in the console.

    When I manually copy paste your exact code into the Javascript console, then the events are added to the data layer.

    So your script works fine when it’s pasted directly, but not when it’s obtained via the GTM – even if it is executed only when the player is present, which makes me think the trigger is working as expected.

    I use JWP 7 and the latest GTM.

    Any ideas will be welcome, I’m at a loss. Thanks!


  18. Sebastian
    April 27, 2016

    Hi David,

    thanks for this really helpful guide. It works fine for our site. But i also would like to track an embedded youtube player in the same manner. Therefore I added the variable and the Trigger for Youtube and just changed the name of the player in the skript to YT.Player so it looks like this:
    while (true) {
    var player = YT.Player(i);
    if (!player.id)
    But that doesn’t work. Do i have to make more changes? Is it possible to track an embedded YouTube Player with this skript?

    Thanks a lot!

  19. Seth
    June 9, 2016

    This is great and I can see the items being pushed to the dataLayer… only thing I am missing is how you push the values in the dataLayer into Google Analytics as an event using GTM?

    Maybe I missed something? Any links or articles that would help me with this would be great.

  20. Joe
    July 19, 2016

    Hi David,

    I’m having the same issue as Yannick – I can see JWPlayer Tracking Tool firing – but nothing is added to the datalayer. It would be great to get this working – as we use GTM and JWplayer but aren’t seeing any events at the moment. If anyone has any ideas/suggestions on getting it working recently, please let me know.


  21. September 29, 2016

    Hi there,

    Thanks for posting this great script—very very useful method.

    I’ve set this up through GTM but I’m seeing two “Play” events whenever I play a video for the first time on a page. The dataLayer is populated with the same values on each event (unlike with the 1%, 2% etc events) so this seems like a bug. Has anyone else experienced this or is it local to the embeds I’m attempting to track? By contract, the 1% event only appears once, which is correct behaviour.

    As a solution I suppose I can just not send the Play events to GA and use the 1% events to measure plays (fine as long as the videos aren’t very long). I’d be intrigued to hear if anyone else is seeing this or has a better solution.

    Many thanks again

  22. April 25, 2017

    Thanks for your tetorial, i’m not sure if it is updated with the latest JWPlayer as i have implemented the solution as presented above however i didnt recieve the data.

    the steps i did is :

    2. Created JS Variable – IsJWplayerAvailable
    3. Created Load Rule on Dom Ready JWPlayer on DomReady
    4. Added the Script to Custom HTML Tag and Firing Trigger = IsJWplayerAvailable does not equal undefined

    The results were no data available in the dataLayer variables when clicking on any of the videos.
    What am i doing wrong?

    I didnt publish to production however would love to know what i’m doing wrong.


Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.