/**
* @class
* @name ClientSideUserId
* @memberof ATInternet.Tracker.Plugins
* @type {function}
* @param tag {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
*/
ATInternet.Tracker.Plugins.ClientSideUserId = function (tag) {
'use strict';
var _config = {};
var _isITP = false;
var _isClient = false;
var _user = null;
var _eventID = -1;
var _debug = {
level: 'DEBUG',
messageEnd: 'method ended'
};
// Set specific plugin configuration.
// If global configuration already exists, set only undefined properties.
tag.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
* @private
*/
var _setOptoutSettings = function () {
var fromStorage = false;
if (ATInternet.Utils.optedOut === null) {
if (tag.storage.get(_config.userIdStorageName, true) === _config.optOut) {
ATInternet.Utils.optedOut = true;
fromStorage = true;
} else {
ATInternet.Utils.optedOut = false;
}
} else if (ATInternet.Utils.optedOut === false) {
if (tag.getParam(_config.userIdHitName) === _config.optOut) {
tag.delParam(_config.userIdHitName);
}
if (tag.storage.get(_config.userIdStorageName, true) === _config.optOut) {
tag.storage.del(_config.userIdStorageName);
}
}
_user.optout.isOptedout = ATInternet.Utils.optedOut;
_user.optout.fromStorage = fromStorage;
};
/**
* Check if user id cookie has to be set on server side (CDDC).
* @memberof ATInternet.Tracker.Plugins.ClientSideUserId#
* @function
* return {bool}
* @private
*/
var _isServerSideUserId = function () {
var cddcDomain = _config.baseDomain;
if (!cddcDomain) {
var cookieDomain = tag.getConfig('cookieDomain');
if (cookieDomain) {
cddcDomain = cookieDomain;
if (cddcDomain.charAt(0) === '.') {
cddcDomain = cddcDomain.substring(1, cddcDomain.length);
}
}
}
var collectDomain = tag.builder.getCollectDomain();
var currentDomain = tag.utils.getHostName();
return !!(cddcDomain && collectDomain && currentDomain && collectDomain.indexOf(cddcDomain) !== -1 && currentDomain.indexOf(cddcDomain) !== -1);
};
/**
* Check if current configuration is ITP compatible.
* @memberof ATInternet.Tracker.Plugins.ClientSideUserId#
* @function
* @return {boolean}
* @private
*/
var _isITPCompatible = function () {
var isITP = false;
var configHttp = tag.getConfig('forceHttp');
if (!configHttp && _config.itpCompliant) {
// Optout status or userid from customer context have priority
if (typeof _user.contextUserId === 'undefined' && !_user.optout.isOptedout) {
// Server side has to be checked on:
// -> 'never' mode
// --> on all devices/browser
// -> 'always' mode:
// -> 'required' mode:
// --> on devices/browser other than Apple/Safari
// --> on devices/browser like Apple/Safari with no userid cookie from client side
switch (_config.clientSideMode) {
case 'never':
isITP = _isServerSideUserId();
break;
case 'always':
case 'required':
if (!_isClient || (_user.storageUserId === null)) {
isITP = _isServerSideUserId();
}
break;
}
}
}
return isITP;
};
/**
* Init user object
* @memberof ATInternet.Tracker.Plugins.ClientSideUserId#
* @function
* @private
*/
var _initUser = function () {
_user = {
contextUserId: undefined,
storageUserId: null,
finalUserId: null,
isFromTrackerContext: false,
forceStorage: false,
optout: {
isOptedout: false,
fromStorage: false
}
};
};
/**
* Init global context.
* @memberof ATInternet.Tracker.Plugins.ClientSideUserId#
* @function
* @private
*/
var _initContext = function () {
// Init user object
_initUser();
// Process OPT-OUT first
_setOptoutSettings();
// Get current user IDs
_user.contextUserId = tag.getContext('userIdentifier');
_user.storageUserId = tag.storage.get('atuserid', true);
// Init context parameters
_isClient = _isClientConfiguration();
// Check if user id has to be set from server side (CDDC)
_isITP = _isITPCompatible();
};
/**
* Process user object
* @memberof ATInternet.Tracker.Plugins.ClientSideUserId#
* @function
* @private
*/
var _processUser = function () {
_user.isFromTrackerContext = false;
_user.forceStorage = false;
if (_user.optout.isOptedout) {
_user.finalUserId = _config.optOut;
_user.isFromTrackerContext = !_user.optout.fromStorage;
_user.forceStorage = true;
} else if (tag.getConfig('disableCookie') || tag.getConfig('disableStorage')) {
_user.finalUserId = tag.getParam(_config.userIdHitName); // Consent-NO
_user.isFromTrackerContext = true;
} else if (typeof _user.contextUserId !== 'undefined') {
_user.finalUserId = _user.contextUserId;
_user.isFromTrackerContext = true;
} else if (_user.storageUserId !== null) {
_user.finalUserId = _user.storageUserId;
} else {
_user.finalUserId = ATInternet.Utils.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' && _user.storageUserId === null) || _user.isFromTrackerContext) {
var expiration_date = new Date();
expiration_date.setTime(expiration_date.getTime() + (_config.userIdCookieDuration * 24 * 60 * 60 * 1000));
tag.storage.set(_config.userIdStorageName, _user.finalUserId, {
end: expiration_date,
path: '/'
}, _user.forceStorage);
if (ATInternet.Utils.consent && !_user.isFromTrackerContext && _user.finalUserId !== tag.storage.get(_config.userIdStorageName, true)) {
tag.setParam(_config.userIdHitName, _user.finalUserId + '-NO', {
multihit: true,
permanent: true,
hitType: ['all']
});
}
}
};
/**
* Set user ID in buffer and storage.
* @memberof ATInternet.Tracker.Plugins.ClientSideUserId#
* @function
* @private
*/
var _setUserId = function () {
tag.setParam(_config.userIdHitName, _user.finalUserId, {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 (!_isITP && (_isClient || _user.optout.isOptedout || (typeof _user.contextUserId !== 'undefined'))) {
tag.setConfig('userIdOrigin', 'client');
_processUser();
_setUserId();
} else {
tag.setConfig('userIdOrigin', 'server');
}
};
/**
* @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', 'Utils'];
tag.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
*/
tag.clientSideUserId = {};
/**
* [Helper added by plugin {@link ATInternet.Tracker.Plugins.ClientSideUserId ClientSideUserId}]
* Add a user ID to all hits "&idclient=" and store it in "atuserid".
* @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
*/
tag.clientSideUserId.set = function (id) {
if (!_user.optout.isOptedout) {
_user.finalUserId = id;
_user.isFromTrackerContext = true;
_user.forceStorage = false;
_setUserId();
}
/* @if debug */
tag.debug('ClientSideUserId:clientSideUserId:set', _debug.level, _debug.messageEnd, {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
*/
tag.clientSideUserId.store = function () {
_user.finalUserId = (tag.getParam(_config.userIdHitName) || _user.finalUserId);
if (_user.finalUserId !== null &&
_user.finalUserId !== ATInternet.Utils.privacy.CONSENTNO &&
_user.finalUserId !== _user.storageUserId) {
_user.isFromTrackerContext = true;
_user.forceStorage = true;
_setStorageValue();
}
/* @if debug */
tag.debug('ClientSideUserId:clientSideUserId:store', _debug.level, _debug.messageEnd, {id: _user.finalUserId});
/* @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|null}
* @public
*/
tag.clientSideUserId.get = function () {
/* @if debug */
tag.debug('ClientSideUserId:clientSideUserId:get', _debug.level, _debug.messageEnd, {id: _user.finalUserId});
/* @endif */
_user.finalUserId = (tag.getParam(_config.userIdHitName) || _user.finalUserId);
return _user.finalUserId;
};
/**
*[Helper added by plugin {@link ATInternet.Tracker.Plugins.ClientSideUserId ClientSideUserId}] Clear user ID.
* @alias clientSideUserId.clear
* @memberof! ATInternet.Tracker.Tag#
* @function
* @example
* <pre><code class="javascript">tag.clientSideUserId.clear();</code></pre>
* @public
*/
tag.clientSideUserId.clear = function () {
/* @if debug */
tag.debug('ClientSideUserId:clientSideUserId:clear', _debug.level, _debug.messageEnd, {id: _user.finalUserId});
/* @endif */
_initUser();
tag.delParam(_config.userIdHitName);
tag.storage.del(_config.userIdStorageName);
};
// For unit tests on private elements !!!
/* @if test */
var _this = this;
_this._isClientConfiguration = _isClientConfiguration;
_this._setOptoutSettings = _setOptoutSettings;
_this._isServerSideUserId = _isServerSideUserId;
_this._isITPCompatible = _isITPCompatible;
_this._initUser = _initUser;
_this._initContext = _initContext;
_this._processUser = _processUser;
_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._userIdFromContext = _user.contextUserId;
_this._userIdFromStorage = _user.storageUserId;
_this.getThemAll = function () {
_this._userIdCookieDuration = _config.userIdCookieDuration;
_this._userIdExpirationMode = _config.userIdExpirationMode;
_this._optOut = _config.optOut;
_this._userIdStorageName = _config.userIdStorageName;
_this._userIdFromContext = _user.contextUserId;
_this._userIdFromStorage = _user.storageUserId;
};
/* @endif */
};
ATInternet.Tracker.addPlugin('ClientSideUserId');