Shoora
4/29/2019 - 2:38 PM

GAS w/ dc.js

GAS w/ dc.js

/**
 * @preserve Copyright 2011, Cardinal Path and DigitalInc.
 *
 * GAS - Google Analytics on Steroids
 * https://github.com/CardinalPath/gas
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 * Licensed under the GPLv3 license.
 */
(function(window, undefined) {

/**
 * GAS - Google Analytics on Steroids
 *
 * Helper Functions
 *
 * Copyright 2011, Cardinal Path and Direct Performance
 * Licensed under the MIT license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */

/**
 * GasHelper singleton class
 *
 * Should be called when ga.js is loaded to get the pageTracker.
 *
 * @constructor
 */
/*jshint -W079*/
var GasHelper = function () {
    this._setDummyTracker();
};
/*jshint +W079*/

GasHelper.prototype._setDummyTracker = function () {
    if (!this['tracker']) {
        var trackers = window['_gat']['_getTrackers']();
        if (trackers.length > 0) {
            this['tracker'] = trackers[0];
        }
    }
};

/**
 * Returns true if the element is found in the Array, false otherwise.
 *
 * @param {Array} obj Array to search at.
 * @param {object} item Item to search form.
 * @return {boolean} true if contains.
 */
GasHelper.prototype.inArray = function (obj, item) {
    if (obj && obj.length) {
        for (var i = 0; i < obj.length; i++) {
            if (obj[i] === item) {
                return true;
            }
        }
    }
    return false;
};

/**
 * Removes special characters and Lowercase String
 *
 * @param {string} str to be sanitized.
 * @param {boolean} strict_opt If we should remove any non ascii char.
 * @return {string} Sanitized string.
 */
GasHelper.prototype._sanitizeString = function (str, strict_opt) {
    str = str.toLowerCase()
        .replace(/^\ +/, '')
        .replace(/\ +$/, '')
        .replace(/\s+/g, '_')
        .replace(/[áàâãåäæª]/g, 'a')
        .replace(/[éèêëЄ€]/g, 'e')
        .replace(/[íìîï]/g, 'i')
        .replace(/[óòôõöøº]/g, 'o')
        .replace(/[úùûü]/g, 'u')
        .replace(/[碩]/g, 'c');

    if (strict_opt) {
        str = str.replace(/[^a-z0-9_\-]/g, '_');
    }
    return str.replace(/_+/g, '_');
};

/**
 * Cross Browser helper to addEventListener.
 *
 * ga_next.js currently have a _addEventListener directive. So _gas will
 * allways prefer that if available, and will use this one only as a fallback
 *
 * @param {HTMLElement} obj The Element to attach event to.
 * @param {string} evt The event that will trigger the binded function.
 * @param {function(event)} ofnc The function to bind to the element.
 * @param {boolean} bubble true if event should be fired at bubble phase.
 * Defaults to false. Works only on W3C compliant browser. MSFT don't support
 * it.
 * @return {boolean} true if it was successfuly binded.
 */
GasHelper.prototype._addEventListener = function (obj, evt, ofnc, bubble) {
    var fnc = function (event) {
        if (!event || !event.target) {
            event = window.event;
            event.target = event.srcElement;
        }
        return ofnc.call(obj, event);
    };
    // W3C model
    if (obj.addEventListener) {
        obj.addEventListener(evt, fnc, !!bubble);
        return true;
    }
    // M$ft model
    else if (obj.attachEvent) {
        return obj.attachEvent('on' + evt, fnc);
    }
    // Browser doesn't support W3C or M$ft model. Time to go old school
    else {
        evt = 'on' + evt;
        if (typeof obj[evt] === 'function') {
            // Object already has a function on traditional
            // Let's wrap it with our own function inside another function
            fnc = (function (f1, f2) {
                return function () {
                    f1.apply(this, arguments);
                    f2.apply(this, arguments);
                };
            }(obj[evt], fnc));
        }
        obj[evt] = fnc;
        return true;
    }
};

/**
 * Cross Browser Helper to emulate jQuery.live
 *
 * Binds to the document root. Listens to all events of the specific type.
 * If event don't bubble it won't catch
 */
GasHelper.prototype._liveEvent = function (tag, evt, ofunc) {
    var gh = this;
    tag = tag.toUpperCase();
    tag = tag.split(',');

    gh._addEventListener(document, evt, function (me) {
        for (var el = me.target; el.nodeName !== 'HTML';
            el = el.parentNode)
        {
            if (gh.inArray(tag, el.nodeName) || el.parentNode === null) {
                break;
            }
        }
        if (el && gh.inArray(tag, el.nodeName)) {
            ofunc.call(el, me);
        }

    }, true);
};

/**
 * Cross Browser DomReady function.
 *
 * Inspired by: http://dean.edwards.name/weblog/2006/06/again/#comment367184
 *
 * @param {function(Event)} callback DOMReady callback.
 * @return {boolean} Ignore return value.
 */
GasHelper.prototype._DOMReady = function (callback) {
    var scp = this;
    function cb() {
        if (cb.done) return;
        cb.done = true;
        callback.apply(scp, arguments);
    }
    if (/^(interactive|complete)/.test(document.readyState)) return cb();
    this._addEventListener(document, 'DOMContentLoaded', cb, false);
    this._addEventListener(window, 'load', cb, false);
};


/**
 * GAS - Google Analytics on Steroids
 *
 * Copyright 2011, Cardinal Path and Direct Performance
 * Licensed under the MIT license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */
 /*global document:true*/

/**
 * Google Analytics original _gaq.
 *
 * This never tries to do something that is not supposed to. So it won't break
 * in the future.
 */
window['_gaq'] = window['_gaq'] || [];

var _prev_gas = window['_gas'] || [];

// Avoid duplicate definition
if (_prev_gas._accounts_length >= 0) {
    return;
}

//Shortcuts, these speed up and compress the code
/*jshint -W079*/
var document = window.document,
    toString = Object.prototype.toString,
    hasOwn = Object.prototype.hasOwnProperty,
    push = Array.prototype.push,
    slice = Array.prototype.slice,
    trim = String.prototype.trim,
    sindexOf = String.prototype.indexOf,
    url = document.location.href,
    documentElement = document.documentElement;
/*jshint +W079*/
/**
 * GAS Sigleton
 * @constructor
 */
function GAS() {
    var self = this;
    self['version'] = '1.11.0';
    self._accounts = {};
    self._accounts_length = 0;
    self._queue = _prev_gas;
    self._default_tracker = '_gas1';
    self.gh = {};
    self._hooks = {
        '_addHook': [self._addHook]
    };
    // Need to be pushed to make sure tracker is done
    // Sets up helpers, very first thing pushed into gas
    self.push(function () {
        self.gh = new GasHelper();
    });
}

/**
 * First standard Hook that is responsible to add next Hooks
 *
 * _addHook calls always reurn false so they don't get pushed to _gaq
 * @param {string} fn The function you wish to add a Hook to.
 * @param {function()} cb The callback function to be appended to hooks.
 * @return {boolean} Always false.
 */
GAS.prototype._addHook = function (fn, cb) {
    if (typeof fn === 'string' && typeof cb === 'function') {
        if (typeof _gas._hooks[fn] === 'undefined') {
            _gas._hooks[fn] = [];
        }
        _gas._hooks[fn].push(cb);
    }
    return false;
};

/**
 * Construct the correct account name to be used on _gaq calls.
 *
 * The account name for the first unamed account pushed to _gas is the standard
 * account name. It's pushed without the account name to _gaq, so if someone
 * calls directly _gaq it works as expected.
 * @param {string} acct Account name.
 * @return {string} Correct account name to be used already with trailling dot.
 */
function _build_acct_name(acct) {
    return acct === _gas._default_tracker ? '' : acct + '.';
}

function _gaq_push(arr) {
    if (_gas.debug_mode) {
        try {
            console.log(arr);
        }catch (e) {}
    }
    return window['_gaq'].push(arr);
}

/**
 * Everything pushed to _gas is executed by this call.
 *
 * This function should not be called directly. Instead use _gas.push
 * @return {number} This is the same return as _gaq.push calls.
 */
GAS.prototype._execute = function () {
    var args = slice.call(arguments),
        self = this,
        sub = args.shift(),
        gaq_execute = true,
        i, foo, hooks, acct_name, repl_sub, return_val = 0;

    if (typeof sub === 'function') {
        // Pushed functions are executed right away
        return _gaq_push(
            (function (s, gh) {
                return function () {
                    // pushed functions receive helpers through this object
                    s.call(gh);
                };
            }(sub, self.gh))
        );

    } else if (typeof sub === 'object' && sub.length > 0) {
        foo = sub.shift();

        if (sindexOf.call(foo, '.') >= 0) {
            acct_name = foo.split('.')[0];
            foo = foo.split('.')[1];
        } else {
            acct_name = undefined;
        }

        // Execute hooks
        hooks = self._hooks[foo];
        if (hooks && hooks.length > 0) {
            for (i = 0; i < hooks.length; i++) {
                try {
                    repl_sub = hooks[i].apply(self.gh, sub);
                    if (repl_sub === false) {
                        // Returning false from a hook cancel the call
                        gaq_execute = false;
                    } else {
                        if (repl_sub && repl_sub.length > 0) {
                            // Returning an array changes the call parameters
                            sub = repl_sub;
                        }
                    }
                } catch (e) {
                    if (foo !== '_trackException') {
                        self.push(['_trackException', e]);
                    }
                }
            }
        }
        // Cancel execution on _gaq if any hook returned false
        if (gaq_execute === false) {
            return 1;
        }
        // Intercept _setAccount calls
        if (foo === '_setAccount') {

            for (i in self._accounts) {
                if (self._accounts[i] === sub[0]) {
                    // Repeated account
                    if (acct_name === undefined) {
                        return 1;
                    }
                }
            }
            acct_name = acct_name || '_gas' +
                String(self._accounts_length + 1);
            // Force that the first unamed account is _gas1
            if (typeof self._accounts['_gas1'] === 'undefined' &&
                sindexOf.call(acct_name, '_gas') !== -1) {
                acct_name = '_gas1';
            }
            self._accounts[acct_name] = sub[0];
            self._accounts_length += 1;
            acct_name = _build_acct_name(acct_name);
            return_val = _gaq_push([acct_name + foo, sub[0]]);
            // Must try t get the tracker if it's a _setAccount
            self.gh._setDummyTracker();
            return return_val;
        }

        // Intercept functions that can only be called once.
        if (foo === '_link' || foo === '_linkByPost' || foo === '_require' ||
            foo === '_anonymizeIp')
        {
            args = slice.call(sub);
            args.unshift(foo);
            return _gaq_push(args);
        }

        // If user provides account than trigger event for just that account.
        var acc_foo;
        if (acct_name && self._accounts[acct_name]) {
            acc_foo = _build_acct_name(acct_name) + foo;
            args = slice.call(sub);
            args.unshift(acc_foo);
            return _gaq_push(args);
        }

        // Call Original _gaq, for all accounts
        if (self._accounts_length > 0) {
            for (i in self._accounts) {
                if (hasOwn.call(self._accounts, i)) {
                    acc_foo = _build_acct_name(i) + foo;
                    args = slice.call(sub);
                    args.unshift(acc_foo);
                    return_val += _gaq_push(args);
                }
            }
        } else {
            // If there are no accounts we just push it to _gaq
            args = slice.call(sub);
            args.unshift(foo);
            return _gaq_push(args);
        }
        return return_val ? 1 : 0;
    }
};

/**
 * Standard method to execute GA commands.
 *
 * Everything pushed to _gas is in fact pushed back to _gaq. So Helpers are
 * ready for hooks. This creates _gaq as a series of functions that call
 * _gas._execute() with the same arguments.
 */
GAS.prototype.push = function () {
    var self = this;
    var args = slice.call(arguments);
    for (var i = 0; i < args.length; i++) {
        (function (arr, self) {
            window['_gaq'].push(function () {
                self._execute.call(self, arr);
            });
        }(args[i], self));
    }
};

/**
 * _gas main object.
 *
 * It's supposed to be used just like _gaq but here we extend it. In it's core
 * everything pushed to _gas is run through possible hooks and then pushed to
 * _gaq
 */
/*global _gas:true*/
window['_gas'] = _gas = new GAS();
/*global _gas:false*/


/**
 * Hook for _trackException
 *
 * Watchout for circular calls
 */
_gas.push(['_addHook', '_trackException', function (exception, message) {
    _gas.push(['_trackEvent',
        'Exception ' + (exception.name || 'Error'),
        message || exception.message || exception,
        url
    ]);
    return false;
}]);

/**
 * Hook to enable Debug Mode
 */
_gas.push(['_addHook', '_setDebug', function (set_debug) {
    _gas.debug_mode = !!set_debug;
}]);

/**
 * Hook to Remove other Hooks
 *
 * It will remove the last inserted hook from a _gas function.
 *
 * @param {string} func _gas Function Name to remove Hooks from.
 * @return {boolean} Always returns false.
 */
_gas.push(['_addHook', '_popHook', function (func) {
    var arr = _gas._hooks[func];
    if (arr && arr.pop) {
        arr.pop();
    }
    return false;
}]);

/**
 * Hook to set the default tracker.
 *
 * The default tracker is the nameless tracker that is pushed into _gaq_push
 */
_gas.push(['_addHook', '_gasSetDefaultTracker', function (tname) {
    _gas._default_tracker = tname;
    return false;
}]);

/**
 * Wrap-up
 */
// Execute previous functions
while (_gas._queue.length > 0) {
	_gas.push(_gas._queue.shift());
}

// Import ga.js
if (typeof window._gat === 'undefined') {
	(function () {
		var gasScript = document.getElementByID('gas-script');
		var ga = document.createElement('script');
		ga.type = 'text/javascript';
		ga.async = true;
		if (gasScript !== null && gasScript.getAttribute('data-use-dcjs') === 'true') {
			ga.src = (
				'https:' === document.location.protocol ?
				'https://' : 'http://') +
				'stats.g.doubleclick.net/dc.js';
		} else {
			ga.src = (
				'https:' === document.location.protocol ?
				'https://ssl' : 'http://www') +
				'.google-analytics.com/ga.js';
		}
		var s = document.getElementsByTagName('script')[0];
		s.parentNode.insertBefore(ga, s);
	}());
}

})(window);
/**
 * @preserve Copyright 2011, Cardinal Path and DigitalInc.
 *
 * GAS - Google Analytics on Steroids
 * https://github.com/CardinalPath/gas
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 * Licensed under the GPLv3 license.
 */
