/**
* @class
* @classdesc Main Tag Object.
* @name ATInternet.Tracker.Tag
* @memberof ATInternet.Tracker
* @type {function}
* @param config {object} Configuration of the Tag
* @param context {object} Context of the Tag
* @param callback {function} Executed when tracker is ready
* @public
*/
var Tag = function (config, context, callback) {
'use strict';
context = context || {};
var self = this;
/**
* Version of the tracker.
* @name version
* @memberof ATInternet.Tracker.Tag
* @inner
* @type {string}
* @public
*/
self.version = '#VERSION#';
/**
* Contains tagging configuration: context variable (like 'page', 'level2', ...)
* @type {object}
* @private
*/
var _context = window['ATInternet']['Utils']['cloneSimpleObject'](context);
//instantiation of all sub objects
/**
* Module for triggers management.
* @name triggers
* @memberof ATInternet.Tracker.Tag#
* @type {TriggersManager}
* @public
* @see {@link TriggersManager}
*/
self.triggers = new TriggersManager(self);
/**
* Use to trigger event.
* @name emit
* @memberof ATInternet.Tracker.Tag#
* @function
* @param trigger {string} Trigger to emit
* @param data {object} Data to transmit to listeners
* @public
* @example
* <pre><code class="javascript">tag.emit('RichMedia:richMedia:remove', {
* lvl: 'DEBUG',
* msg: 'method ended',
* details: {playerId: plyr, media: mediaObject}
* });
* </code></pre>
* @see {@link TriggersManager#emit}
*/
self.emit = self.triggers.emit;
/**
* Use to emit debug triggers.
* @memberof ATInternet.Tracker.Tag#
* @name debug
* @function
* @param trigger {string} Trigger that you want to emit
* @param level {string} DEBUG, ERROR, WARNING
* @param message {string}
* @param details {*} Data you want to transmit to listeners
* @public
* @example
* <pre><code class="javascript">tag.debug('RichMedia:richMedia:remove', 'DEBUG', 'method ended', {playerId: plyr, media: mediaObject});
* </code></pre>
*/
/* @if debug */
self.debug = function (trigger, level, message, details) {
self.emit(trigger, {
lvl: level,
msg: message,
details: details
});
};
/* @endif */
/**
* Use to add a trigger listener.
* @name onTrigger
* @memberof ATInternet.Tracker.Tag#
* @function
* @param trigger {string} Trigger you want to subscribe
* @param callback {function} Method that you want to be triggered
* @returns {number} Callback ID
* @public
* @example
* <pre><code class="javascript">// It returns the ID of the callback so you can delete it if needed.
* var idCallback = tag.onTrigger('myTrigger', callback(trig, data, idCallbackBis){});
* </code></pre>
* @see {@link TriggersManager#on}
*/
self.onTrigger = self.triggers['on'];
/**
* Internal configuration object.
* @type {object}
* @private
*/
var _conf = window['ATInternet']['Utils']['cloneSimpleObject'](dfltGlobalCfg) || {};
//Overloading of the configuration with the one given in parameter
var k;
for (k in config) {
if (config.hasOwnProperty(k)) {
_conf[k] = config[k];
}
}
/**
* Get configuration.
* @name getConfig
* @memberof ATInternet.Tracker.Tag#
* @function
* @param key {string} Configuration property name
* @returns {*} Configuration property value if exist, undefined if not
* @public
*/
self.getConfig = function (key) {
return _conf[key];
};
/**
* Set configuration.
* @name setConfig
* @memberof ATInternet.Tracker.Tag#
* @function
* @param key {string} Configuration property name
* @param value {*} Configuration property value
* @param ifNotExist {boolean} If true, the property will only be set if the configuration property doesn't exist
* @returns {*}
* @public
*/
self.setConfig = function (key, value, ifNotExist) {
if (_conf[key] === undefined || !ifNotExist) {
self.emit('Tracker:Config:Set:' + key, {lvl: 'INFO', details: {bef: _conf[key], aft: value}});
_conf[key] = value;
}
};
/**
* Set the specific configuration of a plugin.
* If the configuration already exists, set only the undefined properties.
* @name configPlugin
* @memberof ATInternet.Tracker.Tag#
* @function
* @param plg {string} Name of the plugin concerned
* @param cfg {object} Value of the plugin configuration
* @param callback {function} Function which be called if the plugin configuration change
* @returns {object}
* @public
*/
self.configPlugin = function (plg, cfg, callback) {
_conf[plg] = _conf[plg] || {};
var k;
for (k in cfg) {
if (cfg.hasOwnProperty(k)) {
if (_conf[plg][k] === undefined) {
_conf[plg][k] = cfg[k];
}
}
}
if (callback) {
callback(_conf[plg]);
self.onTrigger('Tracker:Config:Set:' + plg, function (trig, data) {
callback(data.details.aft);
});
}
return _conf[plg];
};
/**
* Get a context variable.
* @name getContext
* @memberof ATInternet.Tracker.Tag#
* @function
* @param key {string} Context variable name
* @returns {*}
* @public
*/
self.getContext = function (key) {
return _context[key];
};
/**
* Set a context variable.
* @name setContext
* @memberof ATInternet.Tracker.Tag#
* @function
* @param {string} key context variable name
* @param {*} value
* @public
*/
self.setContext = function (key, value) {
self.emit('Tracker:Context:Set:' + key, {lvl: 'INFO', details: {bef: _context[key], aft: value}});
_context[key] = value;
};
/**
* Delete context value or parameter value in context(s).
* @name delContext
* @memberof ATInternet.Tracker.Tag#
* @function
* @param key1 {string} Context name
* @param key2 {string} Context parameter name (first level)
* @public
* @example
* <pre><code class="javascript">tag.delContext('myContext'); //=> Delete 'myContext' content
* tag.delContext('myContext', 'param'); //=> Delete 'param' content in 'myContext'
* tag.delContext(undefined, 'param'); //=> Delete 'param' content in all contexts
* </code></pre>
*/
self.delContext = function (key1, key2) {
self.emit('Tracker:Context:Deleted:' + key1 + ':' + key2, {lvl: 'INFO', details: {key1: key1, key2: key2}});
if (key1) {
if (_context.hasOwnProperty(key1)) {
if (key2) {
if (_context[key1] && _context[key1].hasOwnProperty(key2)) {
_context[key1][key2] = undefined;
}
}
else {
_context[key1] = undefined;
}
}
}
else if (key2) {
var key;
for (key in _context) {
if (_context.hasOwnProperty(key)) {
if (_context[key] && _context[key].hasOwnProperty(key2)) {
_context[key][key2] = undefined;
}
}
}
}
};
/**
* Module for plugins management.
* @name plugins
* @memberof ATInternet.Tracker.Tag#
* @type {PluginsManager}
* @public
* @see {@link PluginsManager}
*/
self.plugins = new PluginsManager(self);
/**
* Module for buffer management.
* @name buffer
* @memberof ATInternet.Tracker.Tag#
* @type {BufferManager}
* @public
* @see {@link BufferManager}
*/
self.buffer = new BufferManager(self);
/**
* Set value for a hit variable (overrides if present).
* @name setParam
* @memberof ATInternet.Tracker.Tag#
* @function
* @param name {string} Name of the hit variable
* @param value {string|number|function|Array} value of the hit variable
* @param options {object} Configuration of the variable, if no hitType defined, it will be "page" by default
* @public
* @example
* <pre><code class="javascript">tag.setParam('test1', 'val1', {hitType: ['test', 'click'], permanent: true, encode: true});
* </code></pre>
* @see {@link BufferManager}
*/
self.setParam = self.buffer.set;
/**
* Use to get the collection of hit parameters stored (or a value if a parameter name is given).
* @name getParams
* @memberof ATInternet.Tracker.Tag#
* @function
* @param param {string} Parameter name (optional)
* @returns {string|object}
* @public
* @see {@link BufferManager}
*/
self.getParams = function (param) {
return self.buffer.get(param, false);
};
/**
* Get variables from the buffer using the filter given, with possibility of returning options or not.
* @name getParam
* @memberof ATInternet.Tracker.Tag#
* @function
* @param filterList {Array} List of key/value(s) in an array. (ex : [[key1,value1],[key2,[value2A,value2B]]]) Filter on variable's options
* @param withOptions {boolean} If true only returns value else returns object with value and options
* @returns {string|object}
* @public
* @example
* <pre><code class="javascript">// This filter will get variables with hitType 'page' OR 'all', AND with permanent true
* var filter = [
* ['hitType',['page','all']],
* ['permanent',true]
* ]
*
* var dataObj = tag.getParam(filter, true); // true to get options
* dataObj = {
* 'variableExample' : {
* value:'value',
* options: {
* hitType:['page'],
* permanent:true
* }
* }
* }
*
* var dataObj = tag.getParam(filter); // no option in results
* dataObj = {
* 'variableExample':'value'
* }
* </code></pre>
* @see {@link BufferManager}
*/
self.getParam = self.buffer.get;
/**
* Use to delete a stored parameter.
* @name delParam
* @memberof ATInternet.Tracker.Tag#
* @function
* @public
* @see {@link BufferManager}
*/
self.delParam = self.buffer['del'];
/**
* Module for hit builder.
* @name builder
* @memberof ATInternet.Tracker.Tag#
* @type {BuildManager}
* @public
* @see {@link BuildManager}
*/
self.builder = new BuildManager(self);
/**
* Send the hit and call the callback if present
* The hit will integrate parameters stored
* @name sendHit
* @memberof ATInternet.Tracker.Tag#
* @function
* @param customParams {object} Object which contains some hit parameters that you would like to send specifically (they are given priority over the current buffer)
* @param filters {Array} List of buffer filters
* @public
* @see {@link BuildManager}
*/
self.sendHit = self.builder.send;
/**
* Send single hit from complete url. An event will be sent thanks to {@link TriggersManager} :
* <br />- <b>"Tracker:Hit:Sent:Ok"</b> with the hit as data if succeed,
* <br />- <b>"Tracker:Hit:Sent:Error"</b> with error as data otherwise.
* @name sendUrl
* @memberof ATInternet.Tracker.Tag#
* @function
* @param hit {string} Url to send
* @public
* @see {@link BuildManager}
*/
self.sendUrl = self.builder.sendUrl;
/**
* Module for callback management.
* @name callbacks
* @memberof ATInternet.Tracker.Tag#
* @type {CallbacksManager}
* @public
* @see {@link CallbacksManager}
*/
self.callbacks = new CallbacksManager(self);
// Ajout du timestamp dans le hit pour le différencier d'un autre
self.setParam('ts', function () {
return new Date().getTime()
}, {permanent: true, hitType: ['all']});
// Ajout de l'idclient dans le cas où l'écriture en cookie est désactivée
if (self.getConfig('disableCookie')) {
self.setParam('idclient', 'xxxxxx-NO', {permanent: true, hitType: ['all']});
}
// Ajout du paramètre medium (ex: fia pour Facebook) si déclaré dans le marqueur
if (self.getConfig('medium')) {
self.setParam('medium', self.getConfig('medium'), {permanent: true, hitType: ['all']});
}
/* Constructor */
self.plugins['init']();
self.callbacks['init']();
//ajout de l'instance dans la collection
ATInternet.Tracker.instances.push(self);
self.emit('Tracker:Ready', {
lvl: 'INFO',
msg: 'Tracker initialized',
details: {
tracker: self,
args: {
config: config,
context: context,
callback: callback
}
}
});
callback && callback(self);
};
ATInternet.Tracker.Tag = Tag;
/**
* Reference all instances of Tag.
* @name instances
* @memberof ATInternet.Tracker
* @type {Array}
* @public
*/
ATInternet.Tracker.instances = [];
/**
* Reference all plugins loaded.
* @name pluginProtos
* @memberof ATInternet.Tracker
* @type {object}
* @public
*/
ATInternet.Tracker.pluginProtos = {};
/**
* This method loads a plugin in all instances of Tag.
* @name addPlugin
* @memberof ATInternet.Tracker
* @function
* @param name {string} Plugin's name to add
* @param obj {object} Plugin to add
* @public
*/
ATInternet.Tracker.addPlugin = function (name, obj) {
'use strict';
obj = obj || ATInternet.Tracker.Plugins[name];
//Ajout de son proto dans la collection (si pas déjà présent).
if (!ATInternet.Tracker.pluginProtos[name]) {
ATInternet.Tracker.pluginProtos[name] = obj;
//création d'une instance du plugin dans toutes les instances du tracker
for (var i = 0; i < ATInternet.Tracker.instances.length; i++) {
ATInternet.Tracker.instances[i].plugins.load(name, obj);
}
}
};
/**
* This method deletes a plugin loaded in all instances of Tag.
* @name delPlugin
* @memberof ATInternet.Tracker
* @function
* @param name {string} plugin's name to delete
* @public
*/
ATInternet.Tracker.delPlugin = function (name) {
'use strict';
//Ajout de son proto dans la collection (si pas déjà présent)
if (ATInternet.Tracker.pluginProtos[name]) {
ATInternet.Tracker.pluginProtos[name] = undefined;
//Suppression de l'instance du plugin dans toutes les instances du tracker
for (var i = 0; i < ATInternet.Tracker.instances.length; i++) {
ATInternet.Tracker.instances[i].plugins.unload(name);
}
}
};
/**
* Reference all callbacks loaded.
* @name callbackProtos
* @memberof ATInternet.Tracker
* @type {object}
* @public
*/
ATInternet.Tracker.callbackProtos = {};