/**
* @class
* @classdesc Plugin used to manage identified visitors
* @name IdentifiedVisitor
* @memberOf ATInternet.Tracker.Plugins
* @type {function}
* @param tag {object} Instance of the Tag used
* @public
*/
ATInternet.Tracker.Plugins.IdentifiedVisitor = function (tag) {
'use strict';
var _this = this;
// Global configuration, storage and query values
var _storageTextual = null;
var _storageNumeric = null;
var _storageCategory = null;
var _storageVrn = null;
var _queryTextual = '';
var _queryNumeric = '';
var _storageRedirectTextual = null;
var _storageRedirectNumeric = null;
var _setStorageMethod = '';
var _getStorageMethod = '';
var _delStorageMethod = '';
var conf = {};
var _debug = {
level: 'DEBUG',
messageEnd: 'method ended'
};
// Set specific plugin configuration
// If global configuration already exists, set only undefined properties
tag.configPlugin('IdentifiedVisitor', dfltPluginCfg || {}, function (newConf) {
conf = newConf;
});
tag.setConfig('redirectionLifetime', dfltGlobalCfg.redirectionLifetime, true);
/**
* Check if current page is a redirection one
* @memberof ATInternet.Tracker.Plugins.IdentifiedVisitor#
* @function
* @return {boolean}
* @private
*/
var _isRedirection = function () {
return !!tag.getConfig('redirect');
};
/**
* Define domain attribution for the numsite
* @memberof ATInternet.Tracker.Plugins.IdentifiedVisitor#
* @function
* @private
*/
var _setDomainAttribution = function () {
_setStorageMethod = conf.domainAttribution ? 'set' : 'setPrivate';
_getStorageMethod = conf.domainAttribution ? 'get' : 'getPrivate';
_delStorageMethod = conf.domainAttribution ? 'del' : 'delPrivate';
};
/**
* Helper to use the plugin Storage
* @memberof ATInternet.Tracker.Plugins.IdentifiedVisitor#
* @function
* @param method {string} Method to call
* @param params {Array} Arguments to give
* @return {*}
* @private
*/
var _pluginStorage = function (method, params) {
var ret = null;
tag.plugins.exec('Storage', method, params, function (data) {
ret = data;
});
return ret;
};
/**
* Get identified visitor values in the query string
* @memberof ATInternet.Tracker.Plugins.IdentifiedVisitor#
* @function
* @private
*/
var _getQueryValues = function () {
var href = tag.utils.getLocation();
_queryTextual = tag.utils.getQueryStringValue('xtat', href);
_queryNumeric = tag.utils.getQueryStringValue('xtan', href);
};
/**
* Get identified visitor values in the storage from a redirection
* @memberof ATInternet.Tracker.Plugins.IdentifiedVisitor#
* @function
* @private
*/
var _getStorageRedirectValues = function () {
_storageRedirectTextual = _pluginStorage(_getStorageMethod, [['atredir', 'at']]);
_storageRedirectNumeric = _pluginStorage(_getStorageMethod, [['atredir', 'an']]);
// Burn after reading
_pluginStorage(_delStorageMethod, [['atredir', 'at']]);
_pluginStorage(_delStorageMethod, [['atredir', 'an']]);
};
/**
* Check if a stored data exists with 'object' type, if not, method creates data to store and returns true
* If exists but with another type, method returns false
* @memberof ATInternet.Tracker.Plugins.IdentifiedVisitor#
* @function
* @param name {string} Name of the stored data
* @param options {object} Options of the data to store in case of creation
* @return boolean {boolean} Returns true if the stored data already exists or if has been created, false if any problem
* @private
*/
var _checkStorage = function (name, options) {
var temp = _pluginStorage(_getStorageMethod, [name, true]);
if (temp !== null) {
return (typeof temp === 'object' && !(temp instanceof Array));
} else {
_pluginStorage(_setStorageMethod, [name, {}, options]);
return true;
}
};
/**
* Set identified visitor values in storage for redirection
* @memberof ATInternet.Tracker.Plugins.IdentifiedVisitor#
* @function
* @private
*/
var _setStorageRedirectValues = function () {
if ((_queryTextual || _queryNumeric) && _checkStorage('atredir', {
path: '/',
end: tag.getConfig('redirectionLifetime')
})) {
if (_queryNumeric) {
_pluginStorage(_setStorageMethod, [
['atredir', 'an'],
_queryNumeric
]);
}
if (_queryTextual) {
_pluginStorage(_setStorageMethod, [
['atredir', 'at'],
_queryTextual
]);
}
}
};
/**
* get identified visitor and new visitor (vrn) values from the persistent storage
* @memberof ATInternet.Tracker.Plugins.IdentifiedVisitor#
* @function
* @private
*/
var _getStorageValues = function () {
_storageTextual = _pluginStorage(_getStorageMethod, [
['atidvisitor', 'at']
]);
_storageNumeric = _pluginStorage(_getStorageMethod, [
['atidvisitor', 'an']
]);
_storageCategory = _pluginStorage(_getStorageMethod, [
['atidvisitor', 'ac']
]);
_storageVrn = _pluginStorage(_getStorageMethod, [
['atidvisitor', 'vrn']
]);
};
/**
* Check/create/write a property in the storage session (create it if necessary)
* @memberof ATInternet.Tracker.Plugins.IdentifiedVisitor#
* @function
* @param key {string} Property name
* @param value {string} Value for the property
* @private
*/
var _setStorage = function (key, value) {
var test = _checkStorage('atidvisitor', {path: '/', session: conf.lifetime * 24 * 60 * 60});
if (test) {
_pluginStorage(_setStorageMethod, [
['atidvisitor', key],
value
]);
}
};
/**
* Add the key/value to the next hits, and check/create the session storage to update its property
* @memberof ATInternet.Tracker.Plugins.IdentifiedVisitor#
* @function
* @param key {string} Property to set
* @param value {string} Value to set for the property
* @param store {boolean} Store value
* @private
*/
var _set = function (key, value, store) {
tag.setParam(key, value, {
'hitType': ['all'],
permanent: true
});
store && _setStorage(key, value);
};
/**
* Set the identified visitor in buffer and storage
* @memberof ATInternet.Tracker.Plugins.IdentifiedVisitor#
* @function
* @private
*/
var _setParams = function () {
// Function used to build object from string value
var _processValue = function (obj, str) {
if (/-/.test(str)) {
obj.category = str.split('-')[0];
obj.id = str.split('-')[1];
} else {
obj.id = str;
}
};
// Numeric identifier processing
var numObj = {category: '', id: ''};
var numStr = _queryNumeric || _storageRedirectNumeric;
_processValue(numObj, numStr);
// Textual identifier processing
var textObj = {category: '', id: ''};
var textStr = _queryTextual || _storageRedirectTextual;
_processValue(textObj, textStr);
// Set textual identifier
if (textObj.id) {
if (textObj.category) {
_set('ac', textObj.category, true);
}
_set('at', textObj.id, true);
} else if (_storageTextual) {
_set('at', _storageTextual, false);
if (_storageCategory) {
_set('ac', _storageCategory, false);
}
}
//Set numeric identifier depending on priority
if (numObj.id) {
if (numObj.category) {
_set('ac', numObj.category, true);
}
_set('an', numObj.id, true);
} else if (_storageNumeric) {
_set('anc', _storageCategory + '-' + _storageNumeric, false);
}
};
/**
* Add a new visitor property in the page context
* @memberof ATInternet.Tracker.Plugins.IdentifiedVisitor#
* @function
* @private
*/
var _addPageContext = function () {
var contextPageObject = tag.getContext('page') || {};
contextPageObject.vrn = 1;
tag.setContext('page', contextPageObject);
};
/**
* Set new visitor (vrn) in storage and page context
* @memberof ATInternet.Tracker.Plugins.IdentifiedVisitor#
* @function
* @private
*/
var _setVrnValue = function () {
var regVal = '-' + tag.getConfig('site') + '-';
var regExp = new RegExp(regVal);
if (!regExp.test(_storageVrn)) {
_storageVrn = (_storageVrn || '') + regVal;
_setStorage('vrn', _storageVrn);
_addPageContext();
}
};
/**
* Run the automatic process
* @memberof ATInternet.Tracker.Plugins.IdentifiedVisitor#
* @function
* @private
*/
var _run = function () {
_setDomainAttribution(); //commun
_getQueryValues(); //commun
if (_isRedirection()) {
_setStorageRedirectValues(); //redirect
} else {
_getStorageRedirectValues(); //pas redirect
_getStorageValues(); //pas redirect
_setParams(); //pas redirect
_setVrnValue(); // pas redirect
}
tag.emit('IdentifiedVisitor:Ready', {
lvl: 'INFO',
details: {
storageRedirectTextual: _storageRedirectTextual,
storageRedirectNumeric: _storageRedirectNumeric,
storageTextual: _storageTextual,
storageNumeric: _storageNumeric,
storageCategory: _storageCategory,
storageVrn: _storageVrn
}
});
};
/**
* Check dependencies and launch the automatic process when all dependencies are present
* @memberof ATInternet.Tracker.Plugins.IdentifiedVisitor#
* @function
* @private
*/
var _init = function () {
var dependencies = ['Storage', 'Utils'];
tag.plugins.waitForDependencies(dependencies, _run);
};
// Launch process
_init();
/**
* [Object added by plugin {@link ATInternet.Tracker.Plugins.IdentifiedVisitor IdentifiedVisitor}] Tags to identify a visitor.
* @name identifiedVisitor
* @memberof ATInternet.Tracker.Tag
* @inner
* @type {object}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#identifiedVisitor.set}
* @property {function} unset Tag helper, see details here {@link ATInternet.Tracker.Tag#identifiedVisitor.unset}
* @public
*/
tag.identifiedVisitor = {};
/**
* [Helper added by plugin {@link ATInternet.Tracker.Plugins.IdentifiedVisitor IdentifiedVisitor}] Set an identified visitor
* @alias identifiedVisitor.set
* @memberof! ATInternet.Tracker.Tag#
* @function
* @param tagObject {object} 2 properties : id, category
* @example
* <pre><code class="javascript">
* tag.identifiedVisitor.set({
* id:'id123', // or a numeric value, id:123456
* category:'123'
* });
* </code></pre>
* @public
*/
tag.identifiedVisitor.set = function (tagObject) {
tagObject = tagObject || {};
var identifier = tagObject.id;
var category = tagObject.category;
if (typeof identifier === 'number') {
_set('an', identifier.toString(), true);
} else if (typeof identifier === 'string') {
_set('at', identifier, true);
}
if (typeof category !== 'undefined') {
_set('ac', category, true);
}
/* @if debug */
tag.debug('IdentifiedVisitor:identifiedVisitor:set', _debug.level, _debug.messageEnd, tagObject);
/* @endif */
};
/**
* [Helper added by plugin {@link ATInternet.Tracker.Plugins.IdentifiedVisitor IdentifiedVisitor}] Unset an identified visitor (delete all stored data and params from buffer)
* @alias identifiedVisitor.unset
* @memberof! ATInternet.Tracker.Tag#
* @function
* @public
*/
tag.identifiedVisitor.unset = function () {
var delParams = function (tab, str) {
for (var i = 0; i < tab.length; i++) {
_pluginStorage(_delStorageMethod, [['atidvisitor', tab[i]]]);
tag.delParam(tab[i]);
}
tag.delParam(str);
};
delParams(['an', 'at', 'ac'], 'anc');
/* @if debug */
tag.debug('IdentifiedVisitor:identifiedVisitor:unset', _debug.level, _debug.messageEnd);
/* @endif */
};
// For unit tests on private elements !!!
/* @if test */
_this._IDENTIFIEDVISITOR_LIFETIME = conf.lifetime;
_this.getAllParams = function () {
_this._storage_textual = _storageTextual;
_this._storage_numeric = _storageNumeric;
_this._storage_category = _storageCategory;
_this._storage_vrn = _storageVrn;
_this._query_textual = _queryTextual;
_this._query_numeric = _queryNumeric;
_this._storage_redirect_textual = _storageRedirectTextual;
_this._storage_redirect_numeric = _storageRedirectNumeric;
};
_this._set_storage_method = _setStorageMethod;
_this._get_storage_method = _getStorageMethod;
_this._setDomainAttribution = _setDomainAttribution;
_this._pluginStorage = _pluginStorage;
_this._getQueryValues = _getQueryValues;
_this._getStorageRedirectValues = _getStorageRedirectValues;
_this._setStorageRedirectValues = _setStorageRedirectValues;
_this._getStorageValues = _getStorageValues;
_this._checkStorage = _checkStorage;
_this._run = _run;
_this._setParams = _setParams;
_this._setVrnValue = _setVrnValue;
_this._addPageContext = _addPageContext;
_this._init = _init;
_this._set = _set;
_this._setStorage = _setStorage;
/* @endif */
};
ATInternet.Tracker.addPlugin('IdentifiedVisitor');