Comparing version 2.0.4 to 2.1.0
109
autotrack.js
@@ -1,54 +0,57 @@ | ||
(function(){var f,aa="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(c.get||c.set)throw new TypeError("ES3 does not support getters and setters.");a!=Array.prototype&&a!=Object.prototype&&(a[b]=c.value)},k="undefined"!=typeof window&&window===this?this:"undefined"!=typeof global&&null!=global?global:this;function l(){l=function(){};k.Symbol||(k.Symbol=ba)}var ca=0;function ba(a){return"jscomp_symbol_"+(a||"")+ca++} | ||
function m(){l();var a=k.Symbol.iterator;a||(a=k.Symbol.iterator=k.Symbol("iterator"));"function"!=typeof Array.prototype[a]&&aa(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return da(this)}});m=function(){}}function da(a){var b=0;return ea(function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}})}function ea(a){m();a={next:a};a[k.Symbol.iterator]=function(){return this};return a} | ||
function n(a){if(!(a instanceof Array)){m();var b=a[Symbol.iterator];a=b?b.call(a):da(a);for(var c=[];!(b=a.next()).done;)c.push(b.value);a=c}return a}function fa(a,b){function c(){}c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a;for(var d in b)if(Object.defineProperties){var e=Object.getOwnPropertyDescriptor(b,d);e&&Object.defineProperty(a,d,e)}else a[d]=b[d]} | ||
var p=window.Element.prototype,ha=p.matches||p.matchesSelector||p.webkitMatchesSelector||p.mozMatchesSelector||p.msMatchesSelector||p.oMatchesSelector;function ia(a,b){if(a&&1==a.nodeType&&b){if("string"==typeof b||1==b.nodeType)return a==b||ja(a,b);if("length"in b)for(var c=0,d;d=b[c];c++)if(a==d||ja(a,d))return!0}return!1}function ja(a,b){if("string"!=typeof b)return!1;if(ha)return ha.call(a,b);b=a.parentNode.querySelectorAll(b);for(var c=0,d;d=b[c];c++)if(d==a)return!0;return!1} | ||
function ka(a){for(var b=[];a&&a.parentNode&&1==a.parentNode.nodeType;)a=a.parentNode,b.push(a);return b} | ||
function q(a,b,c){function d(a){var d;if(g.composed&&"function"==typeof a.composedPath)for(var e=a.composedPath(),h=0,E;E=e[h];h++)1==E.nodeType&&ia(E,b)&&(d=E);else a:{if((d=a.target)&&1==d.nodeType&&b)for(d=[d].concat(ka(d)),e=0;h=d[e];e++)if(ia(h,b)){d=h;break a}d=void 0}d&&c.call(d,a,d)}var e=document,g={composed:!0,P:!0},g=void 0===g?{}:g;e.addEventListener(a,d,g.P);return{j:function(){e.removeEventListener(a,d,g.P)}}} | ||
function la(a){var b={};if(!a||1!=a.nodeType)return b;a=a.attributes;if(!a.length)return{};for(var c=0,d;d=a[c];c++)b[d.name]=d.value;return b}var ma=/:(80|443)$/,r=document.createElement("a"),t={}; | ||
function u(a){a=a&&"."!=a?a:location.href;if(t[a])return t[a];r.href=a;if("."==a.charAt(0)||"/"==a.charAt(0))return u(r.href);var b="80"==r.port||"443"==r.port?"":r.port,b="0"==b?"":b,c=r.host.replace(ma,"");return t[a]={hash:r.hash,host:c,hostname:r.hostname,href:r.href,origin:r.origin?r.origin:r.protocol+"//"+c,pathname:"/"==r.pathname.charAt(0)?r.pathname:"/"+r.pathname,port:b,protocol:r.protocol,search:r.search}}var v=[]; | ||
function na(a,b){var c=this;this.context=a;this.N=b;this.f=(this.c=/Task$/.test(b))?a.get(b):a[b];this.b=[];this.a=[];this.i=function(a){for(var b=[],d=0;d<arguments.length;++d)b[d-0]=arguments[d];return c.a[c.a.length-1].apply(null,[].concat(n(b)))};this.c?a.set(b,this.i):a[b]=this.i}function w(a,b){a.b.push(b);oa(a)}function x(a,b){b=a.b.indexOf(b);-1<b&&(a.b.splice(b,1),0<a.b.length?oa(a):a.j())} | ||
function oa(a){a.a=[];for(var b,c=0;b=a.b[c];c++){var d=a.a[c-1]||a.f.bind(a.context);a.a.push(b(d))}}na.prototype.j=function(){var a=v.indexOf(this);-1<a&&(v.splice(a,1),this.c?this.context.set(this.N,this.f):this.context[this.N]=this.f)};function y(a,b){var c=v.filter(function(c){return c.context==a&&c.N==b})[0];c||(c=new na(a,b),v.push(c));return c} | ||
function z(a,b,c,d,e){if("function"==typeof d){var g=c.get("buildHitTask");return{buildHitTask:function(c){c.set(a,null,!0);c.set(b,null,!0);d(c,e);g(c)}}}return A({},a,b)}function B(a,b){var c=la(a),d={};Object.keys(c).forEach(function(a){if(!a.indexOf(b)&&a!=b+"on"){var e=c[a];"true"==e&&(e=!0);"false"==e&&(e=!1);a=pa(a.slice(b.length));d[a]=e}});return d} | ||
function qa(a){"loading"==document.readyState?document.addEventListener("DOMContentLoaded",function c(){document.removeEventListener("DOMContentLoaded",c);a()}):a()}function ra(a,b){var c;return function(d){for(var e=[],g=0;g<arguments.length;++g)e[g-0]=arguments[g];clearTimeout(c);c=setTimeout(function(){return a.apply(null,[].concat(n(e)))},b)}}function sa(a){function b(){c||(c=!0,a())}var c=!1;setTimeout(b,2E3);return b} | ||
var A=Object.assign||function(a,b){for(var c=[],d=1;d<arguments.length;++d)c[d-1]=arguments[d];for(var e=0;d=c[e];e++)for(var g in d)Object.prototype.hasOwnProperty.call(d,g)&&(a[g]=d[g]);return a};function pa(a){return a.replace(/[\-\_]+(\w?)/g,function(a,c){return c.toUpperCase()})}function C(a){return"object"==typeof a&&null!==a} | ||
function F(a,b){var c=window.GoogleAnalyticsObject||"ga";window[c]=window[c]||function(a){for(var b=[],d=0;d<arguments.length;++d)b[d-0]=arguments[d];(window[c].q=window[c].q||[]).push(b)};window.gaDevIds=window.gaDevIds||[];0>window.gaDevIds.indexOf("i5iSjo")&&window.gaDevIds.push("i5iSjo");window[c]("provide",a,b);window.gaplugins=window.gaplugins||{};window.gaplugins[a.charAt(0).toUpperCase()+a.slice(1)]=b}var G={R:1,S:2,T:3,V:4,W:5,X:6,Y:7,Z:8,$:9,U:10},H=Object.keys(G).length; | ||
function I(a,b){a.set("\x26_av","2.0.4");var c=a.get("\x26_au"),c=parseInt(c||"0",16).toString(2);if(c.length<H)for(var d=H-c.length;d;)c="0"+c,d--;b=H-b;c=c.substr(0,b)+1+c.substr(b+1);a.set("\x26_au",parseInt(c||"0",2).toString(16))}function J(a,b){I(a,G.R);this.a=A({},b);this.i=a;this.b=this.a.stripQuery&&this.a.queryDimensionIndex?"dimension"+this.a.queryDimensionIndex:null;this.f=this.f.bind(this);this.c=this.c.bind(this);b=this.f;w(y(a,"get"),b);b=this.c;w(y(a,"buildHitTask"),b)} | ||
J.prototype.f=function(a){var b=this;return function(c){if("page"==c||c==b.b){var d={location:a("location"),page:a("page")};return ta(b,d)[c]}return a(c)}};J.prototype.c=function(a){var b=this;return function(c){var d=ta(b,{location:c.get("location"),page:c.get("page")});c.set(d,null,!0);a(c)}}; | ||
function ta(a,b){var c=u(b.page||b.location),d=c.pathname;if(a.a.indexFilename){var e=d.split("/");a.a.indexFilename==e[e.length-1]&&(e[e.length-1]="",d=e.join("/"))}"remove"==a.a.trailingSlash?d=d.replace(/\/+$/,""):"add"==a.a.trailingSlash&&(/\.\w+$/.test(d)||"/"==d.substr(-1)||(d+="/"));d={page:d+(a.a.stripQuery?"":c.search)};b.location&&(d.location=b.location);a.b&&(d[a.b]=c.search.slice(1)||"(not set)");return"function"==typeof a.a.urlFieldsFilter?(b=a.a.urlFieldsFilter(d,u),c={},c.page=b.page, | ||
c.location=b.location,c[a.b]=b[a.b],c):d}J.prototype.remove=function(){var a=this.f;x(y(this.i,"get"),a);a=this.c;x(y(this.i,"buildHitTask"),a)};F("cleanUrlTracker",J);function K(a,b){var c=this;I(a,G.S);if(window.addEventListener){this.a=A({events:["click"],fieldsObj:{},attributePrefix:"ga-"},b);this.f=a;this.c=this.c.bind(this);var d="["+this.a.attributePrefix+"on]";this.b={};this.a.events.forEach(function(a){c.b[a]=q(a,d,c.c)})}} | ||
K.prototype.c=function(a,b){var c=this.a.attributePrefix;a.type==b.getAttribute(c+"on")&&(a=B(b,c),c=A({},this.a.fieldsObj,a),this.f.send(a.hitType||"event",z({transport:"beacon"},c,this.f,this.a.hitFilter,b)))};K.prototype.remove=function(){var a=this;Object.keys(this.b).forEach(function(b){a.b[b].j()})};F("eventTracker",K); | ||
function ua(a,b){var c=this;I(a,G.T);window.IntersectionObserver&&window.MutationObserver&&(this.a=A({rootMargin:"0px",fieldsObj:{},attributePrefix:"ga-"},b),this.c=a,this.K=this.K.bind(this),this.M=this.M.bind(this),this.I=this.I.bind(this),this.J=this.J.bind(this),this.b=null,this.items=[],this.h={},this.g={},qa(function(){return c.observeElements(c.a.elements)}))}f=ua.prototype; | ||
f.observeElements=function(a){var b=this;a=L(this,a);this.items=this.items.concat(a.items);this.h=A({},a.h,this.h);this.g=A({},a.g,this.g);a.items.forEach(function(a){var c=b.g[a.threshold]=b.g[a.threshold]||new IntersectionObserver(b.M,{rootMargin:b.a.rootMargin,threshold:[+a.threshold]});(a=b.h[a.id]||(b.h[a.id]=document.getElementById(a.id)))&&c.observe(a)});this.b||(this.b=new MutationObserver(this.K),this.b.observe(document.body,{childList:!0,subtree:!0}));requestAnimationFrame(function(){})}; | ||
f.unobserveElements=function(a){var b=[],c=[];this.items.forEach(function(d){a.some(function(a){a=va(a);return a.id===d.id&&a.threshold===d.threshold&&a.trackFirstImpressionOnly===d.trackFirstImpressionOnly})?c.push(d):b.push(d)});if(b.length){var d=L(this,b),e=L(this,c);this.items=d.items;this.h=d.h;this.g=d.g;c.forEach(function(a){if(!d.h[a.id]){var b=e.g[a.threshold],c=e.h[a.id];c&&b.unobserve(c);d.g[a.threshold]||e.g[a.threshold].disconnect()}})}else this.unobserveAllElements()}; | ||
f.unobserveAllElements=function(){var a=this;Object.keys(this.g).forEach(function(b){a.g[b].disconnect()});this.b.disconnect();this.b=null;this.items=[];this.h={};this.g={}};function L(a,b){var c=[],d={},e={};b.length&&b.forEach(function(b){b=va(b);c.push(b);e[b.id]=a.h[b.id]||null;d[b.threshold]=a.g[b.threshold]||null});return{items:c,h:e,g:d}}f.K=function(a){for(var b=0,c;c=a[b];b++){for(var d=0,e;e=c.removedNodes[d];d++)M(this,e,this.J);for(d=0;e=c.addedNodes[d];d++)M(this,e,this.I)}}; | ||
function M(a,b,c){1==b.nodeType&&b.id in a.h&&c(b.id);for(var d=0,e;e=b.childNodes[d];d++)M(a,e,c)} | ||
f.M=function(a){for(var b=[],c=0,d;d=a[c];c++)for(var e=0,g;g=this.items[e];e++){var h;if(h=d.target.id===g.id)(h=g.threshold)?h=d.intersectionRatio>=h:(h=d.intersectionRect,h=0<h.top||0<h.bottom||0<h.left||0<h.right);if(h){var D=g.id;h=document.getElementById(D);var D={transport:"beacon",eventCategory:"Viewport",eventAction:"impression",eventLabel:D,nonInteraction:!0},Ea=A({},this.a.fieldsObj,B(h,this.a.attributePrefix));this.c.send("event",z(D,Ea,this.c,this.a.hitFilter,h));g.trackFirstImpressionOnly&& | ||
b.push(g)}}b.length&&this.unobserveElements(b)};f.I=function(a){var b=this,c=this.h[a]=document.getElementById(a);this.items.forEach(function(d){a==d.id&&b.g[d.threshold].observe(c)})};f.J=function(a){var b=this,c=this.h[a];this.items.forEach(function(d){a==d.id&&b.g[d.threshold].unobserve(c)});this.h[a]=null};f.remove=function(){this.unobserveAllElements()};F("impressionTracker",ua);function va(a){"string"==typeof a&&(a={id:a});return A({threshold:0,trackFirstImpressionOnly:!0},a)} | ||
function wa(){this.a={}}wa.prototype.aa=function(a,b){for(var c=[],d=1;d<arguments.length;++d)c[d-1]=arguments[d];(this.a[a]=this.a[a]||[]).forEach(function(a){return a.apply(null,[].concat(n(c)))})};var N={},O=!1;function P(a,b){this.a={};this.key=a;this.H=b||{}}fa(P,wa);function Q(a,b,c){a=["autotrack",a,b].join(":");N[a]||(N[a]=new P(a,c),N[a].key=a,O||(window.addEventListener("storage",xa),O=!0));return N[a]} | ||
P.prototype.get=function(){try{var a=String(window.localStorage.getItem(this.key));return R(a,this.H)}catch(b){return{}}};P.prototype.set=function(a){var b=this.get();a=A(b,a);try{window.localStorage.setItem(this.key,JSON.stringify(a))}catch(c){}};function ya(a){try{window.localStorage.removeItem(a.key)}catch(b){}}P.prototype.j=function(){delete N[this.key];Object.keys(N).length||(window.removeEventListener("storage",xa),O=!1)}; | ||
function xa(a){var b=N[a.key];if(b){var c=R(a.oldValue,b.H);a=R(a.newValue,b.H);b.aa("externalSet",a,c)}}function R(a,b){var c;try{c=JSON.parse(a)}catch(d){c={}}return A({},b,c)}var za={};function S(a,b,c){this.f=a;this.timeout=b||T;this.timeZone=c;b=this.b=this.b.bind(this);w(y(a,"sendHitTask"),b);try{this.c=new Intl.DateTimeFormat("en-US",{timeZone:this.timeZone})}catch(d){}this.a=Q(a.get("trackingId"),"session",{hitTime:0,isExpired:!1})} | ||
S.prototype.isExpired=function(a){a=a?a:this.a.get();if(a.isExpired)return!0;var b=new Date,c=(a=a.hitTime)&&new Date(a);return a&&(b-c>6E4*this.timeout||this.c&&this.c.format(b)!=this.c.format(c))?!0:!1};S.prototype.b=function(a){var b=this;return function(c){a(c);var d=b.a.get(),e=b.isExpired(d);c=c.get("sessionControl");d.hitTime=+new Date;if("start"==c||e)d.isExpired=!1;"end"==c&&(d.isExpired=!0);b.a.set(d)}};S.prototype.j=function(){var a=this.b;x(y(this.f,"sendHitTask"),a);this.a.j();delete za[this.f.get("trackingId")]}; | ||
var T=30;function U(a,b){I(a,G.U);window.addEventListener&&(this.a=A({increaseThreshold:20,sessionTimeout:T,fieldsObj:{}},b),this.c=a,this.b=Aa(this),this.f=ra(this.f.bind(this),500),this.s=this.s.bind(this),this.i=Q(a.get("trackingId"),"plugins/max-scroll-tracker"),this.O=new S(a,this.a.sessionTimeout,this.a.timeZone),b=this.s,w(y(a,"set"),b),Ba(this))}function Ba(a){100>(a.i.get()[a.b]||0)&&window.addEventListener("scroll",a.f)} | ||
U.prototype.f=function(){var a=document.documentElement,b=document.body,a=Math.min(100,Math.max(0,Math.round(window.pageYOffset/(Math.max(a.offsetHeight,a.scrollHeight,b.offsetHeight,b.scrollHeight)-window.innerHeight)*100)));if(this.O.isExpired())ya(this.i);else if(b=this.i.get()[this.b]||0,a>b&&(100!=a&&100!=b||window.removeEventListener("scroll",this.f),b=a-b,100==a||b>=this.a.increaseThreshold)){var c={};this.i.set((c[this.b]=a,c));a={transport:"beacon",eventCategory:"Max Scroll",eventAction:"increase", | ||
eventValue:b,eventLabel:String(a),nonInteraction:!0};this.a.maxScrollMetricIndex&&(a["metric"+this.a.maxScrollMetricIndex]=b);this.c.send("event",z(a,this.a.fieldsObj,this.c,this.a.hitFilter))}};U.prototype.s=function(a){var b=this;return function(c,d){a(c,d);var e={};(C(c)?c:(e[c]=d,e)).page&&(c=b.b,b.b=Aa(b),b.b!=c&&Ba(b))}};function Aa(a){a=u(a.c.get("page")||a.c.get("location"));return a.pathname+a.search} | ||
U.prototype.remove=function(){this.O.j();window.removeEventListener("scroll",this.f);var a=this.s;x(y(this.c,"set"),a)};F("maxScrollTracker",U);var Ca={};function V(a,b){I(a,G.V);window.matchMedia&&(this.a=A({changeTemplate:this.changeTemplate,changeTimeout:1E3,fieldsObj:{}},b),C(this.a.definitions)&&(b=this.a.definitions,this.a.definitions=Array.isArray(b)?b:[b],this.b=a,this.c=[],Da(this)))} | ||
function Da(a){a.a.definitions.forEach(function(b){if(b.name&&b.dimensionIndex){var c=Fa(b);a.b.set("dimension"+b.dimensionIndex,c);Ga(a,b)}})}function Fa(a){var b;a.items.forEach(function(a){Ha(a.media).matches&&(b=a)});return b?b.name:"(not set)"} | ||
function Ga(a,b){b.items.forEach(function(c){c=Ha(c.media);var d=ra(function(){var c=Fa(b),d=a.b.get("dimension"+b.dimensionIndex);c!==d&&(a.b.set("dimension"+b.dimensionIndex,c),c={transport:"beacon",eventCategory:b.name,eventAction:"change",eventLabel:a.a.changeTemplate(d,c),nonInteraction:!0},a.b.send("event",z(c,a.a.fieldsObj,a.b,a.a.hitFilter)))},a.a.changeTimeout);c.addListener(d);a.c.push({ca:c,ba:d})})}V.prototype.remove=function(){for(var a=0,b;b=this.c[a];a++)b.ca.removeListener(b.ba)}; | ||
V.prototype.changeTemplate=function(a,b){return a+" \x3d\x3e "+b};F("mediaQueryTracker",V);function Ha(a){return Ca[a]||(Ca[a]=window.matchMedia(a))}function W(a,b){I(a,G.W);window.addEventListener&&(this.a=A({formSelector:"form",shouldTrackOutboundForm:this.shouldTrackOutboundForm,fieldsObj:{},attributePrefix:"ga-"},b),this.b=a,this.c=q("submit",this.a.formSelector,this.f.bind(this)))} | ||
W.prototype.f=function(a,b){var c={transport:"beacon",eventCategory:"Outbound Form",eventAction:"submit",eventLabel:u(b.action).href};this.a.shouldTrackOutboundForm(b,u)&&(navigator.sendBeacon||(a.preventDefault(),c.hitCallback=sa(function(){b.submit()})),a=A({},this.a.fieldsObj,B(b,this.a.attributePrefix)),this.b.send("event",z(c,a,this.b,this.a.hitFilter,b)))};W.prototype.shouldTrackOutboundForm=function(a,b){a=b(a.action);return a.hostname!=location.hostname&&"http"==a.protocol.slice(0,4)}; | ||
W.prototype.remove=function(){this.c.j()};F("outboundFormTracker",W);function X(a,b){var c=this;I(a,G.X);window.addEventListener&&(this.a=A({events:["click"],linkSelector:"a, area",shouldTrackOutboundLink:this.shouldTrackOutboundLink,fieldsObj:{},attributePrefix:"ga-"},b),this.f=a,this.c=this.c.bind(this),this.b={},this.a.events.forEach(function(a){c.b[a]=q(a,c.a.linkSelector,c.c)}))} | ||
X.prototype.c=function(a,b){if(this.a.shouldTrackOutboundLink(b,u)){var c=b.getAttribute("href")||b.getAttribute("xlink:href"),d=u(c),e={transport:"beacon",eventCategory:"Outbound Link",eventAction:a.type,eventLabel:d.href};navigator.sendBeacon||"click"!=a.type||"_blank"==b.target||a.metaKey||a.ctrlKey||a.shiftKey||a.altKey||1<a.which||window.addEventListener("click",function(a){a.defaultPrevented||(a.preventDefault(),e.hitCallback=sa(function(){location.href=c}))});a=A({},this.a.fieldsObj,B(b,this.a.attributePrefix)); | ||
this.f.send("event",z(e,a,this.f,this.a.hitFilter,b))}};X.prototype.shouldTrackOutboundLink=function(a,b){a=a.getAttribute("href")||a.getAttribute("xlink:href");b=b(a);return b.hostname!=location.hostname&&"http"==b.protocol.slice(0,4)};X.prototype.remove=function(){var a=this;Object.keys(this.b).forEach(function(b){a.b[b].j()})};F("outboundLinkTracker",X);var Y=function Ia(b){return b?(b^16*Math.random()>>b/4).toString(16):"10000000-1000-4000-8000-100000000000".replace(/[018]/g,Ia)}(); | ||
function Ja(a,b){I(a,G.Y);if(window.addEventListener){this.a=A({sessionTimeout:T,fieldsObj:{}},b);this.c=a;this.f=null;this.o=this.o.bind(this);this.l=this.l.bind(this);this.C=this.C.bind(this);this.L=this.L.bind(this);this.b=Q(a.get("trackingId"),"plugins/page-visibility-tracker");b=this.L;var c=this.b;(c.a.externalSet=c.a.externalSet||[]).push(b);this.i=new S(a,this.a.sessionTimeout,this.a.timeZone);b=this.o;w(y(a,"set"),b);document.addEventListener("visibilitychange",this.l);window.addEventListener("unload", | ||
this.C);"visible"==document.visibilityState&&this.l()}}f=Ja.prototype;f.l=function(){var a=this.b.get();"visible"==this.f&&"hidden"==a.state&&a.pageId!=Y&&(a.state="visible",a.pageId=Y,this.b.set(a));var b={time:+new Date,state:document.visibilityState,pageId:Y};this.i.isExpired()?"hidden"==document.visibilityState?ya(this.b):(this.c.send("pageview",z({transport:"beacon"},this.a.fieldsObj,this.c,this.a.hitFilter)),this.b.set(b)):(a.pageId==Y&&"visible"==a.state&&Ka(this,a),this.b.set(b));this.f=document.visibilityState}; | ||
function Ka(a,b,c){var d={transport:"beacon",nonInteraction:!0,eventCategory:"Page Visibility",eventAction:"track",eventLabel:"(not set)"};c&&(d.da=+new Date-c);var e=c,e=void 0===e?+new Date:e;c=!a.i.isExpired();b=b.time&&Math.round((e-b.time)/1E3);if(b=c&&0<b?b:0)d.eventValue=b,a.a.visibleMetricIndex&&(d["metric"+a.a.visibleMetricIndex]=b);a.c.send("event",z(d,a.a.fieldsObj,a.c,a.a.hitFilter))} | ||
f.o=function(a){var b=this;return function(c,d){var e={},e=C(c)?c:(e[c]=d,e);e.page&&e.page!==b.c.get("page")&&"visible"==b.f&&b.l();a(c,d)}};f.L=function(a,b){a.time!=b.time&&b.pageId==Y&&"visible"==b.state&&Ka(this,b,a.time)};f.C=function(){"hidden"!=this.f&&this.l()};f.remove=function(){this.i.j();var a=this.o;x(y(this.c,"set"),a);window.removeEventListener("unload",this.C);document.removeEventListener("visibilitychange",this.l)};F("pageVisibilityTracker",Ja); | ||
function La(a,b){I(a,G.Z);window.addEventListener&&(this.a=A({fieldsObj:{},hitFilter:null},b),this.b=a,this.m=this.m.bind(this),this.G=this.G.bind(this),this.A=this.A.bind(this),this.u=this.u.bind(this),this.v=this.v.bind(this),this.B=this.B.bind(this),"complete"!=document.readyState?window.addEventListener("load",this.m):this.m())}f=La.prototype; | ||
f.m=function(){if(window.FB)try{window.FB.Event.subscribe("edge.create",this.v),window.FB.Event.subscribe("edge.remove",this.B)}catch(a){}window.twttr&&this.G()};f.G=function(){var a=this;try{window.twttr.ready(function(){window.twttr.events.bind("tweet",a.A);window.twttr.events.bind("follow",a.u)})}catch(b){}};function Ma(a){try{window.twttr.ready(function(){window.twttr.events.unbind("tweet",a.A);window.twttr.events.unbind("follow",a.u)})}catch(b){}} | ||
f.A=function(a){"tweet"==a.region&&(a={transport:"beacon",socialNetwork:"Twitter",socialAction:"tweet",socialTarget:a.data.url||a.target.getAttribute("data-url")||location.href},this.b.send("social",z(a,this.a.fieldsObj,this.b,this.a.hitFilter)))};f.u=function(a){"follow"==a.region&&(a={transport:"beacon",socialNetwork:"Twitter",socialAction:"follow",socialTarget:a.data.screen_name||a.target.getAttribute("data-screen-name")},this.b.send("social",z(a,this.a.fieldsObj,this.b,this.a.hitFilter)))}; | ||
f.v=function(a){this.b.send("social",z({transport:"beacon",socialNetwork:"Facebook",socialAction:"like",socialTarget:a},this.a.fieldsObj,this.b,this.a.hitFilter))};f.B=function(a){this.b.send("social",z({transport:"beacon",socialNetwork:"Facebook",socialAction:"unlike",socialTarget:a},this.a.fieldsObj,this.b,this.a.hitFilter))};f.remove=function(){window.removeEventListener("load",this.m);try{window.FB.Event.unsubscribe("edge.create",this.v),window.FB.Event.unsubscribe("edge.remove",this.B)}catch(a){}Ma(this)}; | ||
F("socialWidgetTracker",La);function Na(a,b){I(a,G.$);history.pushState&&window.addEventListener&&(this.a=A({shouldTrackUrlChange:this.shouldTrackUrlChange,trackReplaceState:!1,fieldsObj:{},hitFilter:null},b),this.b=a,this.c=location.pathname+location.search,this.D=this.D.bind(this),this.F=this.F.bind(this),this.w=this.w.bind(this),a=this.D,w(y(history,"pushState"),a),a=this.F,w(y(history,"replaceState"),a),window.addEventListener("popstate",this.w))}f=Na.prototype; | ||
f.D=function(a){var b=this;return function(c){for(var d=[],e=0;e<arguments.length;++e)d[e-0]=arguments[e];a.apply(null,[].concat(n(d)));Z(b,!0)}};f.F=function(a){var b=this;return function(c){for(var d=[],e=0;e<arguments.length;++e)d[e-0]=arguments[e];a.apply(null,[].concat(n(d)));Z(b,!1)}};f.w=function(){Z(this,!0)}; | ||
function Z(a,b){setTimeout(function(){var c=a.c,d=location.pathname+location.search;c!=d&&a.a.shouldTrackUrlChange.call(a,d,c)&&(a.c=d,a.b.set({page:d,title:document.title}),(b||a.a.trackReplaceState)&&a.b.send("pageview",z({transport:"beacon"},a.a.fieldsObj,a.b,a.a.hitFilter)))},0)}f.shouldTrackUrlChange=function(a,b){return!(!a||!b)};f.remove=function(){var a=this.D;x(y(history,"pushState"),a);a=this.F;x(y(history,"replaceState"),a);window.removeEventListener("popstate",this.w)}; | ||
F("urlChangeTracker",Na);})(); | ||
(function(){var f,aa="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(c.get||c.set)throw new TypeError("ES3 does not support getters and setters.");a!=Array.prototype&&a!=Object.prototype&&(a[b]=c.value)},k="undefined"!=typeof window&&window===this?this:"undefined"!=typeof global&&null!=global?global:this;function ba(){ba=function(){};k.Symbol||(k.Symbol=ca)}var da=0;function ca(a){return"jscomp_symbol_"+(a||"")+da++} | ||
function l(){ba();var a=k.Symbol.iterator;a||(a=k.Symbol.iterator=k.Symbol("iterator"));"function"!=typeof Array.prototype[a]&&aa(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return ea(this)}});l=function(){}}function ea(a){var b=0;return fa(function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}})}function fa(a){l();a={next:a};a[k.Symbol.iterator]=function(){return this};return a} | ||
function m(a){if(!(a instanceof Array)){l();var b=a[Symbol.iterator];a=b?b.call(a):ea(a);for(var c=[];!(b=a.next()).done;)c.push(b.value);a=c}return a}function ha(a,b){function c(){}c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a;for(var d in b)if(Object.defineProperties){var e=Object.getOwnPropertyDescriptor(b,d);e&&Object.defineProperty(a,d,e)}else a[d]=b[d]} | ||
var n=window.Element.prototype,ia=n.matches||n.matchesSelector||n.webkitMatchesSelector||n.mozMatchesSelector||n.msMatchesSelector||n.oMatchesSelector;function ja(a,b){if(a&&1==a.nodeType&&b){if("string"==typeof b||1==b.nodeType)return a==b||ka(a,b);if("length"in b)for(var c=0,d;d=b[c];c++)if(a==d||ka(a,d))return!0}return!1}function ka(a,b){if("string"!=typeof b)return!1;if(ia)return ia.call(a,b);b=a.parentNode.querySelectorAll(b);for(var c=0,d;d=b[c];c++)if(d==a)return!0;return!1} | ||
function la(a){for(var b=[];a&&a.parentNode&&1==a.parentNode.nodeType;)a=a.parentNode,b.push(a);return b} | ||
function p(a,b,c){function d(a){var d;if(h.composed&&"function"==typeof a.composedPath)for(var e=a.composedPath(),g=0,F;F=e[g];g++)1==F.nodeType&&ja(F,b)&&(d=F);else a:{if((d=a.target)&&1==d.nodeType&&b)for(d=[d].concat(la(d)),e=0;g=d[e];e++)if(ja(g,b)){d=g;break a}d=void 0}d&&c.call(d,a,d)}var e=document,h={composed:!0,R:!0},h=void 0===h?{}:h;e.addEventListener(a,d,h.R);return{j:function(){e.removeEventListener(a,d,h.R)}}} | ||
function ma(a){var b={};if(!a||1!=a.nodeType)return b;a=a.attributes;if(!a.length)return{};for(var c=0,d;d=a[c];c++)b[d.name]=d.value;return b}var na=/:(80|443)$/,q=document.createElement("a"),r={}; | ||
function t(a){a=a&&"."!=a?a:location.href;if(r[a])return r[a];q.href=a;if("."==a.charAt(0)||"/"==a.charAt(0))return t(q.href);var b="80"==q.port||"443"==q.port?"":q.port,b="0"==b?"":b,c=q.host.replace(na,"");return r[a]={hash:q.hash,host:c,hostname:q.hostname,href:q.href,origin:q.origin?q.origin:q.protocol+"//"+c,pathname:"/"==q.pathname.charAt(0)?q.pathname:"/"+q.pathname,port:b,protocol:q.protocol,search:q.search}}var u=[]; | ||
function oa(a,b){var c=this;this.context=a;this.O=b;this.f=(this.c=/Task$/.test(b))?a.get(b):a[b];this.b=[];this.a=[];this.i=function(a){for(var b=[],d=0;d<arguments.length;++d)b[d-0]=arguments[d];return c.a[c.a.length-1].apply(null,[].concat(m(b)))};this.c?a.set(b,this.i):a[b]=this.i}function v(a,b){a.b.push(b);pa(a)}function w(a,b){b=a.b.indexOf(b);-1<b&&(a.b.splice(b,1),0<a.b.length?pa(a):a.j())} | ||
function pa(a){a.a=[];for(var b,c=0;b=a.b[c];c++){var d=a.a[c-1]||a.f.bind(a.context);a.a.push(b(d))}}oa.prototype.j=function(){var a=u.indexOf(this);-1<a&&(u.splice(a,1),this.c?this.context.set(this.O,this.f):this.context[this.O]=this.f)};function x(a,b){var c=u.filter(function(c){return c.context==a&&c.O==b})[0];c||(c=new oa(a,b),u.push(c));return c} | ||
function y(a,b,c,d,e){if("function"==typeof d){var h=c.get("buildHitTask");return{buildHitTask:function(c){c.set(a,null,!0);c.set(b,null,!0);d(c,e);h(c)}}}return z({},a,b)}function A(a,b){var c=ma(a),d={};Object.keys(c).forEach(function(a){if(!a.indexOf(b)&&a!=b+"on"){var e=c[a];"true"==e&&(e=!0);"false"==e&&(e=!1);a=qa(a.slice(b.length));d[a]=e}});return d} | ||
function ra(a){"loading"==document.readyState?document.addEventListener("DOMContentLoaded",function c(){document.removeEventListener("DOMContentLoaded",c);a()}):a()}function sa(a,b){var c;return function(d){for(var e=[],h=0;h<arguments.length;++h)e[h-0]=arguments[h];clearTimeout(c);c=setTimeout(function(){return a.apply(null,[].concat(m(e)))},b)}}function ta(a){function b(){c||(c=!0,a())}var c=!1;setTimeout(b,2E3);return b} | ||
var z=Object.assign||function(a,b){for(var c=[],d=1;d<arguments.length;++d)c[d-1]=arguments[d];for(var d=0,e=c.length;d<e;d++){var h=Object(c[d]),g;for(g in h)Object.prototype.hasOwnProperty.call(h,g)&&(a[g]=h[g])}return a};function qa(a){return a.replace(/[\-\_]+(\w?)/g,function(a,c){return c.toUpperCase()})}function B(a){return"object"==typeof a&&null!==a} | ||
function C(a,b){var c=window.GoogleAnalyticsObject||"ga";window[c]=window[c]||function(a){for(var b=[],d=0;d<arguments.length;++d)b[d-0]=arguments[d];(window[c].q=window[c].q||[]).push(b)};window.gaDevIds=window.gaDevIds||[];0>window.gaDevIds.indexOf("i5iSjo")&&window.gaDevIds.push("i5iSjo");window[c]("provide",a,b);window.gaplugins=window.gaplugins||{};window.gaplugins[a.charAt(0).toUpperCase()+a.slice(1)]=b}var D={S:1,T:2,U:3,W:4,X:5,Y:6,Z:7,$:8,aa:9,V:10},G=Object.keys(D).length; | ||
function H(a,b){a.set("\x26_av","2.1.0");var c=a.get("\x26_au"),c=parseInt(c||"0",16).toString(2);if(c.length<G)for(var d=G-c.length;d;)c="0"+c,d--;b=G-b;c=c.substr(0,b)+1+c.substr(b+1);a.set("\x26_au",parseInt(c||"0",2).toString(16))}function I(a,b){H(a,D.S);this.a=z({},b);this.i=a;this.b=this.a.stripQuery&&this.a.queryDimensionIndex?"dimension"+this.a.queryDimensionIndex:null;this.f=this.f.bind(this);this.c=this.c.bind(this);b=this.f;v(x(a,"get"),b);b=this.c;v(x(a,"buildHitTask"),b)} | ||
I.prototype.f=function(a){var b=this;return function(c){if("page"==c||c==b.b){var d={location:a("location"),page:a("page")};return ua(b,d)[c]}return a(c)}};I.prototype.c=function(a){var b=this;return function(c){var d=ua(b,{location:c.get("location"),page:c.get("page")});c.set(d,null,!0);a(c)}}; | ||
function ua(a,b){var c=t(b.page||b.location),d=c.pathname;if(a.a.indexFilename){var e=d.split("/");a.a.indexFilename==e[e.length-1]&&(e[e.length-1]="",d=e.join("/"))}"remove"==a.a.trailingSlash?d=d.replace(/\/+$/,""):"add"==a.a.trailingSlash&&(/\.\w+$/.test(d)||"/"==d.substr(-1)||(d+="/"));d={page:d+(a.a.stripQuery?"":c.search)};b.location&&(d.location=b.location);a.b&&(d[a.b]=c.search.slice(1)||"(not set)");return"function"==typeof a.a.urlFieldsFilter?(b=a.a.urlFieldsFilter(d,t),c={},c.page=b.page, | ||
c.location=b.location,c[a.b]=b[a.b],c):d}I.prototype.remove=function(){var a=this.f;w(x(this.i,"get"),a);a=this.c;w(x(this.i,"buildHitTask"),a)};C("cleanUrlTracker",I);function J(a,b){var c=this;H(a,D.T);if(window.addEventListener){this.a=z({events:["click"],fieldsObj:{},attributePrefix:"ga-"},b);this.f=a;this.c=this.c.bind(this);var d="["+this.a.attributePrefix+"on]";this.b={};this.a.events.forEach(function(a){c.b[a]=p(a,d,c.c)})}} | ||
J.prototype.c=function(a,b){var c=this.a.attributePrefix;a.type==b.getAttribute(c+"on")&&(a=A(b,c),c=z({},this.a.fieldsObj,a),this.f.send(a.hitType||"event",y({transport:"beacon"},c,this.f,this.a.hitFilter,b)))};J.prototype.remove=function(){var a=this;Object.keys(this.b).forEach(function(b){a.b[b].j()})};C("eventTracker",J); | ||
function va(a,b){var c=this;H(a,D.U);window.IntersectionObserver&&window.MutationObserver&&(this.a=z({rootMargin:"0px",fieldsObj:{},attributePrefix:"ga-"},b),this.c=a,this.L=this.L.bind(this),this.N=this.N.bind(this),this.J=this.J.bind(this),this.K=this.K.bind(this),this.b=null,this.items=[],this.h={},this.g={},ra(function(){return c.observeElements(c.a.elements)}))}f=va.prototype; | ||
f.observeElements=function(a){var b=this;a=K(this,a);this.items=this.items.concat(a.items);this.h=z({},a.h,this.h);this.g=z({},a.g,this.g);a.items.forEach(function(a){var c=b.g[a.threshold]=b.g[a.threshold]||new IntersectionObserver(b.N,{rootMargin:b.a.rootMargin,threshold:[+a.threshold]});(a=b.h[a.id]||(b.h[a.id]=document.getElementById(a.id)))&&c.observe(a)});this.b||(this.b=new MutationObserver(this.L),this.b.observe(document.body,{childList:!0,subtree:!0}));requestAnimationFrame(function(){})}; | ||
f.unobserveElements=function(a){var b=[],c=[];this.items.forEach(function(d){a.some(function(a){a=wa(a);return a.id===d.id&&a.threshold===d.threshold&&a.trackFirstImpressionOnly===d.trackFirstImpressionOnly})?c.push(d):b.push(d)});if(b.length){var d=K(this,b),e=K(this,c);this.items=d.items;this.h=d.h;this.g=d.g;c.forEach(function(a){if(!d.h[a.id]){var b=e.g[a.threshold],c=e.h[a.id];c&&b.unobserve(c);d.g[a.threshold]||e.g[a.threshold].disconnect()}})}else this.unobserveAllElements()}; | ||
f.unobserveAllElements=function(){var a=this;Object.keys(this.g).forEach(function(b){a.g[b].disconnect()});this.b.disconnect();this.b=null;this.items=[];this.h={};this.g={}};function K(a,b){var c=[],d={},e={};b.length&&b.forEach(function(b){b=wa(b);c.push(b);e[b.id]=a.h[b.id]||null;d[b.threshold]=a.g[b.threshold]||null});return{items:c,h:e,g:d}}f.L=function(a){for(var b=0,c;c=a[b];b++){for(var d=0,e;e=c.removedNodes[d];d++)L(this,e,this.K);for(d=0;e=c.addedNodes[d];d++)L(this,e,this.J)}}; | ||
function L(a,b,c){1==b.nodeType&&b.id in a.h&&c(b.id);for(var d=0,e;e=b.childNodes[d];d++)L(a,e,c)} | ||
f.N=function(a){for(var b=[],c=0,d;d=a[c];c++)for(var e=0,h;h=this.items[e];e++){var g;if(g=d.target.id===h.id)(g=h.threshold)?g=d.intersectionRatio>=g:(g=d.intersectionRect,g=0<g.top||0<g.bottom||0<g.left||0<g.right);if(g){var E=h.id;g=document.getElementById(E);var E={transport:"beacon",eventCategory:"Viewport",eventAction:"impression",eventLabel:E,nonInteraction:!0},Ga=z({},this.a.fieldsObj,A(g,this.a.attributePrefix));this.c.send("event",y(E,Ga,this.c,this.a.hitFilter,g));h.trackFirstImpressionOnly&& | ||
b.push(h)}}b.length&&this.unobserveElements(b)};f.J=function(a){var b=this,c=this.h[a]=document.getElementById(a);this.items.forEach(function(d){a==d.id&&b.g[d.threshold].observe(c)})};f.K=function(a){var b=this,c=this.h[a];this.items.forEach(function(d){a==d.id&&b.g[d.threshold].unobserve(c)});this.h[a]=null};f.remove=function(){this.unobserveAllElements()};C("impressionTracker",va);function wa(a){"string"==typeof a&&(a={id:a});return z({threshold:0,trackFirstImpressionOnly:!0},a)} | ||
function xa(){this.a={}}xa.prototype.ba=function(a,b){for(var c=[],d=1;d<arguments.length;++d)c[d-1]=arguments[d];(this.a[a]=this.a[a]||[]).forEach(function(a){return a.apply(null,[].concat(m(c)))})};var M={},N=!1,O;function P(a,b){b=void 0===b?{}:b;this.a={};this.b=a;this.v=b;this.l=null}ha(P,xa);function Q(a,b,c){a=["autotrack",a,b].join(":");M[a]||(M[a]=new P(a,c),N||(window.addEventListener("storage",ya),N=!0));return M[a]} | ||
function R(){if(null!=O)return O;try{window.localStorage.setItem("autotrack","autotrack"),window.localStorage.removeItem("autotrack"),O=!0}catch(a){O=!1}return O}P.prototype.get=function(){if(this.l)return this.l;if(R())try{this.l=S(window.localStorage.getItem(this.b))}catch(a){}return this.l=z({},this.v,this.l)};P.prototype.set=function(a){this.l=z({},this.v,this.l,a);if(R())try{var b=JSON.stringify(this.l);window.localStorage.setItem(this.b,b)}catch(c){}}; | ||
function za(a){a.l={};if(R())try{window.localStorage.removeItem(a.b)}catch(b){}}P.prototype.j=function(){delete M[this.b];Object.keys(M).length||(window.removeEventListener("storage",ya),N=!1)};function ya(a){var b=M[a.key];if(b){var c=z({},b.v,S(a.oldValue));a=z({},b.v,S(a.newValue));b.l=a;b.ba("externalSet",a,c)}}function S(a){var b={};if(a)try{b=JSON.parse(a)}catch(c){}return b}var Aa={}; | ||
function T(a,b,c){this.f=a;this.timeout=b||U;this.timeZone=c;b=this.b=this.b.bind(this);v(x(a,"sendHitTask"),b);try{this.c=new Intl.DateTimeFormat("en-US",{timeZone:this.timeZone})}catch(d){}this.a=Q(a.get("trackingId"),"session",{hitTime:0,isExpired:!1})}T.prototype.isExpired=function(a){a=a?a:this.a.get();if(a.isExpired)return!0;var b=new Date,c=(a=a.hitTime)&&new Date(a);return a&&(b-c>6E4*this.timeout||this.c&&this.c.format(b)!=this.c.format(c))?!0:!1}; | ||
T.prototype.b=function(a){var b=this;return function(c){a(c);var d=b.a.get(),e=b.isExpired(d);c=c.get("sessionControl");d.hitTime=+new Date;if("start"==c||e)d.isExpired=!1;"end"==c&&(d.isExpired=!0);b.a.set(d)}};T.prototype.j=function(){var a=this.b;w(x(this.f,"sendHitTask"),a);this.a.j();delete Aa[this.f.get("trackingId")]};var U=30; | ||
function V(a,b){H(a,D.V);window.addEventListener&&(this.a=z({increaseThreshold:20,sessionTimeout:U,fieldsObj:{}},b),this.c=a,this.b=Ba(this),this.f=sa(this.f.bind(this),500),this.m=this.m.bind(this),this.i=Q(a.get("trackingId"),"plugins/max-scroll-tracker"),this.P=new T(a,this.a.sessionTimeout,this.a.timeZone),b=this.m,v(x(a,"set"),b),Ca(this))}function Ca(a){100>(a.i.get()[a.b]||0)&&window.addEventListener("scroll",a.f)} | ||
V.prototype.f=function(){var a=document.documentElement,b=document.body,a=Math.min(100,Math.max(0,Math.round(window.pageYOffset/(Math.max(a.offsetHeight,a.scrollHeight,b.offsetHeight,b.scrollHeight)-window.innerHeight)*100)));if(this.P.isExpired())za(this.i);else if(b=this.i.get()[this.b]||0,a>b&&(100!=a&&100!=b||window.removeEventListener("scroll",this.f),b=a-b,100==a||b>=this.a.increaseThreshold)){var c={};this.i.set((c[this.b]=a,c));a={transport:"beacon",eventCategory:"Max Scroll",eventAction:"increase", | ||
eventValue:b,eventLabel:String(a),nonInteraction:!0};this.a.maxScrollMetricIndex&&(a["metric"+this.a.maxScrollMetricIndex]=b);this.c.send("event",y(a,this.a.fieldsObj,this.c,this.a.hitFilter))}};V.prototype.m=function(a){var b=this;return function(c,d){a(c,d);var e={};(B(c)?c:(e[c]=d,e)).page&&(c=b.b,b.b=Ba(b),b.b!=c&&Ca(b))}};function Ba(a){a=t(a.c.get("page")||a.c.get("location"));return a.pathname+a.search} | ||
V.prototype.remove=function(){this.P.j();window.removeEventListener("scroll",this.f);var a=this.m;w(x(this.c,"set"),a)};C("maxScrollTracker",V);var Da={};function W(a,b){H(a,D.W);window.matchMedia&&(this.a=z({changeTemplate:this.changeTemplate,changeTimeout:1E3,fieldsObj:{}},b),B(this.a.definitions)&&(b=this.a.definitions,this.a.definitions=Array.isArray(b)?b:[b],this.b=a,this.c=[],Ea(this)))} | ||
function Ea(a){a.a.definitions.forEach(function(b){if(b.name&&b.dimensionIndex){var c=Fa(b);a.b.set("dimension"+b.dimensionIndex,c);Ha(a,b)}})}function Fa(a){var b;a.items.forEach(function(a){Ia(a.media).matches&&(b=a)});return b?b.name:"(not set)"} | ||
function Ha(a,b){b.items.forEach(function(c){c=Ia(c.media);var d=sa(function(){var c=Fa(b),d=a.b.get("dimension"+b.dimensionIndex);c!==d&&(a.b.set("dimension"+b.dimensionIndex,c),c={transport:"beacon",eventCategory:b.name,eventAction:"change",eventLabel:a.a.changeTemplate(d,c),nonInteraction:!0},a.b.send("event",y(c,a.a.fieldsObj,a.b,a.a.hitFilter)))},a.a.changeTimeout);c.addListener(d);a.c.push({da:c,ca:d})})}W.prototype.remove=function(){for(var a=0,b;b=this.c[a];a++)b.da.removeListener(b.ca)}; | ||
W.prototype.changeTemplate=function(a,b){return a+" \x3d\x3e "+b};C("mediaQueryTracker",W);function Ia(a){return Da[a]||(Da[a]=window.matchMedia(a))}function X(a,b){H(a,D.X);window.addEventListener&&(this.a=z({formSelector:"form",shouldTrackOutboundForm:this.shouldTrackOutboundForm,fieldsObj:{},attributePrefix:"ga-"},b),this.b=a,this.c=p("submit",this.a.formSelector,this.f.bind(this)))} | ||
X.prototype.f=function(a,b){var c={transport:"beacon",eventCategory:"Outbound Form",eventAction:"submit",eventLabel:t(b.action).href};this.a.shouldTrackOutboundForm(b,t)&&(navigator.sendBeacon||(a.preventDefault(),c.hitCallback=ta(function(){b.submit()})),a=z({},this.a.fieldsObj,A(b,this.a.attributePrefix)),this.b.send("event",y(c,a,this.b,this.a.hitFilter,b)))};X.prototype.shouldTrackOutboundForm=function(a,b){a=b(a.action);return a.hostname!=location.hostname&&"http"==a.protocol.slice(0,4)}; | ||
X.prototype.remove=function(){this.c.j()};C("outboundFormTracker",X);function Y(a,b){var c=this;H(a,D.Y);window.addEventListener&&(this.a=z({events:["click"],linkSelector:"a, area",shouldTrackOutboundLink:this.shouldTrackOutboundLink,fieldsObj:{},attributePrefix:"ga-"},b),this.f=a,this.c=this.c.bind(this),this.b={},this.a.events.forEach(function(a){c.b[a]=p(a,c.a.linkSelector,c.c)}))} | ||
Y.prototype.c=function(a,b){if(this.a.shouldTrackOutboundLink(b,t)){var c=b.getAttribute("href")||b.getAttribute("xlink:href"),d=t(c),e={transport:"beacon",eventCategory:"Outbound Link",eventAction:a.type,eventLabel:d.href};navigator.sendBeacon||"click"!=a.type||"_blank"==b.target||a.metaKey||a.ctrlKey||a.shiftKey||a.altKey||1<a.which||window.addEventListener("click",function(a){a.defaultPrevented||(a.preventDefault(),e.hitCallback=ta(function(){location.href=c}))});a=z({},this.a.fieldsObj,A(b,this.a.attributePrefix)); | ||
this.f.send("event",y(e,a,this.f,this.a.hitFilter,b))}};Y.prototype.shouldTrackOutboundLink=function(a,b){a=a.getAttribute("href")||a.getAttribute("xlink:href");b=b(a);return b.hostname!=location.hostname&&"http"==b.protocol.slice(0,4)};Y.prototype.remove=function(){var a=this;Object.keys(this.b).forEach(function(b){a.b[b].j()})};C("outboundLinkTracker",Y);var Z=function Ja(b){return b?(b^16*Math.random()>>b/4).toString(16):"10000000-1000-4000-8000-100000000000".replace(/[018]/g,Ja)}(); | ||
function Ka(a,b){H(a,D.Z);if(document.visibilityState){this.a=z({sessionTimeout:U,visibleThreshold:5E3,fieldsObj:{}},b);this.c=a;this.i=this.f=null;this.u=this.u.bind(this);this.o=this.o.bind(this);this.F=this.F.bind(this);this.M=this.M.bind(this);this.b=Q(a.get("trackingId"),"plugins/page-visibility-tracker");b=this.M;var c=this.b;(c.a.externalSet=c.a.externalSet||[]).push(b);this.m=new T(a,this.a.sessionTimeout,this.a.timeZone);b=this.u;v(x(a,"set"),b);window.addEventListener("unload",this.F);document.addEventListener("visibilitychange", | ||
this.o);"visible"==document.visibilityState&&this.o()}}f=Ka.prototype; | ||
f.o=function(){var a=this;if("visible"==document.visibilityState||"hidden"==document.visibilityState){var b=La(this,this.b.get()),c={time:+new Date,state:document.visibilityState,pageId:Z};this.i&&"hidden"==document.visibilityState&&clearTimeout(this.i);this.m.isExpired()?"hidden"==this.f&&"visible"==document.visibilityState?(clearTimeout(this.i),this.i=setTimeout(function(){a.c.send("pageview",y({transport:"beacon",queueTime:+new Date-c.time},a.a.fieldsObj,a.c,a.a.hitFilter));a.b.set(c)},this.a.visibleThreshold)): | ||
"hidden"==document.visibilityState&&za(this.b):(b.pageId==Z&&"visible"==b.state&&Ma(this,b),this.b.set(c));this.f=document.visibilityState}};function La(a,b){"visible"==a.f&&"hidden"==b.state&&b.pageId!=Z&&(b.state="visible",b.pageId=Z,a.b.set(b));return b} | ||
function Ma(a,b,c){var d=c,d=void 0===d?+new Date:d,e=!a.m.isExpired();b=b.time&&d-b.time;(e=e&&0<b?b:0)&&e>=a.a.visibleThreshold&&(e=Math.round(e/1E3),b={transport:"beacon",nonInteraction:!0,eventCategory:"Page Visibility",eventAction:"track",eventValue:e,eventLabel:"(not set)"},c&&(b.queueTime=+new Date-c),a.a.visibleMetricIndex&&(b["metric"+a.a.visibleMetricIndex]=e),a.c.send("event",y(b,a.a.fieldsObj,a.c,a.a.hitFilter)))} | ||
f.u=function(a){var b=this;return function(c,d){var e={},e=B(c)?c:(e[c]=d,e);e.page&&e.page!==b.c.get("page")&&"visible"==b.f&&b.o();a(c,d)}};f.M=function(a,b){a.time!=b.time&&b.pageId==Z&&"visible"==b.state&&Ma(this,b,a.time)};f.F=function(){"hidden"!=this.f&&this.o()};f.remove=function(){this.b.j();this.m.j();var a=this.u;w(x(this.c,"set"),a);window.removeEventListener("unload",this.F);document.removeEventListener("visibilitychange",this.o)};C("pageVisibilityTracker",Ka); | ||
function Na(a,b){H(a,D.$);window.addEventListener&&(this.a=z({fieldsObj:{},hitFilter:null},b),this.b=a,this.s=this.s.bind(this),this.I=this.I.bind(this),this.C=this.C.bind(this),this.w=this.w.bind(this),this.A=this.A.bind(this),this.D=this.D.bind(this),"complete"!=document.readyState?window.addEventListener("load",this.s):this.s())}f=Na.prototype; | ||
f.s=function(){if(window.FB)try{window.FB.Event.subscribe("edge.create",this.A),window.FB.Event.subscribe("edge.remove",this.D)}catch(a){}window.twttr&&this.I()};f.I=function(){var a=this;try{window.twttr.ready(function(){window.twttr.events.bind("tweet",a.C);window.twttr.events.bind("follow",a.w)})}catch(b){}};function Oa(a){try{window.twttr.ready(function(){window.twttr.events.unbind("tweet",a.C);window.twttr.events.unbind("follow",a.w)})}catch(b){}} | ||
f.C=function(a){"tweet"==a.region&&(a={transport:"beacon",socialNetwork:"Twitter",socialAction:"tweet",socialTarget:a.data.url||a.target.getAttribute("data-url")||location.href},this.b.send("social",y(a,this.a.fieldsObj,this.b,this.a.hitFilter)))};f.w=function(a){"follow"==a.region&&(a={transport:"beacon",socialNetwork:"Twitter",socialAction:"follow",socialTarget:a.data.screen_name||a.target.getAttribute("data-screen-name")},this.b.send("social",y(a,this.a.fieldsObj,this.b,this.a.hitFilter)))}; | ||
f.A=function(a){this.b.send("social",y({transport:"beacon",socialNetwork:"Facebook",socialAction:"like",socialTarget:a},this.a.fieldsObj,this.b,this.a.hitFilter))};f.D=function(a){this.b.send("social",y({transport:"beacon",socialNetwork:"Facebook",socialAction:"unlike",socialTarget:a},this.a.fieldsObj,this.b,this.a.hitFilter))};f.remove=function(){window.removeEventListener("load",this.s);try{window.FB.Event.unsubscribe("edge.create",this.A),window.FB.Event.unsubscribe("edge.remove",this.D)}catch(a){}Oa(this)}; | ||
C("socialWidgetTracker",Na);function Pa(a,b){H(a,D.aa);history.pushState&&window.addEventListener&&(this.a=z({shouldTrackUrlChange:this.shouldTrackUrlChange,trackReplaceState:!1,fieldsObj:{},hitFilter:null},b),this.b=a,this.c=location.pathname+location.search,this.G=this.G.bind(this),this.H=this.H.bind(this),this.B=this.B.bind(this),a=this.G,v(x(history,"pushState"),a),a=this.H,v(x(history,"replaceState"),a),window.addEventListener("popstate",this.B))}f=Pa.prototype; | ||
f.G=function(a){var b=this;return function(c){for(var d=[],e=0;e<arguments.length;++e)d[e-0]=arguments[e];a.apply(null,[].concat(m(d)));Qa(b,!0)}};f.H=function(a){var b=this;return function(c){for(var d=[],e=0;e<arguments.length;++e)d[e-0]=arguments[e];a.apply(null,[].concat(m(d)));Qa(b,!1)}};f.B=function(){Qa(this,!0)}; | ||
function Qa(a,b){setTimeout(function(){var c=a.c,d=location.pathname+location.search;c!=d&&a.a.shouldTrackUrlChange.call(a,d,c)&&(a.c=d,a.b.set({page:d,title:document.title}),(b||a.a.trackReplaceState)&&a.b.send("pageview",y({transport:"beacon"},a.a.fieldsObj,a.b,a.a.hitFilter)))},0)}f.shouldTrackUrlChange=function(a,b){return!(!a||!b)};f.remove=function(){var a=this.G;w(x(history,"pushState"),a);a=this.H;w(x(history,"replaceState"),a);window.removeEventListener("popstate",this.B)}; | ||
C("urlChangeTracker",Pa);})(); | ||
//# sourceMappingURL=autotrack.js.map |
@@ -90,3 +90,3 @@ /** | ||
}); | ||
source = path.relative('.', path.resolve(__dirname, source)); | ||
source = path.relative('.', path.resolve(__dirname, '..', source)); | ||
return {type, line, column, source, desc: item.description}; | ||
@@ -93,0 +93,0 @@ }; |
@@ -5,2 +5,7 @@ # Changelog | ||
### 2.1.0 (2017-03-06) | ||
- Fix a double-pageview bug on pageload after session timeout (#150). | ||
- Add a visibleThreshold option to pageVisibilityTracker (#148). | ||
### 2.0.4 (2017-02-24) | ||
@@ -7,0 +12,0 @@ |
@@ -87,2 +87,10 @@ # `pageVisibilityTracker` | ||
<tr valign="top"> | ||
<td><code>visibleThreshold</code></td> | ||
<td><code>number</code></td> | ||
<td> | ||
The time in milliseconds to wait before sending a Page Visibility event (or a new pageview in the case of a session timeout). This helps prevent unwanted events from being sent in cases where a user is quickly switching tabs or closing tabs they no longer want open.<br> | ||
<strong>Default:</strong> <code>5000</code> | ||
</td> | ||
</tr> | ||
<tr valign="top"> | ||
<td><code>visibleMetricIndex</code></td> | ||
@@ -89,0 +97,0 @@ <td><code>number</code></td> |
@@ -88,3 +88,3 @@ /** | ||
return webpack({ | ||
entry: glob.sync('./test/unit/*-test.js'), | ||
entry: glob.sync('./test/unit/**/*-test.js'), | ||
output: { | ||
@@ -175,2 +175,3 @@ path: 'test/unit', | ||
verbose: true, | ||
verboseDebugging: true, | ||
}; | ||
@@ -177,0 +178,0 @@ sauceConnectLauncher(opts, (err, sauceConnectProcess) => { |
@@ -18,3 +18,3 @@ /** | ||
export const VERSION = '2.0.4'; | ||
export const VERSION = '2.1.0'; | ||
export const DEV_ID = 'i5iSjo'; | ||
@@ -21,0 +21,0 @@ |
/** | ||
* Fields used by analytics.js. | ||
* This is not an extensive list of all anlaytics.js fields, just the ones | ||
* referenced by autotrack plugins. | ||
* @typedef {{ | ||
* allowAnchor: (boolean|undefined), | ||
* allowLinker: (boolean|undefined), | ||
* alwaysSendReferrer: (boolean|undefined), | ||
* anonymizeIp: (boolean|undefined), | ||
* appId: (string|undefined), | ||
* appInstallerId: (string|undefined), | ||
* appName: (string|undefined), | ||
* appVersion: (string|undefined), | ||
* buildHitTask: (Function|undefined), | ||
* campaignContent: (string|undefined), | ||
* campaignId: (string|undefined), | ||
* campaignKeyword: (string|undefined), | ||
* campaignMedium: (string|undefined), | ||
* campaignName: (string|undefined), | ||
* campaignSource: (string|undefined), | ||
* checkProtocolTask: (Function|undefined), | ||
* checkStorageTask: (Function|undefined), | ||
* clientId: (string|undefined), | ||
* contentGroup: (string|undefined), | ||
* cookieDomain: (string|undefined), | ||
* cookieExpires: (number|undefined), | ||
* cookieName: (string|undefined), | ||
* cookiePath: (string|undefined), | ||
* currencyCode: (string|undefined), | ||
* dataSource: (string|undefined), | ||
* devIdTask: (Function|undefined), | ||
* displayFeaturesTask: (Function|undefined), | ||
* encoding: (string|undefined), | ||
* eventAction: (string|undefined), | ||
@@ -11,12 +36,53 @@ * eventCategory: (string|undefined), | ||
* eventValue: (number|undefined), | ||
* exDescription: (string|undefined), | ||
* exFatal: (boolean|undefined), | ||
* exp: (string|undefined), | ||
* expId: (string|undefined), | ||
* expVar: (string|undefined), | ||
* flashVersion: (string|undefined), | ||
* forceSSL: (boolean|undefined), | ||
* historyImportTask: (Function|undefined), | ||
* hitCallback: (Function|undefined), | ||
* hitPayload: (string|undefined), | ||
* hitType: (string|undefined), | ||
* hitCallback: (Function|undefined), | ||
* hostname: (string|undefined), | ||
* javaEnabled: (boolean|undefined), | ||
* language: (string|undefined), | ||
* legacyCookieDomain: (string|undefined), | ||
* legacyHistoryImport: (boolean|undefined), | ||
* linkerParam: (string|undefined), | ||
* linkid: (string|undefined), | ||
* location: (string|undefined), | ||
* name: (string|undefined), | ||
* nonInteraction: (boolean|undefined), | ||
* page: (string|undefined), | ||
* previewTask: (Function|undefined), | ||
* queueTime: (number|undefined), | ||
* referrer: (string|undefined), | ||
* sampleRate: (number|undefined), | ||
* samplerTask: (Function|undefined), | ||
* screenColors: (string|undefined), | ||
* screenName: (string|undefined), | ||
* screenResolution: (string|undefined), | ||
* sendHitTask: (Function|undefined), | ||
* sessionControl: (string|undefined), | ||
* sessionGroup: (string|undefined), | ||
* siteSpeedSampleRate: (number|undefined), | ||
* socialAction: (string|undefined), | ||
* socialNetwork: (string|undefined), | ||
* socialTarget: (string|undefined), | ||
* storage: (string|undefined), | ||
* timingCategory: (string|undefined), | ||
* timingLabel: (string|undefined), | ||
* timingTask: (Function|undefined), | ||
* timingValue: (number|undefined), | ||
* timingVar: (string|undefined), | ||
* title: (string|undefined), | ||
* trackingId: (string|undefined), | ||
* transport: (string|undefined), | ||
* transportUrl: (string|undefined), | ||
* useBeacon: (boolean|undefined), | ||
* userId: (string|undefined), | ||
* validationTask: (Function|undefined), | ||
* viewportSize: (string|undefined), | ||
* }} | ||
@@ -23,0 +89,0 @@ */ |
@@ -5,2 +5,3 @@ /** | ||
* sessionTimeout: (number), | ||
* visibleThreshold: (number), | ||
* timeZone: (string|undefined), | ||
@@ -7,0 +8,0 @@ * visibleMetricIndex: (number|undefined), |
@@ -47,3 +47,3 @@ /** | ||
// Feature detects to prevent errors in unsupporting browsers. | ||
if (!window.addEventListener) return; | ||
if (!document.visibilityState) return; | ||
@@ -53,2 +53,3 @@ /** @type {PageVisibilityTrackerOpts} */ | ||
sessionTimeout: Session.DEFAULT_TIMEOUT, | ||
visibleThreshold: 5 * SECONDS, | ||
// timeZone: undefined, | ||
@@ -65,2 +66,3 @@ // visibleMetricIndex: undefined, | ||
this.lastPageState = null; | ||
this.visibleThresholdTimeout_ = null; | ||
@@ -85,4 +87,5 @@ // Binds methods to `this`. | ||
window.addEventListener('unload', this.handleWindowUnload); | ||
document.addEventListener('visibilitychange', this.handleChange); | ||
window.addEventListener('unload', this.handleWindowUnload); | ||
if (document.visibilityState == VISIBLE) { | ||
@@ -104,2 +107,7 @@ this.handleChange(); | ||
handleChange() { | ||
if (!(document.visibilityState == VISIBLE || | ||
document.visibilityState == HIDDEN)) { | ||
return; | ||
} | ||
const lastStoredChange = this.validateChangeData(this.store.get()); | ||
@@ -114,21 +122,39 @@ | ||
// If the visibilityState has changed to hidden, clear any scheduled | ||
// pageviews waiting for the visibleThreshold timeout. | ||
if (this.visibleThresholdTimeout_ && document.visibilityState == HIDDEN) { | ||
clearTimeout(this.visibleThresholdTimeout_); | ||
} | ||
if (this.session.isExpired()) { | ||
if (document.visibilityState == HIDDEN) { | ||
// Hidden events should never be sent if a session has expired (if | ||
// they are, they'll likely start a new session with just this event). | ||
this.store.clear(); | ||
} else { | ||
// If the session has expired, changes to visible should be considered | ||
// a new pageview rather than a visibility event. | ||
if (this.lastPageState == HIDDEN && | ||
document.visibilityState == VISIBLE) { | ||
// If the session has expired, changes from hidden to visible should | ||
// be considered a new pageview rather than a visibility event. | ||
// This behavior ensures all sessions contain a pageview so | ||
// session-level page dimensions and metrics (e.g. ga:landingPagePath | ||
// and ga:entrances) are correct. | ||
// Also, in order to prevent false positives, we add a small timeout | ||
// that is cleared if the visibilityState changes to hidden shortly | ||
// after the change to visible. This can happen if a user is quickly | ||
// switching through their open tabs but not actually interacting with | ||
// and of them. It can also happen when a user goes to a tab just to | ||
// immediately close it. Such cases should not be considered pageviews. | ||
clearTimeout(this.visibleThresholdTimeout_); | ||
this.visibleThresholdTimeout_ = setTimeout(() => { | ||
/** @type {FieldsObj} */ | ||
const defaultFields = { | ||
transport: 'beacon', | ||
queueTime: now() - change.time, | ||
}; | ||
this.tracker.send('pageview', | ||
createFieldsObj(defaultFields, this.opts.fieldsObj, | ||
this.tracker, this.opts.hitFilter)); | ||
/** @type {FieldsObj} */ | ||
const defaultFields = {transport: 'beacon'}; | ||
this.tracker.send('pageview', | ||
createFieldsObj(defaultFields, this.opts.fieldsObj, | ||
this.tracker, this.opts.hitFilter)); | ||
this.store.set(change); | ||
this.store.set(change); | ||
}, this.opts.visibleThreshold); | ||
} else if (document.visibilityState == HIDDEN) { | ||
// Hidden events should never be sent if a session has expired (if | ||
// they are, they'll likely start a new session with just this event). | ||
this.store.clear(); | ||
} | ||
@@ -183,29 +209,31 @@ } else { | ||
sendPageVisibilityEvent(lastStoredChange, hitTime = undefined) { | ||
/** @type {FieldsObj} */ | ||
const defaultFields = { | ||
transport: 'beacon', | ||
nonInteraction: true, | ||
eventCategory: 'Page Visibility', | ||
eventAction: 'track', | ||
eventLabel: NULL_DIMENSION, | ||
}; | ||
if (hitTime) { | ||
defaultFields.queueTime = now() - hitTime; | ||
} | ||
const delta = this.getTimeSinceLastStoredChange(lastStoredChange, hitTime); | ||
// If at least a one second delta exists, report it. | ||
if (delta) { | ||
defaultFields.eventValue = delta; | ||
// If the detla is greater than the visibileThreshold, report it. | ||
if (delta && delta >= this.opts.visibleThreshold) { | ||
const deltaInSeconds = Math.round(delta / SECONDS); | ||
/** @type {FieldsObj} */ | ||
const defaultFields = { | ||
transport: 'beacon', | ||
nonInteraction: true, | ||
eventCategory: 'Page Visibility', | ||
eventAction: 'track', | ||
eventValue: deltaInSeconds, | ||
eventLabel: NULL_DIMENSION, | ||
}; | ||
if (hitTime) { | ||
defaultFields.queueTime = now() - hitTime; | ||
} | ||
// If a custom metric was specified, set it equal to the event value. | ||
if (this.opts.visibleMetricIndex) { | ||
defaultFields['metric' + this.opts.visibleMetricIndex] = delta; | ||
defaultFields['metric' + this.opts.visibleMetricIndex] = deltaInSeconds; | ||
} | ||
this.tracker.send('event', | ||
createFieldsObj(defaultFields, this.opts.fieldsObj, | ||
this.tracker, this.opts.hitFilter)); | ||
} | ||
this.tracker.send('event', | ||
createFieldsObj(defaultFields, this.opts.fieldsObj, | ||
this.tracker, this.opts.hitFilter)); | ||
} | ||
@@ -243,4 +271,4 @@ | ||
const isSessionActive = !this.session.isExpired(); | ||
const timeSinceLastStoredChange = lastStoredChange.time && | ||
Math.round((hitTime - lastStoredChange.time) / SECONDS); | ||
const timeSinceLastStoredChange = | ||
lastStoredChange.time && hitTime - lastStoredChange.time; | ||
@@ -296,2 +324,3 @@ return isSessionActive && | ||
remove() { | ||
this.store.destroy(); | ||
this.session.destroy(); | ||
@@ -298,0 +327,0 @@ MethodChain.remove(this.tracker, 'set', this.trackerSetOverride); |
145
lib/store.js
@@ -27,2 +27,6 @@ /** | ||
/** @type {boolean|undefined} */ | ||
let browserSupportsLocalStorage; | ||
/** | ||
@@ -46,3 +50,2 @@ * A storage object to simplify interacting with localStorage. | ||
instances[key] = new Store(key, defaults); | ||
instances[key].key = key; | ||
if (!isListening) initStorageListener(); | ||
@@ -54,23 +57,85 @@ } | ||
/** | ||
* Returns true if the browser supports and can successfully write to | ||
* localStorage. The results is cached so this method can be invoked many | ||
* times with no extra performance cost. | ||
* @private | ||
* @return {boolean} | ||
*/ | ||
static isSupported_() { | ||
if (browserSupportsLocalStorage != null) { | ||
return browserSupportsLocalStorage; | ||
} | ||
try { | ||
window.localStorage.setItem(AUTOTRACK_PREFIX, AUTOTRACK_PREFIX); | ||
window.localStorage.removeItem(AUTOTRACK_PREFIX); | ||
browserSupportsLocalStorage = true; | ||
} catch (err) { | ||
browserSupportsLocalStorage = false; | ||
} | ||
return browserSupportsLocalStorage; | ||
} | ||
/** | ||
* Wraps the native localStorage method for each stubbing in tests. | ||
* @private | ||
* @param {string} key The store key. | ||
* @return {string|null} The stored value. | ||
*/ | ||
static get_(key) { | ||
return window.localStorage.getItem(key); | ||
} | ||
/** | ||
* Wraps the native localStorage method for each stubbing in tests. | ||
* @private | ||
* @param {string} key The store key. | ||
* @param {string} value The value to store. | ||
*/ | ||
static set_(key, value) { | ||
window.localStorage.setItem(key, value); | ||
} | ||
/** | ||
* Wraps the native localStorage method for each stubbing in tests. | ||
* @private | ||
* @param {string} key The store key. | ||
*/ | ||
static clear_(key) { | ||
window.localStorage.removeItem(key); | ||
} | ||
/** | ||
* @param {string} key A key unique to this store. | ||
* @param {Object=} defaults An optional object of key/value defaults. | ||
*/ | ||
constructor(key, defaults) { | ||
constructor(key, defaults = {}) { | ||
super(); | ||
this.key = key; | ||
this.defaults = defaults || {}; | ||
this.key_ = key; | ||
this.defaults_ = defaults; | ||
/** @type {?Object} */ | ||
this.cache_ = null; // Will be set after the first get. | ||
} | ||
/** | ||
* Gets the data stored in localStorage for this store. | ||
* Gets the data stored in localStorage for this store. If the cache is | ||
* already populated, return it as is (since it's always kept up-to-date | ||
* and in sync with activity in other windows via the `storage` event). | ||
* TODO(philipwalton): Implement schema migrations if/when a new | ||
* schema version is introduced. | ||
* @return {!Object} The stored data merged with the defaults. | ||
*/ | ||
get() { | ||
try { | ||
// TODO(philipwalton): Implement schema migrations if/when a new | ||
// schema version is introduced. | ||
const storedItem = String(window.localStorage.getItem(this.key)); | ||
return parse(storedItem, this.defaults); | ||
} catch(err) { | ||
return {}; | ||
if (this.cache_) { | ||
return this.cache_; | ||
} else { | ||
if (Store.isSupported_()) { | ||
try { | ||
this.cache_ = parse(Store.get_(this.key_)); | ||
} catch(err) { | ||
// Do nothing. | ||
} | ||
} | ||
return this.cache_ = assign({}, this.defaults_, this.cache_); | ||
} | ||
@@ -85,9 +150,10 @@ } | ||
set(newData) { | ||
const oldData = this.get(); | ||
const mergedData = assign(oldData, newData); | ||
this.cache_ = assign({}, this.defaults_, this.cache_, newData); | ||
try { | ||
window.localStorage.setItem(this.key, JSON.stringify(mergedData)); | ||
} catch(err) { | ||
// Do nothing. | ||
if (Store.isSupported_()) { | ||
try { | ||
Store.set_(this.key_, JSON.stringify(this.cache_)); | ||
} catch(err) { | ||
// Do nothing. | ||
} | ||
} | ||
@@ -100,6 +166,9 @@ } | ||
clear() { | ||
try { | ||
window.localStorage.removeItem(this.key); | ||
} catch(err) { | ||
// Do nothing. | ||
this.cache_ = {}; | ||
if (Store.isSupported_()) { | ||
try { | ||
Store.clear_(this.key_); | ||
} catch(err) { | ||
// Do nothing. | ||
} | ||
} | ||
@@ -114,3 +183,3 @@ } | ||
destroy() { | ||
delete instances[this.key]; | ||
delete instances[this.key_]; | ||
if (!Object.keys(instances).length) { | ||
@@ -150,4 +219,6 @@ removeStorageListener(); | ||
if (store) { | ||
const oldData = parse(event.oldValue, store.defaults); | ||
const newData = parse(event.newValue, store.defaults); | ||
const oldData = assign({}, store.defaults_, parse(event.oldValue)); | ||
const newData = assign({}, store.defaults_, parse(event.newValue)); | ||
store.cache_ = newData; | ||
store.emit('externalSet', newData, oldData); | ||
@@ -159,16 +230,16 @@ } | ||
/** | ||
* Parses a source string as JSON and merges the result with the passed | ||
* defaults object. If an error occurs while | ||
* @param {string} source A JSON string of data. | ||
* @param {!Object} defaults An object of key/value defaults. | ||
* @return {!Object} The parsed data object merged with the passed defaults. | ||
* Parses a source string as JSON | ||
* @param {string|null} source | ||
* @return {!Object} The JSON object. | ||
*/ | ||
function parse(source, defaults) { | ||
let data; | ||
try { | ||
data = /** @type {!Object} */ (JSON.parse(source)); | ||
} catch(err) { | ||
data = {}; | ||
function parse(source) { | ||
let data = {}; | ||
if (source) { | ||
try { | ||
data = /** @type {!Object} */ (JSON.parse(source)); | ||
} catch(err) { | ||
// Do nothing. | ||
} | ||
} | ||
return assign({}, defaults, data); | ||
return data; | ||
} |
@@ -146,8 +146,9 @@ /** | ||
* @param {!Object} target The target object to assign to. | ||
* @param {...Object} sources Additional objects who properties should be | ||
* assigned to target. | ||
* @param {...?Object} sources Additional objects who properties should be | ||
* assigned to target. Non-objects are converted to objects. | ||
* @return {!Object} The modified target object. | ||
*/ | ||
export const assign = Object.assign || function(target, ...sources) { | ||
for (let source, i = 0; source = sources[i]; i++) { | ||
for (let i = 0, len = sources.length; i < len; i++) { | ||
const source = Object(sources[i]); | ||
for (let key in source) { | ||
@@ -154,0 +155,0 @@ if (Object.prototype.hasOwnProperty.call(source, key)) { |
{ | ||
"name": "autotrack", | ||
"version": "2.0.4", | ||
"version": "2.1.0", | ||
"description": "Automatic and enhanced Google Analytics tracking for common user interactions on the web", | ||
@@ -10,3 +10,3 @@ "main": "lib", | ||
"start": "gulp watch", | ||
"test": "gulp test:e2e" | ||
"test": "gulp test" | ||
}, | ||
@@ -13,0 +13,0 @@ "repository": { |
@@ -26,2 +26,9 @@ /** | ||
const DEFAULT_TRACKER_FIELDS = { | ||
trackingId: 'UA-12345-1', | ||
cookieDomain: 'auto', | ||
siteSpeedSampleRate: 0, | ||
}; | ||
let testId; | ||
@@ -40,3 +47,3 @@ let log; | ||
browser.execute(ga.run, 'create', 'UA-XXXXX-Y', 'auto'); | ||
browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
browser.execute(ga.logHitData, testId); | ||
@@ -43,0 +50,0 @@ }); |
@@ -26,2 +26,9 @@ /** | ||
const DEFAULT_TRACKER_FIELDS = { | ||
trackingId: 'UA-12345-1', | ||
cookieDomain: 'auto', | ||
siteSpeedSampleRate: 0, | ||
}; | ||
let testId; | ||
@@ -40,3 +47,3 @@ let log; | ||
browser.execute(ga.run, 'create', 'UA-XXXXX-Y', 'auto'); | ||
browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
browser.execute(ga.logHitData, testId); | ||
@@ -43,0 +50,0 @@ }); |
@@ -26,2 +26,9 @@ /** | ||
const DEFAULT_TRACKER_FIELDS = { | ||
trackingId: 'UA-12345-1', | ||
cookieDomain: 'auto', | ||
siteSpeedSampleRate: 0, | ||
}; | ||
let testId; | ||
@@ -63,3 +70,3 @@ let log; | ||
browser.scroll(0, 0); | ||
browser.execute(ga.run, 'create', 'UA-XXXXX-Y', 'auto'); | ||
browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
browser.execute(ga.logHitData, testId); | ||
@@ -66,0 +73,0 @@ }); |
@@ -26,2 +26,9 @@ /** | ||
const DEFAULT_TRACKER_FIELDS = { | ||
trackingId: 'UA-12345-1', | ||
cookieDomain: 'auto', | ||
siteSpeedSampleRate: 0, | ||
}; | ||
let testId; | ||
@@ -89,3 +96,3 @@ let log; | ||
browser.url('/test/e2e/fixtures/autotrack.html'); | ||
browser.execute(ga.run, 'create', 'UA-XXXXX-Y', 'auto'); | ||
browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
browser.execute(ga.logHitData, testId); | ||
@@ -111,3 +118,3 @@ browser.execute(ga.run, 'require', 'cleanUrlTracker'); | ||
browser.url('/test/e2e/fixtures/autotrack-rename.html'); | ||
browser.execute(ga.run, 'create', 'UA-XXXXX-Y', 'auto'); | ||
browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
browser.execute(ga.logHitData, testId); | ||
@@ -133,3 +140,3 @@ browser.execute(ga.run, 'require', 'cleanUrlTracker'); | ||
browser.url('/test/e2e/fixtures/autotrack.html'); | ||
browser.execute(ga.run, 'create', 'UA-XXXXX-Y', 'auto'); | ||
browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
browser.execute(ga.logHitData, testId); | ||
@@ -136,0 +143,0 @@ browser.execute(ga.run, 'require', 'cleanUrlTracker'); |
@@ -55,5 +55,3 @@ /** | ||
browser.scroll(0, 0); | ||
browser.execute(() => { | ||
localStorage.clear(); | ||
}); | ||
clearStorage(); | ||
@@ -316,13 +314,40 @@ browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
/** | ||
* Forces the session to expire by changing the stored last hit time. | ||
* Manually clear all stores. | ||
*/ | ||
function clearStorage() { | ||
setStoreData('autotrack:UA-12345-1:session', {}); | ||
setStoreData('autotrack:UA-12345-1:plugins/max-scroll-tracker', {}); | ||
} | ||
/** | ||
* Manually expires the session. | ||
*/ | ||
function expireSession() { | ||
browser.execute(() => { | ||
const storedSessionData = JSON.parse( | ||
localStorage.getItem('autotrack:UA-12345-1:session')) || {}; | ||
setStoreData('autotrack:UA-12345-1:session', {isExpired: true}); | ||
} | ||
storedSessionData.isExpired = true; | ||
localStorage.setItem('autotrack:UA-12345-1:session', | ||
JSON.stringify(storedSessionData)); | ||
}); | ||
/** | ||
* Manually set a value for store in all open windows/tabs. | ||
* @param {string} key | ||
* @param {!Object} value | ||
*/ | ||
function setStoreData(key, value) { | ||
browser.execute((key, value) => { | ||
const oldValue = localStorage.getItem(key); | ||
const newValue = JSON.stringify(value); | ||
// IE11 doesn't support event constructors. | ||
try { | ||
// Set the value on localStorage so it triggers the storage event in | ||
// other tabs. Also, manually dispatch the event in this tab since just | ||
// writing to localStorage won't update the locally cached values. | ||
window.localStorage.setItem(key, newValue); | ||
window.dispatchEvent( | ||
new StorageEvent('storage', {key, oldValue, newValue})); | ||
} catch(err) { | ||
// Do nothing | ||
} | ||
}, key, value); | ||
} |
@@ -26,4 +26,12 @@ /** | ||
const DEFAULT_TRACKER_FIELDS = { | ||
trackingId: 'UA-12345-1', | ||
cookieDomain: 'auto', | ||
siteSpeedSampleRate: 0, | ||
}; | ||
const TIMEOUT = 1000; | ||
const opts = { | ||
@@ -67,3 +75,3 @@ definitions: [ | ||
browser.setViewportSize({width: 800, height: 600}, false); | ||
browser.execute(ga.run, 'create', 'UA-XXXXX-Y', 'auto'); | ||
browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
browser.execute(ga.logHitData, testId); | ||
@@ -140,3 +148,3 @@ }); | ||
browser.execute(ga.run, 'remove'); | ||
browser.execute(ga.run, 'create', 'UA-XXXXX-Y', 'auto'); | ||
browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
browser.execute(ga.logHitData, testId); | ||
@@ -143,0 +151,0 @@ browser.setViewportSize({width: 800, height: 600}, false); |
@@ -26,2 +26,9 @@ /** | ||
const DEFAULT_TRACKER_FIELDS = { | ||
trackingId: 'UA-12345-1', | ||
cookieDomain: 'auto', | ||
siteSpeedSampleRate: 0, | ||
}; | ||
const baseUrl = browser.options.baseUrl; | ||
@@ -42,3 +49,3 @@ | ||
browser.url('/test/e2e/fixtures/outbound-form-tracker.html'); | ||
browser.execute(ga.run, 'create', 'UA-XXXXX-Y', 'auto'); | ||
browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
browser.execute(ga.logHitData, testId); | ||
@@ -92,3 +99,3 @@ }); | ||
browser.url('/test/e2e/fixtures/outbound-form-tracker.html'); | ||
browser.execute(ga.run, 'create', 'UA-XXXXX-Y', 'auto'); | ||
browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
browser.execute(ga.logHitData, testId); | ||
@@ -95,0 +102,0 @@ browser.execute(ga.run, 'require', 'outboundFormTracker', { |
@@ -26,2 +26,9 @@ /** | ||
const DEFAULT_TRACKER_FIELDS = { | ||
trackingId: 'UA-12345-1', | ||
cookieDomain: 'auto', | ||
siteSpeedSampleRate: 0, | ||
}; | ||
const baseUrl = browser.options.baseUrl; | ||
@@ -42,3 +49,3 @@ | ||
browser.url('/test/e2e/fixtures/outbound-link-tracker.html'); | ||
browser.execute(ga.run, 'create', 'UA-XXXXX-Y', 'auto'); | ||
browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
browser.execute(ga.logHitData, testId); | ||
@@ -150,3 +157,3 @@ }); | ||
browser.url('/test/e2e/fixtures/outbound-link-tracker.html'); | ||
browser.execute(ga.run, 'create', 'UA-XXXXX-Y', 'auto'); | ||
browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
browser.execute(ga.logHitData, testId); | ||
@@ -153,0 +160,0 @@ browser.execute(ga.run, 'require', 'outboundLinkTracker', { |
@@ -28,2 +28,3 @@ /** | ||
const SESSION_TIMEOUT_IN_MINUTES = (1/60) * 3; // 3 seconds | ||
const VISIBLE_THRESHOLD = 2000; // 2 seconds | ||
@@ -37,3 +38,7 @@ | ||
const TEST_OPTS = { | ||
visibleThreshold: 0, | ||
}; | ||
let testId; | ||
@@ -50,5 +55,3 @@ let log; | ||
browser.url('/test/e2e/fixtures/autotrack.html?tab=1'); | ||
browser.execute(() => { | ||
localStorage.clear(); | ||
}); | ||
clearStorage(); | ||
browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
@@ -66,3 +69,3 @@ browser.execute(ga.logHitData, testId); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
openNewTab(); | ||
@@ -80,3 +83,3 @@ | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.pause(2000); | ||
@@ -94,3 +97,3 @@ openNewTab(); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
openNewTab(); | ||
@@ -111,2 +114,3 @@ closeAllButFirstTab(); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', { | ||
visibleThreshold: 0, | ||
visibleMetricIndex: 1, | ||
@@ -129,2 +133,3 @@ }); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', { | ||
visibleThreshold: 0, | ||
sessionTimeout: SESSION_TIMEOUT_IN_MINUTES, | ||
@@ -141,9 +146,6 @@ }); | ||
it('sends a pageview when changing to visible if the session has expired', | ||
function() { | ||
it('sends a pageview on session-expiry when changing to visible', function() { | ||
if (!browserSupportsTabs()) return this.skip(); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', { | ||
sessionTimeout: SESSION_TIMEOUT_IN_MINUTES, | ||
}); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
@@ -163,2 +165,18 @@ expireSession(); | ||
it('does not send a session-expiry pageview on initial pageload', function() { | ||
if (!browserSupportsTabs()) return this.skip(); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
expireSession(); | ||
log.removeHits(); | ||
openNewWindow('/test/e2e/fixtures/autotrack.html?window=1'); | ||
browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
browser.execute(ga.logHitData, testId); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
log.assertNoHitsReceived(); | ||
}); | ||
it('resets the session timeout when other hits are sent', function() { | ||
@@ -168,2 +186,3 @@ if (!browserSupportsTabs()) return this.skip(); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', { | ||
visibleThreshold: 0, | ||
sessionTimeout: SESSION_TIMEOUT_IN_MINUTES, | ||
@@ -195,2 +214,52 @@ }); | ||
it('only sends events when the visibleThreshold is met', function() { | ||
if (!browserSupportsTabs()) return this.skip(); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', { | ||
visibleThreshold: VISIBLE_THRESHOLD, | ||
sessionTimeout: SESSION_TIMEOUT_IN_MINUTES, | ||
}); | ||
openNewTab(); | ||
closeAllButFirstTab(); | ||
openNewTab(); | ||
closeAllButFirstTab(); | ||
openNewTab(); | ||
closeAllButFirstTab(); | ||
log.assertNoHitsReceived(); | ||
browser.pause(VISIBLE_THRESHOLD); | ||
openNewTab(); | ||
browser.waitUntil(log.hitCountEquals(1)); | ||
const hits = log.getHits(); | ||
assert.strictEqual(hits[0].ec, 'Page Visibility'); | ||
assert.strictEqual(hits[0].ea, 'track'); | ||
}); | ||
it('waits to send pageviews until the visibleThreshold is met', function() { | ||
if (!browserSupportsTabs()) return this.skip(); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', { | ||
visibleThreshold: VISIBLE_THRESHOLD, | ||
sessionTimeout: SESSION_TIMEOUT_IN_MINUTES, | ||
}); | ||
expireSession(); | ||
log.removeHits(); | ||
openNewTab(); | ||
closeAllButFirstTab(); | ||
const start = Date.now(); | ||
browser.waitUntil(log.hitCountEquals(1)); | ||
const end = Date.now(); | ||
// Expects non-pageview hits queued to be sent after the session has timed | ||
// out to include a pageview immediately before them. | ||
const hits = log.getHits(); | ||
assert.strictEqual(hits[0].t, 'pageview'); | ||
assert(hits[0].qt >= VISIBLE_THRESHOLD); | ||
assert(end - start >= VISIBLE_THRESHOLD); | ||
}); | ||
it('handles closing a window/tab when a visible window is still open', | ||
@@ -201,3 +270,3 @@ function() { | ||
const tab1 = browser.getCurrentTabId(); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
@@ -207,3 +276,3 @@ const window1 = openNewWindow('/test/e2e/fixtures/autotrack.html?window=1'); | ||
browser.execute(ga.logHitData, testId); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
@@ -235,3 +304,3 @@ browser.close(tab1); // Close window1 and switch to tab1. | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.execute(ga.run, 'send', 'pageview'); | ||
@@ -278,3 +347,3 @@ browser.pause(randomInteger(500, 2000)); | ||
const tab1 = browser.getCurrentTabId(); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.execute(ga.run, 'send', 'pageview'); | ||
@@ -289,3 +358,3 @@ browser.pause(randomInteger(500, 2000)); | ||
browser.execute(ga.logHitData, testId); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.execute(ga.run, 'send', 'pageview'); | ||
@@ -329,3 +398,3 @@ browser.pause(randomInteger(500, 2000)); | ||
const tab1 = browser.getCurrentTabId(); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.execute(ga.run, 'send', 'pageview'); | ||
@@ -337,3 +406,3 @@ browser.pause(randomInteger(500, 2000)); | ||
browser.execute(ga.logHitData, testId); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.execute(ga.run, 'send', 'pageview'); | ||
@@ -348,3 +417,3 @@ browser.pause(randomInteger(500, 2000)); | ||
browser.execute(ga.logHitData, testId); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.execute(ga.run, 'send', 'pageview'); | ||
@@ -403,3 +472,3 @@ browser.pause(randomInteger(500, 2000)); | ||
const tab1 = browser.getCurrentTabId(); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.execute(ga.run, 'send', 'pageview'); | ||
@@ -414,3 +483,3 @@ browser.pause(randomInteger(500, 2000)); | ||
browser.execute(ga.logHitData, testId); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.execute(ga.run, 'send', 'pageview'); | ||
@@ -422,3 +491,3 @@ browser.pause(randomInteger(500, 2000)); | ||
browser.execute(ga.logHitData, testId); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.execute(ga.run, 'send', 'pageview'); | ||
@@ -430,3 +499,3 @@ browser.pause(randomInteger(500, 2000)); | ||
browser.execute(ga.logHitData, testId); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.execute(ga.run, 'send', 'pageview'); | ||
@@ -499,3 +568,3 @@ browser.pause(randomInteger(500, 2000)); | ||
const tab1 = browser.getCurrentTabId(); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.execute(ga.run, 'send', 'pageview'); | ||
@@ -510,3 +579,3 @@ browser.pause(randomInteger(500, 2000)); | ||
browser.execute(ga.logHitData, testId); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.execute(ga.run, 'send', 'pageview'); | ||
@@ -518,3 +587,3 @@ browser.pause(randomInteger(500, 2000)); | ||
browser.execute(ga.logHitData, testId); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.execute(ga.run, 'send', 'pageview'); | ||
@@ -525,2 +594,3 @@ browser.pause(randomInteger(500, 2000)); | ||
expireSession(); | ||
browser.pause(randomInteger(500, 2000)); | ||
@@ -581,2 +651,3 @@ browser.close(tab3); // Close tab4 and go to tab3. | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', { | ||
visibleThreshold: 0, | ||
fieldsObj: { | ||
@@ -615,3 +686,3 @@ dimension1: 'pageVisibilityTracker', | ||
it('includes usage params with all hits', () => { | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.execute(ga.run, 'send', 'pageview'); | ||
@@ -631,3 +702,3 @@ browser.waitUntil(log.hitCountEquals(1)); | ||
it('destroys all bound events and functionality', () => { | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker'); | ||
browser.execute(ga.run, 'require', 'pageVisibilityTracker', TEST_OPTS); | ||
browser.execute(ga.run, 'send', 'pageview'); | ||
@@ -743,13 +814,40 @@ | ||
/** | ||
* Forces the session to expire by changing the stored last hit time. | ||
* Manually clear all stores. | ||
*/ | ||
function clearStorage() { | ||
setStoreData('autotrack:UA-12345-1:session', {}); | ||
setStoreData('autotrack:UA-12345-1:plugins/page-visibility-tracker', {}); | ||
} | ||
/** | ||
* Manually expires the session. | ||
*/ | ||
function expireSession() { | ||
browser.execute(() => { | ||
const storedSessionData = JSON.parse( | ||
localStorage.getItem('autotrack:UA-12345-1:session')) || {}; | ||
setStoreData('autotrack:UA-12345-1:session', {isExpired: true}); | ||
} | ||
storedSessionData.isExpired = true; | ||
localStorage.setItem('autotrack:UA-12345-1:session', | ||
JSON.stringify(storedSessionData)); | ||
}); | ||
/** | ||
* Manually set a value for store in all open windows/tabs. | ||
* @param {string} key | ||
* @param {!Object} value | ||
*/ | ||
function setStoreData(key, value) { | ||
browser.execute((key, value) => { | ||
const oldValue = window.localStorage.getItem(key); | ||
const newValue = JSON.stringify(value); | ||
// IE11 doesn't support event constructors. | ||
try { | ||
// Set the value on localStorage so it triggers the storage event in | ||
// other tabs. Also, manually dispatch the event in this tab since just | ||
// writing to localStorage won't update the locally cached values. | ||
window.localStorage.setItem(key, newValue); | ||
window.dispatchEvent( | ||
new StorageEvent('storage', {key, oldValue, newValue})); | ||
} catch(err) { | ||
// Do nothing | ||
} | ||
}, key, value); | ||
} | ||
@@ -765,2 +863,3 @@ | ||
ga('require', 'pageVisibilityTracker', { | ||
visibleThreshold: 0, | ||
hitFilter: (model) => { | ||
@@ -767,0 +866,0 @@ const eventValue = model.get('eventValue'); |
@@ -26,2 +26,9 @@ /** | ||
const DEFAULT_TRACKER_FIELDS = { | ||
trackingId: 'UA-12345-1', | ||
cookieDomain: 'auto', | ||
siteSpeedSampleRate: 0, | ||
}; | ||
let testId; | ||
@@ -40,3 +47,3 @@ let log; | ||
browser.execute(ga.run, 'create', 'UA-XXXXX-Y', 'auto'); | ||
browser.execute(ga.run, 'create', DEFAULT_TRACKER_FIELDS); | ||
browser.execute(ga.logHitData, testId); | ||
@@ -43,0 +50,0 @@ }); |
@@ -46,22 +46,25 @@ /** | ||
}, | ||
{ | ||
browserName: 'firefox', | ||
platform: 'OS X 10.11', | ||
version: 'latest', | ||
}, | ||
{ | ||
browserName: 'safari', | ||
platform: 'OS X 10.12', | ||
version: '10.0', | ||
}, | ||
{ | ||
browserName: 'safari', | ||
platform: 'OS X 10.11', | ||
version: '9', | ||
}, | ||
{ | ||
browserName: 'internet explorer', | ||
platform: 'Windows 8.1', | ||
version: '11', | ||
}, | ||
// TODO(philipwalton): other browsers have been too flaky to run on | ||
// every push. Uncomment and test manually before making releases, but | ||
// for now there's too much failure noise to run on these browsers. | ||
// { | ||
// browserName: 'firefox', | ||
// platform: 'OS X 10.11', | ||
// version: 'latest', | ||
// }, | ||
// { | ||
// browserName: 'safari', | ||
// platform: 'OS X 10.12', | ||
// version: '10.0', | ||
// }, | ||
// { | ||
// browserName: 'safari', | ||
// platform: 'OS X 10.11', | ||
// version: '9', | ||
// }, | ||
// { | ||
// browserName: 'internet explorer', | ||
// platform: 'Windows 8.1', | ||
// version: '11', | ||
// }, | ||
// TODO(philipwalton) Edge webdriver does not fully support enough of the | ||
@@ -68,0 +71,0 @@ // webdriver features to rely on. Wait for full support and then re-add: |
@@ -192,4 +192,5 @@ /** | ||
const originalDateTimeFormatDescriptor = Object.getOwnPropertyDescriptor( | ||
Intl.DateTimeFormat.prototype, 'format'); | ||
const originalDateTimeFormatDescriptor = window.Intl && | ||
window.Intl.DateTimeFormat && Object.getOwnPropertyDescriptor( | ||
Intl.DateTimeFormat.prototype, 'format'); | ||
@@ -196,0 +197,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
705588
8601