Vimeo video player with Google Tag Manager (custom solution)

 


Create a variable “Is Vimeo player present on a page”


To do that, first, we need to create a Custom JavaScript variable and paste the following code:

function () {
for (var e = document.getElementsByTagName("iframe"), x=0; x < e.length; x++) {
if (/^https?:\/\/player.vimeo.com/.test(e[x].src)) {
return true;
}
}
return false;
}


If the page has a Vimeo player embedded in it, this variable will return true.


Custom Javascript - Vimeo player is present


 

Then create a Pageview trigger and use that Custom JavaScript variable in it. If the Vimeo player is present, this trigger will be activated. If there is no Vimeo player, that trigger will remain silent.


Check it in Preview and Debug mode, and you should get something like this.





Vimeo Auto-Event Listener



<script type="text/javascript" id="gtm-vimeo-tracking">

;(function(document, window, config) {

  'use strict';

  // The API won't work on LT IE9, so we bail if we detect those UAs

  if (navigator.userAgent.match(/MSIE [678]\./gi)) return;
  config = cleanConfig(config);

  var handle = getHandler(config.syntax);
  if (document.readyState !== 'loading') {
    init();
  } else {
    document.addEventListener('DOMContentLoaded', function() {
      init();
      document.addEventListener('load', init, true);
    });
  }

  function init() {
    var videos = filter_(selectAllTags_('iframe'), isVimeo);
    if (!videos.length) return;
    loadApi(function() {
      forEach_(videos, listenTo);
    });
  }

  function isVimeo(el) {
    return el.src.indexOf('player.vimeo.com/video/') > -1;

  }

  function loadApi(callback) {
    if (isUndefined_(window.Vimeo)) {
      loadScript('https://player.vimeo.com/api/player.js', callback);
    } else {
      callback();
    }
  }

  function listenTo(el) {
    if (el.__vimeoTracked) return;
    el.__vimeoTracked = true;
    var video = new Vimeo.Player(el);
    var percentages = config._track.percentages;
    var eventNameDict = {
      'play': 'play',
      'pause': 'pause',
      'complete': 'ended'
    };
    var cache = {};
    video.getVideoTitle()
      .then(function(title) {
        forEach_(['play', 'pause', 'complete'], function(key) {
          if (config.events[key]) {
            video.on(eventNameDict[key], function() {
              handle(key, title);
            });
          }
        });
        if (percentages) {
          video.on('timeupdate', function(evt) {
            var percentage = evt.percent;
            var key;
            for (key in percentages) {
              if (percentage >= percentages[key] && !cache[key]) {
                cache[key] = true;
                handle(key, title);
              }
            }
          });
        }
      });
  }

  function cleanConfig(config) {
    config = extend_({}, {
      events: {
        'play': true,
        'pause': true,
        'complete': true
      },
      percentages: {
        each: [],
        every: []
     }
    }, config);
    forEach_(['each', 'every'], function(setting) {
      var vals = config.percentages[setting];
      if (!isArray_(vals)) vals = [vals];
      if (vals) config.percentages[setting] = map_(vals, Number);
    });
    var points = [].concat(config.percentages.each);
    if (config.percentages.every) {
      forEach_(config.percentages.every, function(val) {
        var n = 100 / val;
        var every = [];
        var i;
        for (i = 1; i < n; i++) every.push(val * i);
        points = points.concat(filter_(every, function(val) {
          return val > 0.0 && val < 100.0;
        }));
      });
    }
    var percentages = reduce_(points, function(prev, curr) {
      prev[curr + '%'] = curr / 100.0;
      return prev;
    }, {});
    config._track = {
      percentages: percentages
    };
    return config;
  }

  function getHandler(syntax) {
    syntax = syntax || {};
    var gtmGlobal = syntax.name || 'dataLayer';
    var uaGlobal = syntax.name || window.GoogleAnalyticsObject || 'ga';
    var clGlobal = '_gaq';
    var dataLayer;
    var handlers = {
      'gtm': function(state, title) {
        if (state.indexOf('%') === -1 && state.indexOf('play') === -1) {
          dataLayer.push({
            event: 'video',
            video_provider: 'vimeo',
            video_action: state,
            video_title: title.toLowerCase(),
            video_percent: undefined
            });
        } else if (state === '0%'){
          dataLayer.push({
            event: 'video',
            video_provider: 'vimeo',
            video_action: 'start',
            video_title: title.toLowerCase(),
            video_percent: undefined
          });
        } else if (state.indexOf('play') === -1) {
          dataLayer.push({
            event: 'video',
            video_provider: 'vimeo',
            video_action: 'progress',
            video_percent: state,
            video_title: title.toLowerCase()
          });
        }
      },
      'cl': function(state, title) {
        window[clGlobal].push(['_trackEvent', 'Videos', state, title]);
      },
      'ua': function(state, title) {
        window[uaGlobal]('send', 'event', 'Videos', state, title);
      }
    };
    switch(syntax.type) {
      case 'gtm':
        dataLayer = window[gtmGlobal] = window[gtmGlobal] || [];
        break;
      case 'ua':
        window[uaGlobal] = window[uaGlobal] || function() {
          (window[uaGlobal].q = window[uaGlobal].q || []).push(arguments);
        };
        window[uaGlobal].l = +new Date();
        break;
      case 'cl':
        window[clGlobal] = window[clGlobal] || [];
        break;
      default:
        if (!isUndefined_(window[gtmGlobal])) {
          syntax.type = 'gtm';
          dataLayer = window[gtmGlobal] = window[gtmGlobal] || [];
        } else if (uaGlobal&& !isUndefined_(window[uaGlobal])) {
          syntax.type = 'ua';
        } else if (!isUndefined_(window[clGlobal]) && !isUndefined_(window[clGlobal].push)) {
          syntax.type = 'cl';
        }
        break;
    }
    return handlers[syntax.type];
  }

  function extend_() {
    var args = [].slice.call(arguments);
    var dst = args.shift();
    var src;
    var key;
    var i;
    for (i = 0; i < args.length; i++) {
      src = args[i];
      for (key in src) {
        dst[key] = src[key];
      }
    }
    return dst;
  }
  function isArray_(o) {
    if (Array.isArray_) return Array.isArray_(o);
    return Object.prototype.toString.call(o) === '[object Array]';
  }
  function forEach_(arr, fn) {
    if (Array.prototype.forEach_) return arr.forEach.call(arr, fn);
    var i;
    for (i = 0; i < arr.length; i++) {
      fn.call(window, arr[i], i, arr);
    }
  }
  function map_(arr, fn) {
    if (Array.prototype.map_) return arr.map.call(arr, fn);
    var newArr = [];
    forEach_(arr, function(el, ind, arr) {
      newArr.push(fn.call(window, el, ind, arr));
    });
    return newArr;
  }
  function filter_(arr, fn) {
    if (Array.prototype.filter) return arr.filter.call(arr, fn);
    var newArr = [];
    forEach_(arr, function(el, ind, arr) {
      if (fn.call(window, el, ind, arr)) newArr.push(el);
    });
    return newArr;
  }
  function reduce_(arr, fn, init) {
    if (Array.prototype.reduce) return arr.reduce.call(arr, fn, init);
    var result = init;
    var el;
    var i;
    for (i = 0; i < arr.length; i++) {
      el = arr[i];
      result = fn.call(window, result, el, arr, i);
    }
    return result;
  }
  function isUndefined_(thing) {
    return typeof thing === 'undefined';
  }
  function selectAllTags_(tags) {
    if (!isArray_(tags)) tags = [tags];
    return [].slice.call(document.querySelectorAll(tags.join()));
  }
  function loadScript(src, callback) {
    var f, s;
    f = document.getElementsByTagName('script')[0];
    s = document.createElement('script');
    s.onload = callCallback;
    s.src = src;
    s.async = true;
    f.parentNode.insertBefore(s, f);
    function callCallback() {
      if (callback) {
        callback();
        s.onload = null;
      }
    }
  }
})(document, window, {
  'events': {
    'play': true,
    'pause': false,
    'complete': true
  },
  'percentages': {
    'every': 25,
    'each': [0, 90]
  }
});

/*
 * v1.0.1
 * Created by the Google Analytics consultants at http://www.lunametrics.com
 * Written by @notdanwilkerson
 * Documentation: https://github.com/lunametrics/vimeo-google-analytics/
 * Licensed under the MIT License
 * Modified by Julius Fedorovicius at https://www.analyticsmania.com
 */
</script>


Don’t forget to assign the previously created Window Loaded Trigger:





Create Data Layer Variables and a Custom Event Trigger



After configuring them, it’s time to create a Custom Event Trigger. Vimeo Auto-Event Listener sends all interactions as Data Layer events under “video”.

dataLayer.push({
event: "video",
  ...
});


GTM, go to Triggers > New > Custom Event and enter the following settings:





Create a Google Analytics 4 Tag



Event Name:- video_{{dlv-video_action}}

Event Parameters

video_percent
video_title
video_provider




Page