!function(a,b){function c(){var a=this;a.version="1.11.0",a._accounts={},a._accounts_length=0,a._queue=g,a._default_tracker="_gas1",a.gh={},a._hooks={_addHook:[a._addHook]},a.push(function(){a.gh=new f})}function d(a){return a===_gas._default_tracker?"":a+"."}function e(b){if(_gas.debug_mode)try{console.log(b)}catch(c){}return a._gaq.push(b)}var f=function(){this._setDummyTracker()};f.prototype._setDummyTracker=function(){if(!this.tracker){var b=a._gat._getTrackers();b.length>0&&(this.tracker=b[0])}},f.prototype.inArray=function(a,b){if(a&&a.length)for(var c=0;c<a.length;c++)if(a[c]===b)return!0;return!1},f.prototype._sanitizeString=function(a,b){return a=a.toLowerCase().replace(/^\ +/,"").replace(/\ +$/,"").replace(/\s+/g,"_").replace(/[áàâãåäæª]/g,"a").replace(/[éèêëЄ€]/g,"e").replace(/[íìîï]/g,"i").replace(/[óòôõöøº]/g,"o").replace(/[úùûü]/g,"u").replace(/[碩]/g,"c"),b&&(a=a.replace(/[^a-z0-9_\-]/g,"_")),a.replace(/_+/g,"_")},f.prototype._addEventListener=function(b,c,d,e){var f=function(c){return c&&c.target||(c=a.event,c.target=c.srcElement),d.call(b,c)};return b.addEventListener?(b.addEventListener(c,f,!!e),!0):b.attachEvent?b.attachEvent("on"+c,f):(c="on"+c,"function"==typeof b[c]&&(f=function(a,b){return function(){a.apply(this,arguments),b.apply(this,arguments)}}(b[c],f)),b[c]=f,!0)},f.prototype._liveEvent=function(a,b,c){var d=this;a=a.toUpperCase(),a=a.split(","),d._addEventListener(h,b,function(b){for(var e=b.target;"HTML"!==e.nodeName&&!d.inArray(a,e.nodeName)&&null!==e.parentNode;e=e.parentNode);e&&d.inArray(a,e.nodeName)&&c.call(e,b)},!0)},f.prototype._DOMReady=function(b){function c(){c.done||(c.done=!0,b.apply(d,arguments))}var d=this;return/^(interactive|complete)/.test(h.readyState)?c():(this._addEventListener(h,"DOMContentLoaded",c,!1),this._addEventListener(a,"load",c,!1),void 0)},a._gaq=a._gaq||[];var g=a._gas||[];if(!(g._accounts_length>=0)){var h=a.document,i=(Object.prototype.toString,Object.prototype.hasOwnProperty),j=(Array.prototype.push,Array.prototype.slice),k=(String.prototype.trim,String.prototype.indexOf),l=h.location.href;for(h.documentElement,c.prototype._addHook=function(a,b){return"string"==typeof a&&"function"==typeof b&&("undefined"==typeof _gas._hooks[a]&&(_gas._hooks[a]=[]),_gas._hooks[a].push(b)),!1},c.prototype._execute=function(){var a,c,f,g,h,l=j.call(arguments),m=this,n=l.shift(),o=!0,p=0;if("function"==typeof n)return e(function(a,b){return function(){a.call(b)}}(n,m.gh));if("object"==typeof n&&n.length>0){if(c=n.shift(),k.call(c,".")>=0?(g=c.split(".")[0],c=c.split(".")[1]):g=b,f=m._hooks[c],f&&f.length>0)for(a=0;a<f.length;a++)try{h=f[a].apply(m.gh,n),h===!1?o=!1:h&&h.length>0&&(n=h)}catch(q){"_trackException"!==c&&m.push(["_trackException",q])}if(o===!1)return 1;if("_setAccount"===c){for(a in m._accounts)if(m._accounts[a]===n[0]&&g===b)return 1;return g=g||"_gas"+String(m._accounts_length+1),"undefined"==typeof m._accounts._gas1&&-1!==k.call(g,"_gas")&&(g="_gas1"),m._accounts[g]=n[0],m._accounts_length+=1,g=d(g),p=e([g+c,n[0]]),m.gh._setDummyTracker(),p}if("_link"===c||"_linkByPost"===c||"_require"===c||"_anonymizeIp"===c)return l=j.call(n),l.unshift(c),e(l);var r;if(g&&m._accounts[g])return r=d(g)+c,l=j.call(n),l.unshift(r),e(l);if(!(m._accounts_length>0))return l=j.call(n),l.unshift(c),e(l);for(a in m._accounts)i.call(m._accounts,a)&&(r=d(a)+c,l=j.call(n),l.unshift(r),p+=e(l));return p?1:0}},c.prototype.push=function(){for(var b=this,c=j.call(arguments),d=0;d<c.length;d++)!function(b,c){a._gaq.push(function(){c._execute.call(c,b)})}(c[d],b)},a._gas=_gas=new c,_gas.push(["_addHook","_trackException",function(a,b){return _gas.push(["_trackEvent","Exception "+(a.name||"Error"),b||a.message||a,l]),!1}]),_gas.push(["_addHook","_setDebug",function(a){_gas.debug_mode=!!a}]),_gas.push(["_addHook","_popHook",function(a){var b=_gas._hooks[a];return b&&b.pop&&b.pop(),!1}]),_gas.push(["_addHook","_gasSetDefaultTracker",function(a){return _gas._default_tracker=a,!1}]);_gas._queue.length>0;)_gas.push(_gas._queue.shift());"undefined"==typeof a._gat&&!function(){var a=h.getElementByID("gas-script"),b=h.createElement("script");b.type="text/javascript",b.async=!0,b.src=null!==a&&"true"===a.getAttribute("data-use-dcjs")?("https:"===h.location.protocol?"https://":"http://")+"stats.g.doubleclick.net/dc.js":("https:"===h.location.protocol?"https://ssl":"http://www")+".google-analytics.com/ga.js";var c=h.getElementsByTagName("script")[0];c.parentNode.insertBefore(b,c)}()}}(window);
/**
 * @preserve Copyright 2011, Cardinal Path and DigitalInc.
 *
 * GAS - Google Analytics on Steroids
 * https://github.com/CardinalPath/gas
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 * Licensed under the GPLv3 license.
 */
