/**
* @class
* @name ClientSideUserId
* @memberof ATInternet.Tracker.Plugins
* @type {function}
* @param parent {object} Instance of the Tag used
* @description
* Plugin to enable a visitor to be tracked by creating a user ID in cases where writing a third-party cookie is not possible.
* <br />For example, this might be the case on an Intranet site,
* or when the Safari browser is used (default settings),
* or when a visitor browses using an Apple device like iPhone, iPad or iPod.
* It is also possible to configure the plugin to force the use of a random or custom ID.
* This ID can be found in the idclient variable, present in all hits when the plugin is active.
* @public
*/
window['ATInternet']['Tracker']['Plugins']['ClientSideUserId'] = function (parent) {
"use strict";
var _config = {};
var _userIdFromContext = undefined;
var _userIdFromStorage = null;
var _isClient = false;
var _isOptOut = false;
var _isFromCustomerContext = false;
var _user = {
userID: '',
storageName: '',
isFromContext: false,
force: false
};
var _eventID = -1;
// Set specific plugin configuration.
// If global configuration already exists, set only undefined properties.
parent.configPlugin('ClientSideUserId', dfltPluginCfg || {}, function (newConf) {
_config = newConf;
});
/**
* Check if general configuration implies ClientSideUserId mode activation.
* <br />Note : konqueror|Lunascape|midori|OmniWeb browsers are managed like Safari
* @memberof ATInternet.Tracker.Plugins.ClientSideUserId#
* @function
* @return {boolean}
* @private
*/
var _isClientConfiguration = function () {
var isClient = false;
if (_config.clientSideMode === 'required') {
var userAgent = '';
if (window.navigator) {
userAgent = window.navigator.userAgent;
}
if ((/Safari/.test(userAgent) && !/Chrome/.test(userAgent))
|| /iPhone|iPod|iPad/.test(userAgent)) {
isClient = true;
}
}
else if (_config.clientSideMode === 'always') {
isClient = true;
}
return isClient;
};
/**
* Check if OPT-OUT mode is activated or not.
* @memberof ATInternet.Tracker.Plugins.ClientSideUserId#
* @function
* @return {boolean}
* @private
*/
var _isOptedOutMode = function () {
var isOptedOut = false;
var optedOut = ATInternet.Utils.optedOut;
// 1. Warning, do this check first before recovering atoptedout
if (optedOut === false) {
parent.storage.del('atoptedout');
if (parent.getParam('idclient') === _config.optOut) {
parent.delParam('idclient');
}
}
// 2. Recover atoptedout
var storageOptedOut = parent.storage.get('atoptedout', true);
if ((optedOut === true) || (storageOptedOut === _config.optOut)) {
isOptedOut = true;
}
if (isOptedOut) {
ATInternet.Utils.optedOut = true;
}
return isOptedOut;
};
/**
* Init global context.
* @memberof ATInternet.Tracker.Plugins.ClientSideUserId#
* @function
* @private
*/
var _initContext = function () {
// Get current user IDs
_userIdFromContext = parent.getContext('userIdentifier');
_userIdFromStorage = parent.storage.get('atuserid');
// Init context parameters
_isClient = _isClientConfiguration();
_isOptOut = _isOptedOutMode();
_isFromCustomerContext = (typeof _userIdFromContext !== 'undefined');
};
/**
* Init user object with "userID, storageName and isfromContext" values.
* @memberof ATInternet.Tracker.Plugins.ClientSideUserId#
* @function
* @private
*/
var _initUser = function () {
_user.storageName = _config.userIdStorageName;
_user.isFromContext = false;
_user.force = false;
if (_isOptOut) {
_user.userID = _config.optOut;
_user.storageName = _config.optOutStorageName;
_user.isFromContext = true;
_user.force = true;
}
else if (parent.getConfig('disableCookie') || parent.getConfig('disableStorage')) {
_user.userID = parent.getParam('idclient');
_user.isFromContext = true;
}
else if (_isFromCustomerContext) {
_user.userID = _userIdFromContext;
_user.isFromContext = true;
}
else if (_userIdFromStorage !== null) {
_user.userID = _userIdFromStorage;
}
else {
var uuid = ATInternet.Utils.uuid();
_user.userID = uuid.v4();
}
};
/**
* Create or update stored data value for identifier.
* @memberof ATInternet.Tracker.Plugins.ClientSideUserId#
* @function
* @private
*/
var _setStorageValue = function () {
if (_config.userIdExpirationMode === 'relative' || (_config.userIdExpirationMode === 'fixed' && _userIdFromStorage === null) || _user.isFromContext) {
var expiration_date = new Date();
expiration_date.setTime(expiration_date.getTime() + (_config.userIdCookieDuration * 24 * 60 * 60 * 1000));
parent.storage.set(_user.storageName, _user.userID, {end: expiration_date, path: '/'}, _user.force);
var data = parent.storage.get(_user.storageName, true);
if (ATInternet.Utils.consent && !_user.isFromContext && _user.userID !== data) {
parent.setParam('idclient', _user.userID + '-NO', {
multihit: true,
permanent: true,
hitType: ['all']
});
}
}
};
/**
* Set user ID in buffer and storage.
* @memberof ATInternet.Tracker.Plugins.ClientSideUserId#
* @function
* @private
*/
var _setUserId = function () {
parent.setParam('idclient', _user.userID, {multihit: true, permanent: true, hitType: ['all']});
_setStorageValue();
};
/**
* Get context and stored values according to priorities or generate a new GUID.
* @memberof ATInternet.Tracker.Plugins.ClientSideUserId#
* @function
* @private
*/
var _run = function () {
_initContext();
if (_isClient || _isOptOut || _isFromCustomerContext) {
_initUser();
_setUserId();
}
};
/**
* @memberof ATInternet.Tracker.Plugins.ClientSideUserId#
* @function
* @description
* React to OPT-OUT actions.
* @param event {object}
* @private
*/
var _processEvent = function (event) {
if (event) {
var detail = event.detail;
if (detail && (detail.name === 'clientsideuserid') && (detail.id === _eventID)) {
_run();
}
}
};
/**
* Launch plugin when all dependencies are loaded.
* @memberof ATInternet.Tracker.Plugins.ClientSideUserId#
* @function
* @private
*/
var _init = function () {
var dependencies = ['Storage'];
parent.plugins.waitForDependencies(dependencies, function () {
var uuid = ATInternet.Utils.uuid();
_eventID = parseInt(uuid.num(8));
// Attach event in order to process OPT-OUT actions
ATInternet.Utils.removeOptOutEvent(_processEvent);
ATInternet.Utils.addOptOutEvent(_eventID, _processEvent);
_run();
});
};
// Initialise global process.
_init();
/**
* [Object added by plugin {@link ATInternet.Tracker.Plugins.ClientSideUserId ClientSideUserId}] Tags to manage a user ID on client side mode.
* @name clientSideUserId
* @inner
* @type {object}
* @memberof ATInternet.Tracker.Tag
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#clientSideUserId.set}
* @public
*/
parent.clientSideUserId = {};
/**
*[Helper added by plugin {@link ATInternet.Tracker.Plugins.ClientSideUserId ClientSideUserId}] Add a user ID to all hits "&idclient=" and store it in "atuserid" or "atoptedout".
* @alias clientSideUserId.set
* @memberof! ATInternet.Tracker.Tag#
* @function
* @param id {string|number} User ID
* @example
* <pre><code class="javascript">tag.clientSideUserId.set('abc123');
* </code></pre>
* @public
*/
parent.clientSideUserId.set = function (id) {
if (!_isOptOut) {
_user.userID = id;
_user.isFromContext = true;
_user.storageName = _config.userIdStorageName;
_user.force = false;
_setUserId();
}
/* @if debug */
parent.debug('ClientSideUserId:clientSideUserId:set', 'DEBUG', 'method ended', {id: id});
/* @endif */
};
/**
*[Helper added by plugin {@link ATInternet.Tracker.Plugins.ClientSideUserId ClientSideUserId}] Force idclient storage (useful for consent page mode).
* @alias clientSideUserId.store
* @memberof! ATInternet.Tracker.Tag#
* @function
* @example
* <pre><code class="javascript">tag.clientSideUserId.store();
* </code></pre>
* @public
*/
parent.clientSideUserId.store = function () {
_user.isFromContext = true;
_user.force = true;
_setStorageValue();
/* @if debug */
parent.debug('ClientSideUserId:clientSideUserId:store', 'DEBUG', 'method ended', {id: _user.userID});
/* @endif */
};
/**
*[Helper added by plugin {@link ATInternet.Tracker.Plugins.ClientSideUserId ClientSideUserId}] Get user ID.
* @alias clientSideUserId.get
* @memberof! ATInternet.Tracker.Tag#
* @function
* @example
* <pre><code class="javascript">tag.clientSideUserId.get();
* </code></pre>
* @return {string|number}
* @public
*/
parent.clientSideUserId.get = function () {
/* @if debug */
parent.debug('ClientSideUserId:clientSideUserId:get', 'DEBUG', 'method ended', {id: _user.userID});
/* @endif */
return _user.userID;
};
// For unit tests on private elements !!!
/* @if test */
var _this = this;
_this._isClientConfiguration = _isClientConfiguration;
_this._isOptedOutMode = _isOptedOutMode;
_this._initContext = _initContext;
_this._initUser = _initUser;
_this._setStorageValue = _setStorageValue;
_this._setUserId = _setUserId;
_this._run = _run;
_this._processEvent = _processEvent;
_this._init = _init;
_this._userIdCookieDuration = _config.userIdCookieDuration;
_this._userIdExpirationMode = _config.userIdExpirationMode;
_this._optOut = _config.optOut;
_this._userIdStorageName = _config.userIdStorageName;
_this._optOutStorageName = _config.optOutStorageName;
_this._userIdFromContext = _userIdFromContext;
_this._userIdFromStorage = _userIdFromStorage;
_this.getThemAll = function () {
_this._userIdCookieDuration = _config.userIdCookieDuration;
_this._userIdExpirationMode = _config.userIdExpirationMode;
_this._optOut = _config.optOut;
_this._userIdStorageName = _config.userIdStorageName;
_this._optOutStorageName = _config.optOutStorageName;
_this._userIdFromContext = _userIdFromContext;
_this._userIdFromStorage = _userIdFromStorage;
};
/* @endif */
};
window['ATInternet']['Tracker']['addPlugin']('ClientSideUserId');