(function(window, undefined) {

/**
 * GAS - Google Analytics on Steroids
 *
 * Helper Functions
 *
 * Copyright 2011, Cardinal Path and Direct Performance
 * Licensed under the MIT license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */

/**
 * GasHelper singleton class
 *
 * Should be called when ga.js is loaded to get the pageTracker.
 *
 * @constructor
 */
/*jshint -W079*/
var GasHelper = function () {
    this._setDummyTracker();
};
/*jshint +W079*/

GasHelper.prototype._setDummyTracker = function () {
    if (!this['tracker']) {
        var trackers = window['_gat']['_getTrackers']();
        if (trackers.length > 0) {
            this['tracker'] = trackers[0];
        }
    }
};

/**
 * Returns true if the element is found in the Array, false otherwise.
 *
 * @param {Array} obj Array to search at.
 * @param {object} item Item to search form.
 * @return {boolean} true if contains.
 */
GasHelper.prototype.inArray = function (obj, item) {
    if (obj && obj.length) {
        for (var i = 0; i < obj.length; i++) {
            if (obj[i] === item) {
                return true;
            }
        }
    }
    return false;
};

/**
 * Removes special characters and Lowercase String
 *
 * @param {string} str to be sanitized.
 * @param {boolean} strict_opt If we should remove any non ascii char.
 * @return {string} Sanitized string.
 */
GasHelper.prototype._sanitizeString = function (str, strict_opt) {
    str = str.toLowerCase()
        .replace(/^\ +/, '')
        .replace(/\ +$/, '')
        .replace(/\s+/g, '_')
        .replace(/[áàâãåäæª]/g, 'a')
        .replace(/[éèêëЄ€]/g, 'e')
        .replace(/[íìîï]/g, 'i')
        .replace(/[óòôõöøº]/g, 'o')
        .replace(/[úùûü]/g, 'u')
        .replace(/[碩]/g, 'c');

    if (strict_opt) {
        str = str.replace(/[^a-z0-9_\-]/g, '_');
    }
    return str.replace(/_+/g, '_');
};

/**
 * Cross Browser helper to addEventListener.
 *
 * ga_next.js currently have a _addEventListener directive. So _gas will
 * allways prefer that if available, and will use this one only as a fallback
 *
 * @param {HTMLElement} obj The Element to attach event to.
 * @param {string} evt The event that will trigger the binded function.
 * @param {function(event)} ofnc The function to bind to the element.
 * @param {boolean} bubble true if event should be fired at bubble phase.
 * Defaults to false. Works only on W3C compliant browser. MSFT don't support
 * it.
 * @return {boolean} true if it was successfuly binded.
 */
GasHelper.prototype._addEventListener = function (obj, evt, ofnc, bubble) {
    var fnc = function (event) {
        if (!event || !event.target) {
            event = window.event;
            event.target = event.srcElement;
        }
        return ofnc.call(obj, event);
    };
    // W3C model
    if (obj.addEventListener) {
        obj.addEventListener(evt, fnc, !!bubble);
        return true;
    }
    // M$ft model
    else if (obj.attachEvent) {
        return obj.attachEvent('on' + evt, fnc);
    }
    // Browser doesn't support W3C or M$ft model. Time to go old school
    else {
        evt = 'on' + evt;
        if (typeof obj[evt] === 'function') {
            // Object already has a function on traditional
            // Let's wrap it with our own function inside another function
            fnc = (function (f1, f2) {
                return function () {
                    f1.apply(this, arguments);
                    f2.apply(this, arguments);
                };
            }(obj[evt], fnc));
        }
        obj[evt] = fnc;
        return true;
    }
};

/**
 * Cross Browser Helper to emulate jQuery.live
 *
 * Binds to the document root. Listens to all events of the specific type.
 * If event don't bubble it won't catch
 */
GasHelper.prototype._liveEvent = function (tag, evt, ofunc) {
    var gh = this;
    tag = tag.toUpperCase();
    tag = tag.split(',');

    gh._addEventListener(document, evt, function (me) {
        for (var el = me.target; el.nodeName !== 'HTML';
            el = el.parentNode)
        {
            if (gh.inArray(tag, el.nodeName) || el.parentNode === null) {
                break;
            }
        }
        if (el && gh.inArray(tag, el.nodeName)) {
            ofunc.call(el, me);
        }

    }, true);
};

/**
 * Cross Browser DomReady function.
 *
 * Inspired by: http://dean.edwards.name/weblog/2006/06/again/#comment367184
 *
 * @param {function(Event)} callback DOMReady callback.
 * @return {boolean} Ignore return value.
 */
GasHelper.prototype._DOMReady = function (callback) {
    var scp = this;
    function cb() {
        if (cb.done) return;
        cb.done = true;
        callback.apply(scp, arguments);
    }
    if (/^(interactive|complete)/.test(document.readyState)) return cb();
    this._addEventListener(document, 'DOMContentLoaded', cb, false);
    this._addEventListener(window, 'load', cb, false);
};


/**
 * GAS - Google Analytics on Steroids
 *
 * Copyright 2011, Cardinal Path and Direct Performance
 * Licensed under the MIT license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */
 /*global document:true*/

/**
 * Google Analytics original _gaq.
 *
 * This never tries to do something that is not supposed to. So it won't break
 * in the future.
 */
window['_gaq'] = window['_gaq'] || [];

var _prev_gas = window['_gas'] || [];

// Avoid duplicate definition
if (_prev_gas._accounts_length >= 0) {
    return;
}

//Shortcuts, these speed up and compress the code
/*jshint -W079*/
var document = window.document,
    toString = Object.prototype.toString,
    hasOwn = Object.prototype.hasOwnProperty,
    push = Array.prototype.push,
    slice = Array.prototype.slice,
    trim = String.prototype.trim,
    sindexOf = String.prototype.indexOf,
    url = document.location.href,
    documentElement = document.documentElement;
/*jshint +W079*/
/**
 * GAS Sigleton
 * @constructor
 */
function GAS() {
    var self = this;
    self['version'] = '1.11.0';
    self._accounts = {};
    self._accounts_length = 0;
    self._queue = _prev_gas;
    self._default_tracker = '_gas1';
    self.gh = {};
    self._hooks = {
        '_addHook': [self._addHook]
    };
    // Need to be pushed to make sure tracker is done
    // Sets up helpers, very first thing pushed into gas
    self.push(function () {
        self.gh = new GasHelper();
    });
}

/**
 * First standard Hook that is responsible to add next Hooks
 *
 * _addHook calls always reurn false so they don't get pushed to _gaq
 * @param {string} fn The function you wish to add a Hook to.
 * @param {function()} cb The callback function to be appended to hooks.
 * @return {boolean} Always false.
 */
GAS.prototype._addHook = function (fn, cb) {
    if (typeof fn === 'string' && typeof cb === 'function') {
        if (typeof _gas._hooks[fn] === 'undefined') {
            _gas._hooks[fn] = [];
        }
        _gas._hooks[fn].push(cb);
    }
    return false;
};

/**
 * Construct the correct account name to be used on _gaq calls.
 *
 * The account name for the first unamed account pushed to _gas is the standard
 * account name. It's pushed without the account name to _gaq, so if someone
 * calls directly _gaq it works as expected.
 * @param {string} acct Account name.
 * @return {string} Correct account name to be used already with trailling dot.
 */
function _build_acct_name(acct) {
    return acct === _gas._default_tracker ? '' : acct + '.';
}

function _gaq_push(arr) {
    if (_gas.debug_mode) {
        try {
            console.log(arr);
        }catch (e) {}
    }
    return window['_gaq'].push(arr);
}

/**
 * Everything pushed to _gas is executed by this call.
 *
 * This function should not be called directly. Instead use _gas.push
 * @return {number} This is the same return as _gaq.push calls.
 */
GAS.prototype._execute = function () {
    var args = slice.call(arguments),
        self = this,
        sub = args.shift(),
        gaq_execute = true,
        i, foo, hooks, acct_name, repl_sub, return_val = 0;

    if (typeof sub === 'function') {
        // Pushed functions are executed right away
        return _gaq_push(
            (function (s, gh) {
                return function () {
                    // pushed functions receive helpers through this object
                    s.call(gh);
                };
            }(sub, self.gh))
        );

    } else if (typeof sub === 'object' && sub.length > 0) {
        foo = sub.shift();

        if (sindexOf.call(foo, '.') >= 0) {
            acct_name = foo.split('.')[0];
            foo = foo.split('.')[1];
        } else {
            acct_name = undefined;
        }

        // Execute hooks
        hooks = self._hooks[foo];
        if (hooks && hooks.length > 0) {
            for (i = 0; i < hooks.length; i++) {
                try {
                    repl_sub = hooks[i].apply(self.gh, sub);
                    if (repl_sub === false) {
                        // Returning false from a hook cancel the call
                        gaq_execute = false;
                    } else {
                        if (repl_sub && repl_sub.length > 0) {
                            // Returning an array changes the call parameters
                            sub = repl_sub;
                        }
                    }
                } catch (e) {
                    if (foo !== '_trackException') {
                        self.push(['_trackException', e]);
                    }
                }
            }
        }
        // Cancel execution on _gaq if any hook returned false
        if (gaq_execute === false) {
            return 1;
        }
        // Intercept _setAccount calls
        if (foo === '_setAccount') {

            for (i in self._accounts) {
                if (self._accounts[i] === sub[0]) {
                    // Repeated account
                    if (acct_name === undefined) {
                        return 1;
                    }
                }
            }
            acct_name = acct_name || '_gas' +
                String(self._accounts_length + 1);
            // Force that the first unamed account is _gas1
            if (typeof self._accounts['_gas1'] === 'undefined' &&
                sindexOf.call(acct_name, '_gas') !== -1) {
                acct_name = '_gas1';
            }
            self._accounts[acct_name] = sub[0];
            self._accounts_length += 1;
            acct_name = _build_acct_name(acct_name);
            return_val = _gaq_push([acct_name + foo, sub[0]]);
            // Must try t get the tracker if it's a _setAccount
            self.gh._setDummyTracker();
            return return_val;
        }

        // Intercept functions that can only be called once.
        if (foo === '_link' || foo === '_linkByPost' || foo === '_require' ||
            foo === '_anonymizeIp')
        {
            args = slice.call(sub);
            args.unshift(foo);
            return _gaq_push(args);
        }

        // If user provides account than trigger event for just that account.
        var acc_foo;
        if (acct_name && self._accounts[acct_name]) {
            acc_foo = _build_acct_name(acct_name) + foo;
            args = slice.call(sub);
            args.unshift(acc_foo);
            return _gaq_push(args);
        }

        // Call Original _gaq, for all accounts
        if (self._accounts_length > 0) {
            for (i in self._accounts) {
                if (hasOwn.call(self._accounts, i)) {
                    acc_foo = _build_acct_name(i) + foo;
                    args = slice.call(sub);
                    args.unshift(acc_foo);
                    return_val += _gaq_push(args);
                }
            }
        } else {
            // If there are no accounts we just push it to _gaq
            args = slice.call(sub);
            args.unshift(foo);
            return _gaq_push(args);
        }
        return return_val ? 1 : 0;
    }
};

/**
 * Standard method to execute GA commands.
 *
 * Everything pushed to _gas is in fact pushed back to _gaq. So Helpers are
 * ready for hooks. This creates _gaq as a series of functions that call
 * _gas._execute() with the same arguments.
 */
GAS.prototype.push = function () {
    var self = this;
    var args = slice.call(arguments);
    for (var i = 0; i < args.length; i++) {
        (function (arr, self) {
            window['_gaq'].push(function () {
                self._execute.call(self, arr);
            });
        }(args[i], self));
    }
};

/**
 * _gas main object.
 *
 * It's supposed to be used just like _gaq but here we extend it. In it's core
 * everything pushed to _gas is run through possible hooks and then pushed to
 * _gaq
 */
/*global _gas:true*/
window['_gas'] = _gas = new GAS();
/*global _gas:false*/


/**
 * Hook for _trackException
 *
 * Watchout for circular calls
 */
_gas.push(['_addHook', '_trackException', function (exception, message) {
    _gas.push(['_trackEvent',
        'Exception ' + (exception.name || 'Error'),
        message || exception.message || exception,
        url
    ]);
    return false;
}]);

/**
 * Hook to enable Debug Mode
 */
_gas.push(['_addHook', '_setDebug', function (set_debug) {
    _gas.debug_mode = !!set_debug;
}]);

/**
 * Hook to Remove other Hooks
 *
 * It will remove the last inserted hook from a _gas function.
 *
 * @param {string} func _gas Function Name to remove Hooks from.
 * @return {boolean} Always returns false.
 */
_gas.push(['_addHook', '_popHook', function (func) {
    var arr = _gas._hooks[func];
    if (arr && arr.pop) {
        arr.pop();
    }
    return false;
}]);

/**
 * Hook to set the default tracker.
 *
 * The default tracker is the nameless tracker that is pushed into _gaq_push
 */
_gas.push(['_addHook', '_gasSetDefaultTracker', function (tname) {
    _gas._default_tracker = tname;
    return false;
}]);

/**
 * This is kept just for backward compatibility since it's now supported
 * natively in _gaq.
 */
_gas.push(['_addHook', '_trackPageview', function () {
    var args = slice.call(arguments);
    if (args.length >= 2 &&
        typeof args[0] === 'string' && typeof args[1] === 'string')
    {
        return [{
            'page': args[0],
            'title': args[1]
        }];
    }
    return args;
}]);


/**
 * GAS - Google Analytics on Steroids
 *
 * Download Tracking Plugin
 *
 * Copyright 2011, Cardinal Path and Direct Performance
 * Licensed under the GPLv3 license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */

/**
 * Extracts the file extension and check it against a list
 *
 * Will extract the extensions from a url and check if it matches one of
 * possible options. Used to verify if a url corresponds to a download link.
 *
 * @this {GasHelper} GA Helper object.
 * @param {string} src The url to check.
 * @param {Array} extensions an Array with strings containing the possible
 * extensions.
 * @return {boolean|string} the file extension or false.
 */
function _checkFile(src, extensions) {
    if (typeof src !== 'string') {
        return false;
    }
    var ext = src.split('?')[0];
    ext = ext.split('.');
    ext = ext[ext.length - 1];
    if (ext && this.inArray(extensions, ext)) {
        return ext;
    }
    return false;
}

/**
 * Register the event to listen to downloads
 *
 * @this {GasHelper} GA Helper object.
 * @param {Array|object} opts List of possible extensions for download
 * links.
 */
var _trackDownloads = function (opts) {
    var gh = this;

    if (!gh._downloadTracked) {
        gh._downloadTracked = true;
    } else {
        //Oops double tracking detected.
        return;
    }
    if (!opts) {
        opts = {'extensions': []};
    } else if (typeof opts === 'string') {
        // support legacy opts as String of extensions
        opts = {'extensions': opts.split(',')};
    } else if (opts.length >= 1) {
        // support legacy opts Array of extensions
        opts = {'extensions': opts};
    }
    opts['category'] = opts['category'] || 'Download';

    var ext = 'xls,xlsx,doc,docx,ppt,pptx,pdf,txt,zip';
    ext += ',rar,7z,exe,wma,mov,avi,wmv,mp3,csv,tsv';
    ext = ext.split(',');
    opts['extensions'] = opts['extensions'].concat(ext);

    gh._liveEvent('a', 'mousedown', function (e) {
        var el = this;
        if (el.href) {
            var ext = _checkFile.call(gh,
                el.href, opts['extensions']
            );
            if (ext) {
                _gas.push(['_trackEvent',
                    opts['category'], ext, el.href
                ]);
            }
        }
    });
    return false;
};

/**
 * GAA Hook, receive the extensions to extend default extensions. And trigger
 * the binding of the events.
 *
 * @param {string|Array|object} opts GAs Options. Also backward compatible
 * with array or string of extensions.
 */
_gas.push(['_addHook', '_gasTrackDownloads', _trackDownloads]);

// Old API to be deprecated on v2.0
_gas.push(['_addHook', '_trackDownloads', _trackDownloads]);


/**
 * GAS - Google Analytics on Steroids
 *
 * Ecommerce Meta
 *
 * Copyright 2012, Cardinal Path and Direct Performance
 * Licensed under the GPLv3 license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */

function _gasMetaEcommerce() {
    var i, meta,
        f_trans = 0,
        f_item = 0,
        metas = document.getElementsByTagName('meta');
    for (i = 0; i < metas.length; i++) {
        if (metas[i].name === 'ga_trans') {
            // Fire transaction
            meta = metas[i].content.split('^');
            if (meta.length < 3) {
                // 3 is the minimum for transaction
                break;
            }
            // Add default values for remaining params
            while (meta.length < 8) {
                meta.push('');
            }
            _gas.push(['_addTrans',
                    meta[0],
                    meta[1],
                    meta[2],
                    meta[3],
                    meta[4],
                    meta[5],
                    meta[6],
                    meta[7]
                    ]);
            f_trans++;
        }
        else if (metas[i].name === 'ga_item') {
            // Fire item
            meta = metas[i].content.split('^');
            if (meta.length === 6) {
                _gas.push(['_addItem',
                        meta[0],
                        meta[1],
                        meta[2],
                        meta[3],
                        meta[4],
                        meta[5]
                        ]);
                f_item++;
            }
        }
    }
    if (f_trans > 0 && f_item > 0) {
        _gas.push(['_trackTrans']);
        //_gas.push(['_clearTrans']);
    }
}

_gas.push(['_addHook', '_gasMetaEcommerce', _gasMetaEcommerce]);


/**
 * Hook to sanity check trackEvents
 *
 * The value is rounded and parsed to integer.
 * Negative values are sent as zero.
 * If val is NaN than it is sent as zero.
 */
_gas.push(['_addHook', '_trackEvent', function () {
    var args = slice.call(arguments);
    if (args[3]) {
        args[3] = (args[3] < 0 ? 0 : Math.round(args[3])) || 0;
    }
    return args;
}]);


/**
 * GAS - Google Analytics on Steroids
 *
 * Form Tracking Plugin
 *
 * Copyright 2011, Cardinal Path and Direct Performance
 * Licensed under the GPLv3 license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */

/**
 * get the form name for a specific elemet
 *
 * @param {DOMElemet} el Dom Element.
 * @return {String} Form Name or Id.
 */
function getFormName(el) {
    while (el && el.nodeName !== 'HTML') {
        if (el.nodeName === 'FORM') {break; }
        el = el.parentNode;
    }
    if (el.nodeName === 'FORM') {
        return el.name || el.id || 'none';
    }
    return 'none';
}

var _gasTrackForms = function (opts) {
    if (!this._formTracked) {
        this._formTracked = true;
    } else {
        //Oops double tracking detected.
        return;
    }
    var scp = this;
    if (typeof opts !== 'object') {
        opts = {};
    }

    // Make sure required attrs are defined or fallback to default
    opts['category'] = opts['category'] || 'Form Tracking';
    //opts['live'] = opts['live'] || true; //Ignored

    var trackField = function (e) {
        var el = e.target,
            el_name = el.name || el.id || el.type || el.nodeName,
            form_name = getFormName(el),
            action = 'form (' + form_name + ')',
            label = el_name + ' (' + e.type + ')';

        _gas.push(['_trackEvent', opts['category'], action, label]);
    };

    scp._DOMReady(function () {
        var changeTags = ['input', 'select', 'textarea', 'hidden'];
        var submitTags = ['form'];
        var elements = [];
        var i, j;
        for (i = 0; i < changeTags.length; i++) {
            elements = document.getElementsByTagName(changeTags[i]);
            for (j = 0; j < elements.length; j++) {
                scp._addEventListener(elements[j], 'change', trackField);
            }
        }
        for (i = 0; i < submitTags.length; i++) {
            elements = document.getElementsByTagName(submitTags[i]);
            for (j = 0; j < elements.length; j++) {
                scp._addEventListener(elements[j], 'submit', trackField);
            }
        }
    });
};

_gas.push(['_addHook', '_gasTrackForms', _gasTrackForms]);

// Old API to be deprecated on v2.0
_gas.push(['_addHook', '_trackForms', _gasTrackForms]);

/**
 * GAS - Google Analytics on Steroids
 *
 * HTML5 Video Tracking Plugin
 *
 * Copyright 2011, Cardinal Path
 * Licensed under the GPLv3 license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */

/**
 * Triggers the actual video/audio GA events
 *
 * To be used as a callback for the HTML5 media events
 *
 * @param {Event} e A reference to the HTML event fired.
 * @this {HTMLMediaElement} The HTML element firing the event
 */
function _trackMediaElement(e) {
    _gas.push(['_trackEvent', this.tagName, e.type, this.currentSrc]);
}

/**
 * Triggers the HTML5 Video Tracking on the page

 * @param {String} tag Either 'audio' or 'video'.
 * @this {GasHelper} GA Helper object.
 */
var _trackMedia = function (tag) {
    var self = this;
    self._liveEvent(tag, 'play', _trackMediaElement);
    self._liveEvent(tag, 'pause', _trackMediaElement);
    self._liveEvent(tag, 'ended', _trackMediaElement);
};

var _trackVideo = function () {
    if (!this._videoTracked) {
        this._videoTracked = true;
    } else {
        //Oops double tracking detected.
        return;
    }
    _trackMedia.call(this, 'video');
};

var _trackAudio = function () {
    if (!this._audioTracked) {
        this._audioTracked = true;
    } else {
        //Oops double tracking detected.
        return;
    }
    _trackMedia.call(this, 'audio');
};

_gas.push(['_addHook', '_gasTrackVideo', _trackVideo]);
_gas.push(['_addHook', '_gasTrackAudio', _trackAudio]);

// Old API to be deprecated on v2.0
_gas.push(['_addHook', '_trackVideo', _trackVideo]);
_gas.push(['_addHook', '_trackAudio', _trackAudio]);


/**
 * GAS - Google Analytics on Steroids
 *
 * HTML Markup Plugin
 *
 * Copyright 2012, Cardinal Path and Direct Performance
 * Licensed under the GPLv3 license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */

/**
 * Sets Default pagename and Custom Vars based on Meta
 *
 * If a meta name='ga_vpv' is availalbe on the page use that as a page
 * replacement if the pageview is not passed as parameter.
 *
 * If meta name="ga_custom_var" the 4 values for a custom var must be on
 * content separated by a caret (^).
 */
function _gasMeta() {
    var i, meta,
        metas = document.getElementsByTagName('meta');
    for (i = 0; i < metas.length; i++) {
        if (metas[i].name === 'ga_vpv') {
            meta = metas[i].content;
            (function (vpv) {
                window._gas.push(['_addHook', '_trackPageview', function (p) {
                    if (p === undefined) {
                        return [vpv];
                    }
                }]);
            }(meta));
        } else if (metas[i].name === 'ga_custom_var') {
            meta = metas[i].content.split('^');
            if (meta.length === 4) {
                window._gas.push(['_setCustomVar',
                    parseInt(meta[0], 10),
                    meta[1],
                    meta[2],
                    parseInt(meta[3], 10)
                ]);
            }
        }
    }
}

/**
 * Listens to all clicks and looks for a tagged element on it.
 *
 * Events have the following params:
 *   x-ga-event-category (required) – The category of the event specified in
 * the solution design document
 *   x-ga-event-action (required) – The action of the event specified in the
 * solution design document
 *   x-ga-event-label (optional) – The label of the event specified in the
 * solution design document.  If no label is specified in the solution design
 * document, this attribute can be omitted
 *   x-ga-event-value (optional) – The value (integer) of the event specified
 * in the solution design document.  If no value is specified in the solution
 * design document, this attribute can be omitted
 *   x-ga-event-noninteractive (optional) – Boolean (true/false) value
 * specified in the solution design document.  If the non-interactive value is
 * not specified, this attribute can be omitted
 *
 * Social Actions have the following params:
 *   x-ga-social-network (required) – The network of the social interaction
 * specified in the solution design document
 *   x-ga-social-action (required) – The action of the social interaction
 * specified in the solution design document
 *   x-ga-social-target (optional) – The target of the social interaction
 * specified in the solution design document.  If no target is specified, this
 * attribute can be omitted
 *   x-ga-social-pagepath (optional) – The page path of the social interaction
 * specified in the solution design document.  If no page path is specified,
 * this attribute can be omitted
 */
function _gasHTMLMarkup() {
    var gh = this;

    gh._addEventListener(document, 'mousedown', function (me) {
        var el;
        for (el = me.target; el.nodeName !== 'HTML';
             el = el.parentNode) {
            if (el.getAttribute('x-ga-event-category')) {
                // Event element clicked, fire the _trackEvent
                window._gas.push(['_trackEvent',
                  el.getAttribute('x-ga-event-category'),
                  el.getAttribute('x-ga-event-action'),
                  el.getAttribute('x-ga-event-label') || undefined,
                  parseInt(el.getAttribute('x-ga-event-value'), 10) || 0,
                  el.getAttribute('x-ga-event-noninteractive') === 'true' ? true : false
                ]);
            }
            if (el.getAttribute('x-ga-social-network')) {
                // Social Action Clicked fire _trackSocial
                window._gas.push(['_trackSocial',
                  el.getAttribute('x-ga-social-network'),
                  el.getAttribute('x-ga-social-action'),
                  el.getAttribute('x-ga-social-target') || undefined,
                  el.getAttribute('x-ga-social-pagepath') || undefined
                ]);
            }

            if (el.parentNode === null) {
                break;
            }
        }
    }, true);
}

_gas.push(['_addHook', '_gasMeta', _gasMeta]);
_gas.push(['_addHook', '_gasHTMLMarkup', _gasHTMLMarkup]);


/**
 * GAS - Google Analytics on Steroids
 *
 * MailTo tracking plugin
 *
 * Copyright 2011, Cardinal Path and Direct Performance
 * Licensed under the GPLv3 license.
 */

/**
 * GAS plugin to track mailto: links
 *
 * @param {object} opts GAS Options.
 */
var _gasTrackMailto = function (opts) {
    if (!this._mailtoTracked) {
        this._mailtoTracked = true;
    } else {
        //Oops double tracking detected.
        return;
    }

    if (!opts) {
        opts = {};
    }
    opts['category'] = opts['category'] || 'Mailto';

    this._liveEvent('a', 'mousedown', function (e) {
        var el = e.target;
        if (el && el.href && el.href.toLowerCase &&
          sindexOf.call(el.href.toLowerCase(), 'mailto:') === 0) {
            _gas.push(['_trackEvent', opts['category'], el.href.substr(7)]);
        }
    });
    return false;
};
_gas.push(['_addHook', '_gasTrackMailto', _gasTrackMailto]);

// Old API to be deprecated on v2.0
_gas.push(['_addHook', '_trackMailto', _gasTrackMailto]);


/**
 * GAS - Google Analytics on Steroids
 *
 * Max-Scroll Tracking Plugin
 *
 * Copyright 2011, Cardinal Path and Direct Performance
 * Licensed under the GPLv3 license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */

var _maxScrollOpts;

/**
 * Get current browser viewpane heigtht
 *
 * @return {number} height.
 */
function _get_window_height() {
    return window.innerHeight || documentElement.clientHeight ||
        document.body.clientHeight || 0;
}

/**
 * Get current absolute window scroll position
 *
 * @return {number} YScroll.
 */
function _get_window_Yscroll() {
    return window.pageYOffset || document.body.scrollTop ||
        documentElement.scrollTop || 0;
}

/**
 * Get current absolute document height
 *
 * @return {number} Current document height.
 */
function _get_doc_height() {
    return Math.max(
        document.body.scrollHeight || 0, documentElement.scrollHeight || 0,
        document.body.offsetHeight || 0, documentElement.offsetHeight || 0,
        document.body.clientHeight || 0, documentElement.clientHeight || 0
    );
}


/**
 * Get current vertical scroll percentage
 *
 * @return {number} Current vertical scroll percentage.
 */
function _get_scroll_percentage() {
    return (
        (_get_window_Yscroll() + _get_window_height()) / _get_doc_height()
    ) * 100;
}

var _t = null;
var _max_scroll = 0;
function _update_scroll_percentage(now) {
    if (_t) {
        clearTimeout(_t);
    }
    if (now === true) {
        _max_scroll = Math.max(_get_scroll_percentage(), _max_scroll);
        return;
    }
    _t = setTimeout(function () {
        _max_scroll = Math.max(_get_scroll_percentage(), _max_scroll);
    }, 400);
}

function _sendMaxScroll() {
    _update_scroll_percentage(true);
    _max_scroll = Math.floor(_max_scroll);
    if (_max_scroll <= 0 || _max_scroll > 100) return;
    var bucket = (_max_scroll > 10 ? 1 : 0) * (
        Math.floor((_max_scroll - 1) / 10) * 10 + 1
    );
    bucket = String(bucket) + '-' +
        String(Math.ceil(_max_scroll / 10) * 10);

    _gas.push(['_trackEvent',
        _maxScrollOpts['category'],
        url,
        bucket,
        Math.floor(_max_scroll),
        true // non-interactive
    ]);
}

/**
 * Tracks the max Scroll on the page.
 *
 * @param {object} opts GAS Options to be used.
 * @this {GasHelper} The Ga Helper object
 */
function _trackMaxScroll(opts) {
    if (!this._maxScrollTracked) {
        this._maxScrollTracked = true;
    } else {
        //Oops double tracking detected.
        return;
    }
    _maxScrollOpts = opts || {};
    _maxScrollOpts['category'] = _maxScrollOpts['category'] || 'Max Scroll';

    this._addEventListener(window, 'scroll', _update_scroll_percentage);
    this._addEventListener(window, 'beforeunload', _sendMaxScroll);
}

_gas.push(['_addHook', '_gasTrackMaxScroll', _trackMaxScroll]);

// Old API to be deprecated on v2.0
_gas.push(['_addHook', '_trackMaxScroll', _trackMaxScroll]);


/**
 * GAS - Google Analytics on Steroids
 *
 * Multi-Domain Tracking Plugin
 *
 * Copyright 2011, Cardinal Path and Direct Performance
 * Licensed under the GPLv3 license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */

/**
 * Private variable to store allowAnchor choice
 */
_gas._allowAnchor = false;

/**
 * _setAllowAnchor Hook to store choice for easier use of Anchor
 *
 * This stored value is used on _getLinkerUrl, _link and _linkByPost so it's
 * used the same by default
 */
_gas.push(['_addHook', '_setAllowAnchor', function (val) {
    _gas._allowAnchor = !!val;
}]);

/**
 * _link Hook to use stored allowAnchor value.
 */
_gas.push(['_addHook', '_link', function (url, use_anchor) {
    if (use_anchor === undefined) {
        use_anchor = _gas._allowAnchor;
    }
    return [url, use_anchor];
}]);

/**
 * _linkByPost Hook to use stored allowAnchor value.
 */
_gas.push(['_addHook', '_linkByPost', function (url, use_anchor) {
    if (use_anchor === undefined) {
        use_anchor = _gas._allowAnchor;
    }
    return [url, use_anchor];
}]);

/**
 * Store all domains pushed by _setDomainName that don't match current domain.
 *
 * @type {Array.<string>}
 */
var _external_domains = [];

/**
 * Store the internal domain name
 *
 * @type string
 */
var _internal_domain;

/**
 * _setDomainName Hook to add pushed domains to _external_domains if it doesn't
 * match current domain.
 *
 * This Hook let you call _setDomainName multiple times. So _gas will only
 * apply the one that matches the current domain and the other ones will be
 * used to track external domains with cookie data.
 */
_gas.push(['_addHook', '_setDomainName', function (domainName) {
    if (sindexOf.call('.' + document.location.hostname, domainName) < 0) {
        _external_domains.push(domainName);
        return false;
    }
    _internal_domain = domainName;
}]);

/**
 * _addExternalDomainName Hook.
 *
 * This hook let you add external domains so that urls on current page to this
 * domain are marked to send cookies.
 * You should use _setDomainName for this in most of the cases.
 */
_gas.push(['_addHook', '_addExternalDomainName', function (domainName) {
    _external_domains.push(domainName);
    return false;
}]);

/**
 * Function to mark links on the current pages to send links
 *
 * This function is used to make it easy to implement multi-domain-tracking.
 * @param {string} event_used Should be 'now', 'click' or 'mousedown'. Default
 * 'click'.
 * @this {GasHelper} GAS Helper functions
 * @return {boolean} Returns false to avoid this is puhed to _gaq.
 */
function track_links(event_used) {
    if (!this._multidomainTracked) {
        this._multidomainTracked = true;
    } else {
        //Oops double tracking detected.
        return;
    }
    var internal = document.location.hostname,
        gh = this,
        i, j, el,
        links = document.getElementsByTagName('a');
    if (event_used !== 'now' && event_used !== 'mousedown') {
        event_used = 'click';
    }
    for (i = 0; i < links.length; i++) {
        el = links[i];
        if (sindexOf.call(el.href, 'http') === 0) {
            // Check to see if it's a internal link
            if (el.hostname === internal ||
              sindexOf.call(el.hostname, _internal_domain) >= 0) {
                continue;
            }
            // Tag external Links either now or on mouse event.
            for (j = 0; j < _external_domains.length; j++) {
                if (sindexOf.call(el.hostname, _external_domains[j]) >= 0) {
                    if (event_used === 'now') {
                        el.href = gh['tracker']['_getLinkerUrl'](
                            el.href,
                            _gas._allowAnchor
                        );
                    } else {
                        if (event_used === 'click') {
                            this._addEventListener(el, event_used, function (e) {
                                if (this.target && this.target === '_blank') {
                                    window.open(
                                        gh['tracker']['_getLinkerUrl'](
                                            this.href, _gas._allowAnchor
                                        )
                                    );
                                } else {
                                    _gas.push(
                                        ['_link', this.href, _gas._allowAnchor]
                                    );
                                }
                                if (e.preventDefault)
                                    e.preventDefault();
                                else
                                    e.returnValue = false;
                                return false; //needed for ie7
                            });
                        } else {
                            this._addEventListener(el, event_used, function () {
                                this.href = gh['tracker']['_getLinkerUrl'](
                                    this.href,
                                    _gas._allowAnchor
                                );
                            });
                        }
                    }
                }
            }
        }
    }
    return false;
}

var _gasMultiDomain = function () {
    var gh = this;
    var args = slice.call(arguments);
    if (gh && gh._DOMReady) {
        gh._DOMReady(function () {
            track_links.apply(gh, args);
        });
    }
};

/**
 * Registers Hook to _setMultiDomain
 */
_gas.push(['_addHook', '_gasMultiDomain', _gasMultiDomain]);

// Old API to be deprecated on v2.0
_gas.push(['_addHook', '_setMultiDomain', _gasMultiDomain]);


/**
 * GAS - Google Analytics on Steroids
 *
 * Outbound Link Tracking Plugin
 *
 * Copyright 2011, Cardinal Path and Direct Performance
 * Licensed under the GPLv3 license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */

/**
 * Triggers the Outbound Link Tracking on the page
 *
 * @this {object} GA Helper object.
 * @param {object} opts Custom options for Outbound Links.
 */
var _gasTrackOutboundLinks = function (opts) {
    if (!this._outboundTracked) {
        this._outboundTracked = true;
    } else {
        //Oops double tracking detected.
        return;
    }
    var gh = this;
    if (!opts) {
        opts = {};
    }
    opts['category'] = opts['category'] || 'Outbound';

    gh._liveEvent('a', 'mousedown', function (e) {
        var l = this;
        if (
            (l.protocol === 'http:' || l.protocol === 'https:') &&
            sindexOf.call(l.hostname, document.location.hostname) === -1)
        {
            var path = (l.pathname + l.search + ''),
                utm = sindexOf.call(path, '__utm');
            if (utm !== -1) {
                path = path.substring(0, utm);
            }
            _gas.push(['_trackEvent',
                opts['category'],
                l.hostname,
                path
            ]);
        }

    });
};

_gas.push(['_addHook', '_gasTrackOutboundLinks', _gasTrackOutboundLinks]);

// Old API to be deprecated on v2.0
_gas.push(['_addHook', '_trackOutboundLinks', _gasTrackOutboundLinks]);



/**
 * GAS - Google Analytics on Steroids
 *
 * Vimeo Video Tracking Plugin
 *
 * Copyright 2011, Cardinal Path and Direct Performance
 * Licensed under the GPLv3 license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */

var _vimeoTimeTriggers = [];
var _vimeoPoolMaps = {};

/**
 * Cached urls for vimeo players on the page.
 *
 * @type {object}
 */
var _vimeo_urls = {};

function _vimeoPool(data) {
    if (!_vimeoPoolMaps[data.player_id]) {
        _vimeoPoolMaps[data.player_id] = {};
        _vimeoPoolMaps[data.player_id].timeTriggers = slice.call(
            _vimeoTimeTriggers
        );
    }
    if (_vimeoPoolMaps[data.player_id].timeTriggers.length > 0) {
        if (data.data.percent * 100 >=
            _vimeoPoolMaps[data.player_id].timeTriggers[0])
        {
            var action = _vimeoPoolMaps[data.player_id].timeTriggers.shift();
            _gas.push([
                '_trackEvent',
                'Vimeo Video',
                action + '%',
                _vimeo_urls[data.player_id]
            ]);
        }
    }
}

/**
 * Helper function to post messages to a vimeo player
 *
 * @param {string} method The method from the vimeo API.
 * @param {string} params to be passed as the value of the method.
 * @param {object} target Iframe DOM Element for the Vimeo player.
 * @return {boolean} true if it worked or false otherwise.
 */
function _vimeoPostMessage(method, params, target) {
    if (!target.contentWindow || !target.contentWindow.postMessage || !JSON) {
        return false;
    }
    var url = target.getAttribute('src').split('?')[0],
        data = JSON.stringify({
            method: method,
            value: params
        });
    target.contentWindow.postMessage(data, url);
    return true;
}


/**
 * Flag that indicates if the global listener has been bind to the window
 * @type {boolean}
 */
var _has_vimeo_window_event = false;

var _vimeoOpts;

/**
 * postMessage Listener
 * @param {Object} event The Vimeo API return event.
 */
/*jshint latedef:false*/
function _vimeoPostMessageListener(event) {
    if (sindexOf.call(event.origin, '//player.vimeo.com') > -1) {
        var data = JSON.parse(event.data);
        if (data.event === 'ready') {
            _trackVimeo.call(_gas.gh); // Force rerun since a player is ready
        } else if (data.method) {
            if (data.method === 'getVideoUrl') {
                _vimeo_urls[data.player_id] = data.value;
            }
        } else if (data.event === 'playProgress') {
            _vimeoPool(data);
        } else {
            _gas.push(['_trackEvent', _vimeoOpts['category'],
                data.event, _vimeo_urls[data.player_id]]);
        }
    }

}
/*jshint latedef:true*/

/**
 * Triggers the Vimeo Tracking on the page
 *
 * Only works for the Universal Tag from Vimeo (iframe). The video must have
 * the parameter api=1 on the url in order to make the tracking work.
 *
 * @this {GasHelper} GA Helper object.
 */
function _trackVimeo() {
    var iframes = document.getElementsByTagName('iframe');
    var vimeo_videos = 0;
    var player_id;
    var player_src;
    var separator;
    var force = _vimeoOpts['force'];
    var partials = _vimeoOpts['percentages'];
    for (var i = 0; i < iframes.length; i++) {
        if (sindexOf.call(iframes[i].src, '//player.vimeo.com') > -1) {
            player_id = 'gas_vimeo_' + i;
            player_src = iframes[i].src;
            separator = '?';
            if (sindexOf.call(player_src, '?') > -1) {
                separator = '&';
            }
            if (sindexOf.call(player_src, 'api=1') < 0) {
                if (force) {
                    // Reload the video enabling the api
                    player_src += separator + 'api=1&player_id=' + player_id;
                } else {
                    // We won't track players that don't have api enabled.
                    continue;
                }
            } else {
                if (sindexOf.call(player_src, 'player_id=') < -1) {
                    player_src += separator + 'player_id=' + player_id;
                }
            }
            vimeo_videos++;
            iframes[i].id = player_id;
            if (iframes[i].src !== player_src) {
                iframes[i].src = player_src;
                break; // break to wait until it is ready since we reloaded it.
            }
            // We need to cache the video url since vimeo won't provide it
            // in the event
            _vimeoPostMessage('getVideoUrl', '', iframes[i]);
            _vimeoPostMessage('addEventListener', 'play', iframes[i]);
            _vimeoPostMessage('addEventListener', 'pause', iframes[i]);
            _vimeoPostMessage('addEventListener', 'finish', iframes[i]);
            if (partials) {
                _vimeoTimeTriggers = partials;
                _vimeoPostMessage('addEventListener', 'playProgress',
                    iframes[i]);
            }
        }
    }
    if (vimeo_videos > 0 && _has_vimeo_window_event === false) {
        this._addEventListener(window, 'message',
            _vimeoPostMessageListener, false
        );
        _has_vimeo_window_event = true;
    }
}

var _gasTrackVimeo = function (opts) {
    var gh = this;
    // Support
    if (typeof opts === 'boolean' || opts === 'force') {
        opts = {'force': !!opts};
    }
    opts = opts || {};
    opts['category'] = opts['category'] || 'Vimeo Video';
    opts['percentages'] = opts['percentages'] || [];
    opts['force'] = opts['force'] || false;
    _vimeoOpts = opts;
    gh._DOMReady(function () {
        _trackVimeo.call(gh);
    });
    return false;
};

_gas.push(['_addHook', '_gasTrackVimeo', _gasTrackVimeo]);

// Old API to be deprecated on v2.0
_gas.push(['_addHook', '_trackVimeo', _gasTrackVimeo]);


/**
 * GAS - Google Analytics on Steroids
 *
 * YouTube Video Tracking Plugin
 *
 * Copyright 2011, Cardinal Path and Direct Performance
 * Licensed under the GPLv3 license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */

/**
 * Array of percentage to fire events.
 */
var _ytTimeTriggers = [];
var _ytOpts;


/**
 * Used to map each vid to a set of timeTriggers and it's pool timer
 */
var _ytPoolMaps = {};

function _ytPool(target, hash) {
    if (_ytPoolMaps[hash] === undefined ||
        _ytPoolMaps[hash].timeTriggers.length <= 0) {
        return false;
    }
    var p = target['getCurrentTime']() / target['getDuration']() * 100;
    if (p >= _ytPoolMaps[hash].timeTriggers[0]) {
        var action = _ytPoolMaps[hash].timeTriggers.shift();
        _gas.push([
            '_trackEvent',
            _ytOpts['category'],
            action + '%',
            target['getVideoUrl']()
        ]);
    }
    _ytPoolMaps[hash].timer = setTimeout(_ytPool, 1000, target, hash);
}

function _ytStopPool(target) {
    var h = target['getVideoUrl']();
    if (_ytPoolMaps[h] && _ytPoolMaps[h].timer) {
        _ytPool(target, h); // Pool one last time before clearing it.
        clearTimeout(_ytPoolMaps[h].timer);
    }
}

function _ytStartPool(target) {
    if (_ytTimeTriggers && _ytTimeTriggers.length) {
        var h = target['getVideoUrl']();
        if (_ytPoolMaps[h]) {
            _ytStopPool(target);
        } else {
            _ytPoolMaps[h] = {};
            _ytPoolMaps[h].timeTriggers = slice.call(_ytTimeTriggers);
        }
        _ytPoolMaps[h].timer = setTimeout(_ytPool, 1000, target, h);
    }
}


/**
 * Called when the Video State changes
 *
 * We are currently tracking only finish, play and pause events
 *
 * @param {Object} event the event passed by the YT api.
 */
function _ytStateChange(event) {
    var action = '';
    switch (event['data']) {
    case 0:
        action = 'finish';
        _ytStopPool(event['target']);
        break;
    case 1:
        action = 'play';
        _ytStartPool(event['target']);
        break;
    case 2:
        action = 'pause';
        _ytStopPool(event['target']);
        break;
    }
    if (action) {
        _gas.push(['_trackEvent',
            _ytOpts['category'], action, event['target']['getVideoUrl']()
        ]);
    }
}

/**
 * Called when the player fires an Error Event
 *
 * @param {Object} event the event passed by the YT api.
 */
function _ytError(event) {
    _gas.push(['_trackEvent',
        _ytOpts['category'],
        'error (' + event['data'] + ')',
        event['target']['getVideoUrl']()
    ]);
}

/**
 * Looks for object/embed youtube videos and migrate them to the iframe method
 *  so it tries to track them
 */
function _ytMigrateObjectEmbed() {
    var objs = document.getElementsByTagName('object');
    var pars, ifr, ytid;
    var r = /(https?:\/\/www\.youtube(-nocookie)?\.com[^\/]*).*\/v\/([^&?]+)/;
    for (var i = 0; i < objs.length; i++) {
        pars = objs[i].getElementsByTagName('param');
        for (var j = 0; j < pars.length; j++) {
            if (pars[j].name === 'movie' && pars[j].value) {
                // Replace the object with an iframe
                ytid = pars[j].value.match(r);
                if (ytid && ytid[1] && ytid[3]) {
                    ifr = document.createElement('iframe');
                    ifr.src = ytid[1] + '/embed/' + ytid[3] + '?enablejsapi=1';
                    ifr.width = objs[i].width;
                    ifr.height = objs[i].height;
                    ifr.setAttribute('frameBorder', '0');
                    ifr.setAttribute('allowfullscreen', '');
                    objs[i].parentNode.insertBefore(ifr, objs[i]);
                    objs[i].parentNode.removeChild(objs[i]);
                    // Since we removed the object the Array changed
                    i--;
                }
                break;
            }
        }
    }
}

/**
 * Triggers the YouTube Tracking on the page
 *
 * Only works for the iframe tag. The video must have the parameter
 * enablejsapi=1 on the url in order to make the tracking work.
 *
 * @param {(object)} opts GAS Options object.
 */
function _trackYoutube(opts) {
    var force = opts['force'];
    var opt_timeTriggers = opts['percentages'];
    if (force) {
        try {
            _ytMigrateObjectEmbed();
        }catch (e) {
            _gas.push(['_trackException', e,
                'GAS Error on youtube.js:_ytMigrateObjectEmbed'
            ]);
        }
    }

    var youtube_videos = [];
    var iframes = document.getElementsByTagName('iframe');
    for (var i = 0; i < iframes.length; i++) {
        if (sindexOf.call(iframes[i].src, '//www.youtube.com/embed') > -1) {
            if (sindexOf.call(iframes[i].src, 'enablejsapi=1') < 0) {
                if (force) {
                    // Reload the video enabling the api
                    if (sindexOf.call(iframes[i].src, '?') < 0) {
                        iframes[i].src += '?enablejsapi=1';
                    } else {
                        iframes[i].src += '&enablejsapi=1';
                    }
                } else {
                    // We can't track players that don't have api enabled.
                    continue;
                }
            }
            youtube_videos.push(iframes[i]);
        }
    }
    if (youtube_videos.length > 0) {
        if (opt_timeTriggers && opt_timeTriggers.length) {
            _ytTimeTriggers = opt_timeTriggers;
        }
        // this function will be called when the youtube api loads
        window['onYouTubePlayerAPIReady'] = function () {
            var p;
            for (var i = 0; i < youtube_videos.length; i++) {
                p = new window['YT']['Player'](youtube_videos[i]);
                p.addEventListener('onStateChange', _ytStateChange);
                p.addEventListener('onError', _ytError);
            }
        };
        // load the youtube player api
        var tag = document.createElement('script');
        //XXX use document.location.protocol
        var protocol = 'http:';
        if (document.location.protocol === 'https:') {
            protocol = 'https:';
        }
        tag.src = protocol + '//www.youtube.com/player_api';
        tag.type = 'text/javascript';
        tag.async = true;
        var firstScriptTag = document.getElementsByTagName('script')[0];
        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    }
}

var _gasTrackYoutube = function (opts) {
    // Support for legacy parameters
    var args = slice.call(arguments);
    if (args[0] && (typeof args[0] === 'boolean' || args[0] === 'force')) {
        opts = {'force': !!args[0]};
        if (args[1] && args[1].length) {
            opts['percentages'] = args[1];
        }
    }

    opts = opts || {};
    opts['force'] = opts['force'] || false;
    opts['category'] = opts['category'] || 'YouTube Video';
    opts['percentages'] = opts['percentages'] || [];

    _ytOpts = opts;
    var gh = this;
    gh._DOMReady(function () {
        _trackYoutube.call(gh, opts);
    });
    return false;
};

_gas.push(['_addHook', '_gasTrackYoutube', _gasTrackYoutube]);

// Old API to be deprecated on v2.0
_gas.push(['_addHook', '_trackYoutube', _gasTrackYoutube]);


/**
 * Wrap-up
 */
// Execute previous functions
while (_gas._queue.length > 0) {
	_gas.push(_gas._queue.shift());
}

// Import ga.js
if (typeof window._gat === 'undefined') {
	(function () {
		var gasScript = document.getElementByID('gas-script');
		var ga = document.createElement('script');
		ga.type = 'text/javascript';
		ga.async = true;
		if (gasScript !== null && gasScript.getAttribute('data-use-dcjs') === 'true') {
			ga.src = (
				'https:' === document.location.protocol ?
				'https://' : 'http://') +
				'stats.g.doubleclick.net/dc.js';
		} else {
			ga.src = (
				'https:' === document.location.protocol ?
				'https://ssl' : 'http://www') +
				'.google-analytics.com/ga.js';
		}
		var s = document.getElementsByTagName('script')[0];
		s.parentNode.insertBefore(ga, s);
	}());
}

})(window);
/**
 * @preserve Copyright 2011, Cardinal Path and DigitalInc.
 *
 * GAS - Google Analytics on Steroids
 * https://github.com/CardinalPath/gas
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 * Licensed under the GPLv3 license.
 */
!function(a,b){function c(){var a=this;a.version="1.11.0",a._accounts={},a._accounts_length=0,a._queue=F,a._default_tracker="_gas1",a.gh={},a._hooks={_addHook:[a._addHook]},a.push(function(){a.gh=new E})}function d(a){return a===_gas._default_tracker?"":a+"."}function e(b){if(_gas.debug_mode)try{console.log(b)}catch(c){}return a._gaq.push(b)}function f(a,b){if("string"!=typeof a)return!1;var c=a.split("?")[0];return c=c.split("."),c=c[c.length-1],c&&this.inArray(b,c)?c:!1}function g(){var a,b,c=0,d=0,e=G.getElementsByTagName("meta");for(a=0;a<e.length;a++)if("ga_trans"===e[a].name){if(b=e[a].content.split("^"),b.length<3)break;for(;b.length<8;)b.push("");_gas.push(["_addTrans",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]]),c++}else"ga_item"===e[a].name&&(b=e[a].content.split("^"),6===b.length&&(_gas.push(["_addItem",b[0],b[1],b[2],b[3],b[4],b[5]]),d++));c>0&&d>0&&_gas.push(["_trackTrans"])}function h(a){for(;a&&"HTML"!==a.nodeName&&"FORM"!==a.nodeName;)a=a.parentNode;return"FORM"===a.nodeName?a.name||a.id||"none":"none"}function i(a){_gas.push(["_trackEvent",this.tagName,a.type,this.currentSrc])}function j(){var c,d,e=G.getElementsByTagName("meta");for(c=0;c<e.length;c++)"ga_vpv"===e[c].name?(d=e[c].content,function(c){a._gas.push(["_addHook","_trackPageview",function(a){return a===b?[c]:void 0}])}(d)):"ga_custom_var"===e[c].name&&(d=e[c].content.split("^"),4===d.length&&a._gas.push(["_setCustomVar",parseInt(d[0],10),d[1],d[2],parseInt(d[3],10)]))}function k(){var c=this;c._addEventListener(G,"mousedown",function(c){var d;for(d=c.target;"HTML"!==d.nodeName&&(d.getAttribute("x-ga-event-category")&&a._gas.push(["_trackEvent",d.getAttribute("x-ga-event-category"),d.getAttribute("x-ga-event-action"),d.getAttribute("x-ga-event-label")||b,parseInt(d.getAttribute("x-ga-event-value"),10)||0,"true"===d.getAttribute("x-ga-event-noninteractive")?!0:!1]),d.getAttribute("x-ga-social-network")&&a._gas.push(["_trackSocial",d.getAttribute("x-ga-social-network"),d.getAttribute("x-ga-social-action"),d.getAttribute("x-ga-social-target")||b,d.getAttribute("x-ga-social-pagepath")||b]),null!==d.parentNode);d=d.parentNode);},!0)}function l(){return a.innerHeight||L.clientHeight||G.body.clientHeight||0}function m(){return a.pageYOffset||G.body.scrollTop||L.scrollTop||0}function n(){return Math.max(G.body.scrollHeight||0,L.scrollHeight||0,G.body.offsetHeight||0,L.offsetHeight||0,G.body.clientHeight||0,L.clientHeight||0)}function o(){return 100*((m()+l())/n())}function p(a){return T&&clearTimeout(T),a===!0?(U=Math.max(o(),U),void 0):(T=setTimeout(function(){U=Math.max(o(),U)},400),void 0)}function q(){if(p(!0),U=Math.floor(U),!(0>=U||U>100)){var a=(U>10?1:0)*(10*Math.floor((U-1)/10)+1);a=String(a)+"-"+String(10*Math.ceil(U/10)),_gas.push(["_trackEvent",S.category,K,a,Math.floor(U),!0])}}function r(b){this._maxScrollTracked||(this._maxScrollTracked=!0,S=b||{},S.category=S.category||"Max Scroll",this._addEventListener(a,"scroll",p),this._addEventListener(a,"beforeunload",q))}function s(b){if(!this._multidomainTracked){this._multidomainTracked=!0;var c,d,e,f=G.location.hostname,g=this,h=G.getElementsByTagName("a");for("now"!==b&&"mousedown"!==b&&(b="click"),c=0;c<h.length;c++)if(e=h[c],0===J.call(e.href,"http")){if(e.hostname===f||J.call(e.hostname,V)>=0)continue;for(d=0;d<W.length;d++)J.call(e.hostname,W[d])>=0&&("now"===b?e.href=g.tracker._getLinkerUrl(e.href,_gas._allowAnchor):"click"===b?this._addEventListener(e,b,function(b){return this.target&&"_blank"===this.target?a.open(g.tracker._getLinkerUrl(this.href,_gas._allowAnchor)):_gas.push(["_link",this.href,_gas._allowAnchor]),b.preventDefault?b.preventDefault():b.returnValue=!1,!1}):this._addEventListener(e,b,function(){this.href=g.tracker._getLinkerUrl(this.href,_gas._allowAnchor)}))}return!1}}function t(a){if(_[a.player_id]||(_[a.player_id]={},_[a.player_id].timeTriggers=I.call($)),_[a.player_id].timeTriggers.length>0&&100*a.data.percent>=_[a.player_id].timeTriggers[0]){var b=_[a.player_id].timeTriggers.shift();_gas.push(["_trackEvent","Vimeo Video",b+"%",ab[a.player_id]])}}function u(a,b,c){if(!c.contentWindow||!c.contentWindow.postMessage||!JSON)return!1;var d=c.getAttribute("src").split("?")[0],e=JSON.stringify({method:a,value:b});return c.contentWindow.postMessage(e,d),!0}function v(a){if(J.call(a.origin,"//player.vimeo.com")>-1){var b=JSON.parse(a.data);"ready"===b.event?w.call(_gas.gh):b.method?"getVideoUrl"===b.method&&(ab[b.player_id]=b.value):"playProgress"===b.event?t(b):_gas.push(["_trackEvent",Z.category,b.event,ab[b.player_id]])}}function w(){for(var b,c,d,e=G.getElementsByTagName("iframe"),f=0,g=Z.force,h=Z.percentages,i=0;i<e.length;i++)if(J.call(e[i].src,"//player.vimeo.com")>-1){if(b="gas_vimeo_"+i,c=e[i].src,d="?",J.call(c,"?")>-1&&(d="&"),J.call(c,"api=1")<0){if(!g)continue;c+=d+"api=1&player_id="+b}else J.call(c,"player_id=")<-1&&(c+=d+"player_id="+b);if(f++,e[i].id=b,e[i].src!==c){e[i].src=c;break}u("getVideoUrl","",e[i]),u("addEventListener","play",e[i]),u("addEventListener","pause",e[i]),u("addEventListener","finish",e[i]),h&&($=h,u("addEventListener","playProgress",e[i]))}f>0&&bb===!1&&(this._addEventListener(a,"message",v,!1),bb=!0)}function x(a,c){if(fb[c]===b||fb[c].timeTriggers.length<=0)return!1;var d=100*(a.getCurrentTime()/a.getDuration());if(d>=fb[c].timeTriggers[0]){var e=fb[c].timeTriggers.shift();_gas.push(["_trackEvent",db.category,e+"%",a.getVideoUrl()])}fb[c].timer=setTimeout(x,1e3,a,c)}function y(a){var b=a.getVideoUrl();fb[b]&&fb[b].timer&&(x(a,b),clearTimeout(fb[b].timer))}function z(a){if(eb&&eb.length){var b=a.getVideoUrl();fb[b]?y(a):(fb[b]={},fb[b].timeTriggers=I.call(eb)),fb[b].timer=setTimeout(x,1e3,a,b)}}function A(a){var b="";switch(a.data){case 0:b="finish",y(a.target);break;case 1:b="play",z(a.target);break;case 2:b="pause",y(a.target)}b&&_gas.push(["_trackEvent",db.category,b,a.target.getVideoUrl()])}function B(a){_gas.push(["_trackEvent",db.category,"error ("+a.data+")",a.target.getVideoUrl()])}function C(){for(var a,b,c,d=G.getElementsByTagName("object"),e=/(https?:\/\/www\.youtube(-nocookie)?\.com[^\/]*).*\/v\/([^&?]+)/,f=0;f<d.length;f++){a=d[f].getElementsByTagName("param");for(var g=0;g<a.length;g++)if("movie"===a[g].name&&a[g].value){c=a[g].value.match(e),c&&c[1]&&c[3]&&(b=G.createElement("iframe"),b.src=c[1]+"/embed/"+c[3]+"?enablejsapi=1",b.width=d[f].width,b.height=d[f].height,b.setAttribute("frameBorder","0"),b.setAttribute("allowfullscreen",""),d[f].parentNode.insertBefore(b,d[f]),d[f].parentNode.removeChild(d[f]),f--);break}}}function D(b){var c=b.force,d=b.percentages;if(c)try{C()}catch(e){_gas.push(["_trackException",e,"GAS Error on youtube.js:_ytMigrateObjectEmbed"])}for(var f=[],g=G.getElementsByTagName("iframe"),h=0;h<g.length;h++)if(J.call(g[h].src,"//www.youtube.com/embed")>-1){if(J.call(g[h].src,"enablejsapi=1")<0){if(!c)continue;g[h].src+=J.call(g[h].src,"?")<0?"?enablejsapi=1":"&enablejsapi=1"}f.push(g[h])}if(f.length>0){d&&d.length&&(eb=d),a.onYouTubePlayerAPIReady=function(){for(var b,c=0;c<f.length;c++)b=new a.YT.Player(f[c]),b.addEventListener("onStateChange",A),b.addEventListener("onError",B)};var i=G.createElement("script"),j="http:";"https:"===G.location.protocol&&(j="https:"),i.src=j+"//www.youtube.com/player_api",i.type="text/javascript",i.async=!0;var k=G.getElementsByTagName("script")[0];k.parentNode.insertBefore(i,k)}}var E=function(){this._setDummyTracker()};E.prototype._setDummyTracker=function(){if(!this.tracker){var b=a._gat._getTrackers();b.length>0&&(this.tracker=b[0])}},E.prototype.inArray=function(a,b){if(a&&a.length)for(var c=0;c<a.length;c++)if(a[c]===b)return!0;return!1},E.prototype._sanitizeString=function(a,b){return a=a.toLowerCase().replace(/^\ +/,"").replace(/\ +$/,"").replace(/\s+/g,"_").replace(/[áàâãåäæª]/g,"a").replace(/[éèêëЄ€]/g,"e").replace(/[íìîï]/g,"i").replace(/[óòôõöøº]/g,"o").replace(/[úùûü]/g,"u").replace(/[碩]/g,"c"),b&&(a=a.replace(/[^a-z0-9_\-]/g,"_")),a.replace(/_+/g,"_")},E.prototype._addEventListener=function(b,c,d,e){var f=function(c){return c&&c.target||(c=a.event,c.target=c.srcElement),d.call(b,c)};return b.addEventListener?(b.addEventListener(c,f,!!e),!0):b.attachEvent?b.attachEvent("on"+c,f):(c="on"+c,"function"==typeof b[c]&&(f=function(a,b){return function(){a.apply(this,arguments),b.apply(this,arguments)}}(b[c],f)),b[c]=f,!0)},E.prototype._liveEvent=function(a,b,c){var d=this;a=a.toUpperCase(),a=a.split(","),d._addEventListener(G,b,function(b){for(var e=b.target;"HTML"!==e.nodeName&&!d.inArray(a,e.nodeName)&&null!==e.parentNode;e=e.parentNode);e&&d.inArray(a,e.nodeName)&&c.call(e,b)},!0)},E.prototype._DOMReady=function(b){function c(){c.done||(c.done=!0,b.apply(d,arguments))}var d=this;return/^(interactive|complete)/.test(G.readyState)?c():(this._addEventListener(G,"DOMContentLoaded",c,!1),this._addEventListener(a,"load",c,!1),void 0)},a._gaq=a._gaq||[];var F=a._gas||[];if(!(F._accounts_length>=0)){var G=a.document,H=(Object.prototype.toString,Object.prototype.hasOwnProperty),I=(Array.prototype.push,Array.prototype.slice),J=(String.prototype.trim,String.prototype.indexOf),K=G.location.href,L=G.documentElement;c.prototype._addHook=function(a,b){return"string"==typeof a&&"function"==typeof b&&("undefined"==typeof _gas._hooks[a]&&(_gas._hooks[a]=[]),_gas._hooks[a].push(b)),!1},c.prototype._execute=function(){var a,c,f,g,h,i=I.call(arguments),j=this,k=i.shift(),l=!0,m=0;if("function"==typeof k)return e(function(a,b){return function(){a.call(b)}}(k,j.gh));if("object"==typeof k&&k.length>0){if(c=k.shift(),J.call(c,".")>=0?(g=c.split(".")[0],c=c.split(".")[1]):g=b,f=j._hooks[c],f&&f.length>0)for(a=0;a<f.length;a++)try{h=f[a].apply(j.gh,k),h===!1?l=!1:h&&h.length>0&&(k=h)}catch(n){"_trackException"!==c&&j.push(["_trackException",n])}if(l===!1)return 1;if("_setAccount"===c){for(a in j._accounts)if(j._accounts[a]===k[0]&&g===b)return 1;return g=g||"_gas"+String(j._accounts_length+1),"undefined"==typeof j._accounts._gas1&&-1!==J.call(g,"_gas")&&(g="_gas1"),j._accounts[g]=k[0],j._accounts_length+=1,g=d(g),m=e([g+c,k[0]]),j.gh._setDummyTracker(),m}if("_link"===c||"_linkByPost"===c||"_require"===c||"_anonymizeIp"===c)return i=I.call(k),i.unshift(c),e(i);var o;if(g&&j._accounts[g])return o=d(g)+c,i=I.call(k),i.unshift(o),e(i);if(!(j._accounts_length>0))return i=I.call(k),i.unshift(c),e(i);for(a in j._accounts)H.call(j._accounts,a)&&(o=d(a)+c,i=I.call(k),i.unshift(o),m+=e(i));return m?1:0}},c.prototype.push=function(){for(var b=this,c=I.call(arguments),d=0;d<c.length;d++)!function(b,c){a._gaq.push(function(){c._execute.call(c,b)})}(c[d],b)},a._gas=_gas=new c,_gas.push(["_addHook","_trackException",function(a,b){return _gas.push(["_trackEvent","Exception "+(a.name||"Error"),b||a.message||a,K]),!1}]),_gas.push(["_addHook","_setDebug",function(a){_gas.debug_mode=!!a}]),_gas.push(["_addHook","_popHook",function(a){var b=_gas._hooks[a];return b&&b.pop&&b.pop(),!1}]),_gas.push(["_addHook","_gasSetDefaultTracker",function(a){return _gas._default_tracker=a,!1}]),_gas.push(["_addHook","_trackPageview",function(){var a=I.call(arguments);return a.length>=2&&"string"==typeof a[0]&&"string"==typeof a[1]?[{page:a[0],title:a[1]}]:a}]);var M=function(a){var b=this;if(!b._downloadTracked){b._downloadTracked=!0,a?"string"==typeof a?a={extensions:a.split(",")}:a.length>=1&&(a={extensions:a}):a={extensions:[]},a.category=a.category||"Download";var c="xls,xlsx,doc,docx,ppt,pptx,pdf,txt,zip";return c+=",rar,7z,exe,wma,mov,avi,wmv,mp3,csv,tsv",c=c.split(","),a.extensions=a.extensions.concat(c),b._liveEvent("a","mousedown",function(){var c=this;if(c.href){var d=f.call(b,c.href,a.extensions);d&&_gas.push(["_trackEvent",a.category,d,c.href])}}),!1}};_gas.push(["_addHook","_gasTrackDownloads",M]),_gas.push(["_addHook","_trackDownloads",M]),_gas.push(["_addHook","_gasMetaEcommerce",g]),_gas.push(["_addHook","_trackEvent",function(){var a=I.call(arguments);return a[3]&&(a[3]=(a[3]<0?0:Math.round(a[3]))||0),a}]);var N=function(a){if(!this._formTracked){this._formTracked=!0;var b=this;"object"!=typeof a&&(a={}),a.category=a.category||"Form Tracking";var c=function(b){var c=b.target,d=c.name||c.id||c.type||c.nodeName,e=h(c),f="form ("+e+")",g=d+" ("+b.type+")";_gas.push(["_trackEvent",a.category,f,g])};b._DOMReady(function(){var a,d,e=["input","select","textarea","hidden"],f=["form"],g=[];for(a=0;a<e.length;a++)for(g=G.getElementsByTagName(e[a]),d=0;d<g.length;d++)b._addEventListener(g[d],"change",c);for(a=0;a<f.length;a++)for(g=G.getElementsByTagName(f[a]),d=0;d<g.length;d++)b._addEventListener(g[d],"submit",c)})}};_gas.push(["_addHook","_gasTrackForms",N]),_gas.push(["_addHook","_trackForms",N]);var O=function(a){var b=this;b._liveEvent(a,"play",i),b._liveEvent(a,"pause",i),b._liveEvent(a,"ended",i)},P=function(){this._videoTracked||(this._videoTracked=!0,O.call(this,"video"))},Q=function(){this._audioTracked||(this._audioTracked=!0,O.call(this,"audio"))};_gas.push(["_addHook","_gasTrackVideo",P]),_gas.push(["_addHook","_gasTrackAudio",Q]),_gas.push(["_addHook","_trackVideo",P]),_gas.push(["_addHook","_trackAudio",Q]),_gas.push(["_addHook","_gasMeta",j]),_gas.push(["_addHook","_gasHTMLMarkup",k]);var R=function(a){return this._mailtoTracked?void 0:(this._mailtoTracked=!0,a||(a={}),a.category=a.category||"Mailto",this._liveEvent("a","mousedown",function(b){var c=b.target;c&&c.href&&c.href.toLowerCase&&0===J.call(c.href.toLowerCase(),"mailto:")&&_gas.push(["_trackEvent",a.category,c.href.substr(7)])}),!1)};_gas.push(["_addHook","_gasTrackMailto",R]),_gas.push(["_addHook","_trackMailto",R]);var S,T=null,U=0;_gas.push(["_addHook","_gasTrackMaxScroll",r]),_gas.push(["_addHook","_trackMaxScroll",r]),_gas._allowAnchor=!1,_gas.push(["_addHook","_setAllowAnchor",function(a){_gas._allowAnchor=!!a}]),_gas.push(["_addHook","_link",function(a,c){return c===b&&(c=_gas._allowAnchor),[a,c]}]),_gas.push(["_addHook","_linkByPost",function(a,c){return c===b&&(c=_gas._allowAnchor),[a,c]}]);var V,W=[];_gas.push(["_addHook","_setDomainName",function(a){return J.call("."+G.location.hostname,a)<0?(W.push(a),!1):(V=a,void 0)}]),_gas.push(["_addHook","_addExternalDomainName",function(a){return W.push(a),!1}]);var X=function(){var a=this,b=I.call(arguments);a&&a._DOMReady&&a._DOMReady(function(){s.apply(a,b)})};_gas.push(["_addHook","_gasMultiDomain",X]),_gas.push(["_addHook","_setMultiDomain",X]);var Y=function(a){if(!this._outboundTracked){this._outboundTracked=!0;var b=this;a||(a={}),a.category=a.category||"Outbound",b._liveEvent("a","mousedown",function(){var b=this;if(("http:"===b.protocol||"https:"===b.protocol)&&-1===J.call(b.hostname,G.location.hostname)){var c=b.pathname+b.search+"",d=J.call(c,"__utm");-1!==d&&(c=c.substring(0,d)),_gas.push(["_trackEvent",a.category,b.hostname,c])}})}};_gas.push(["_addHook","_gasTrackOutboundLinks",Y]),_gas.push(["_addHook","_trackOutboundLinks",Y]);var Z,$=[],_={},ab={},bb=!1,cb=function(a){var b=this;return("boolean"==typeof a||"force"===a)&&(a={force:!!a}),a=a||{},a.category=a.category||"Vimeo Video",a.percentages=a.percentages||[],a.force=a.force||!1,Z=a,b._DOMReady(function(){w.call(b)}),!1};_gas.push(["_addHook","_gasTrackVimeo",cb]),_gas.push(["_addHook","_trackVimeo",cb]);var db,eb=[],fb={},gb=function(a){var b=I.call(arguments);!b[0]||"boolean"!=typeof b[0]&&"force"!==b[0]||(a={force:!!b[0]},b[1]&&b[1].length&&(a.percentages=b[1])),a=a||{},a.force=a.force||!1,a.category=a.category||"YouTube Video",a.percentages=a.percentages||[],db=a;var c=this;return c._DOMReady(function(){D.call(c,a)}),!1};for(_gas.push(["_addHook","_gasTrackYoutube",gb]),_gas.push(["_addHook","_trackYoutube",gb]);_gas._queue.length>0;)_gas.push(_gas._queue.shift());"undefined"==typeof a._gat&&!function(){var a=G.getElementByID("gas-script"),b=G.createElement("script");b.type="text/javascript",b.async=!0,b.src=null!==a&&"true"===a.getAttribute("data-use-dcjs")?("https:"===G.location.protocol?"https://":"http://")+"stats.g.doubleclick.net/dc.js":("https:"===G.location.protocol?"https://ssl":"http://www")+".google-analytics.com/ga.js";var c=G.getElementsByTagName("script")[0];c.parentNode.insertBefore(b,c)}()}}(window);