/**
* @class
* @classdesc Plugin to manage visitor consent
* @name Privacy
* @memberof ATInternet.Tracker.Plugins
* @type {function}
* @param tag {Object} Instance of the Tag used
* @public
*/
ATInternet.Tracker.Plugins.Privacy = function (tag) {
'use strict';
/**
* Object used to manage authority
* @name Authority
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @inner
* @constructor
* @param config {Object}
* @property {function} setVisitorOptout Authority helper, see details here {@link ATInternet.Tracker.Tag#Authority.setVisitorOptout}
* @property {function} setVisitorOptin Authority helper, see details here {@link ATInternet.Tracker.Tag#Authority.setVisitorOptin}
* @property {function} setVisitorRandomID Authority helper, see details here {@link ATInternet.Tracker.Tag#Authority.setVisitorRandomID}
* @property {function} setVisitorMode Authority helper, see details here {@link ATInternet.Tracker.Tag#Authority.setVisitorMode}
* @property {function} getAuthority Authority helper, see details here {@link ATInternet.Tracker.Tag#Authority.getAuthority}
* @property {function} getVisitorMode Authority helper, see details here {@link ATInternet.Tracker.Tag#Authority.getVisitorMode}
* @property {function} addAuthority Authority helper, see details here {@link ATInternet.Tracker.Tag#Authority.addAuthority}
* @property {function} extendRemoveStorage Authority helper, see details here {@link ATInternet.Tracker.Tag#Authority.extendRemoveStorage}
* @property {function} extendRemoveBuffer Authority helper, see details here {@link ATInternet.Tracker.Tag#Authority.extendRemoveBuffer}
* @property {function} extendRemoveContext Authority helper, see details here {@link ATInternet.Tracker.Tag#Authority.extendRemoveContext}
* @property {function} extendRemoveProperties Authority helper, see details here {@link ATInternet.Tracker.Tag#Authority.extendRemoveProperties}
* @property {function} updateStorageDuration Authority helper, see details here {@link ATInternet.Tracker.Tag#Authority.updateStorageDuration}
* @private
*/
var Authority = function (config) {
/* -------- Authority properties -------- */
var _thisAuthority = this;
var _authority = null;
var _visitorMode = null;
var _privacyParameters = {
storageParams: [],
bufferParams: [],
contextParams: [],
propertiesParams: []
};
var _config = config;
var DEFAULT = 'default';
var OPTIN = 'optin';
var OPTOUT = 'optout';
var RANDOM = 'random';
/* -------- Authority internal methods -------- */
/**
* Initialize Authority context
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @private
*/
function _initAuthorityContext() {
var authorityName = tag.storage.get([_config.authorityStorageName, 'authority_name'], true);
var visitorMode = tag.storage.get([_config.authorityStorageName, 'visitor_mode'], true);
if (authorityName && visitorMode) {
if (authorityName === DEFAULT) {
if (visitorMode === OPTIN) {
_thisAuthority.setVisitorOptin();
} else if (visitorMode === OPTOUT) {
_thisAuthority.setVisitorOptout();
} else if (visitorMode === RANDOM) {
_thisAuthority.setVisitorRandomID();
} else {
_thisAuthority.setVisitorMode(authorityName, visitorMode);
}
} else {
_thisAuthority.setVisitorMode(authorityName, visitorMode);
}
}
}
/**
* Set Authority storage
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @private
*/
function _setAuthorityStorage() {
if (_authority && _visitorMode) {
var expirationDate = new Date();
expirationDate.setTime(expirationDate.getTime() + (_visitorMode.storageDuration * 24 * 60 * 60 * 1000));
var authorityStorageValue = {
authority_name: _authority.name,
visitor_mode: _visitorMode.name
};
tag.storage.set(_config.authorityStorageName, authorityStorageValue, {
end: expirationDate,
path: '/'
});
}
}
/**
* Process Authority storage
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @param updateStorageDuration {boolean} Update storage duration
* @private
*/
function _processAuthorityStorage(updateStorageDuration) {
if (_visitorMode) {
if (_visitorMode.storageDuration > 0) {
if (updateStorageDuration) {
_setAuthorityStorage();
} else {
var authorityStorage = tag.storage.get(_config.authorityStorageName, true);
if (authorityStorage === null) {
_setAuthorityStorage();
} else if (typeof authorityStorage === 'object') {
if ((authorityStorage.authority_name !== _authority.name) || (authorityStorage.visitor_mode !== _visitorMode.name)) {
_setAuthorityStorage();
}
}
}
} else {
tag.storage.del(_config.authorityStorageName);
}
}
}
/**
* Process Tracker settings
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @private
*/
function _processTrackerSettings() {
if (_visitorMode) {
for (var keyConfig in _visitorMode.trackerSettings) {
if (_visitorMode.trackerSettings.hasOwnProperty(keyConfig)) {
tag.setConfig(keyConfig, _visitorMode.trackerSettings[keyConfig]);
}
}
}
}
/**
* Process buffer parameters to add
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @private
*/
function _processParamsToAdd() {
if (_visitorMode && _visitorMode.add) {
for (var param in _visitorMode.add.buffer) {
if (_visitorMode.add.buffer.hasOwnProperty(param)) {
tag.setParam(_visitorMode.add.buffer[param].param, _visitorMode.add.buffer[param].value, {
multihit: true,
permanent: true,
hitType: ['all']
});
}
}
}
}
/**
* Process general privacy parameters
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @private
*/
function _processParamsToRemove() {
if (_visitorMode && _visitorMode.remove) {
var val;
for (var key in _visitorMode.remove) {
if (_visitorMode.remove.hasOwnProperty(key)) {
val = [];
if (_visitorMode.remove[key] instanceof Array) {
val = _visitorMode.remove[key];
}
_privacyParameters[key + 'Params'] = val;
}
}
ATInternet.Utils.privacy.setParameters(_privacyParameters);
_processAuthorityStorage(false);
}
}
/**
* Clean storage parameters depending on general privacy
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @private
*/
function _cleanStorageParams() {
var delCallback = function (param) {
tag.storage.del(param);
tag.storage.delPrivate(param);
};
var getCallback = function (param) {
return (tag.storage.get(param, true) || tag.storage.getPrivate(param, true));
};
ATInternet.Utils.privacy.processStorageParams(delCallback, getCallback);
}
/**
* Clean buffer parameters depending on general privacy
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @private
*/
function _cleanBufferParams() {
var getCallback = function (param) {
return tag.getParam(param);
};
var delCallback = function (param) {
tag.delParam(param);
};
var setCallback = function (param, value, options) {
tag.setParam(param, value, options);
};
ATInternet.Utils.privacy.processBufferParams(getCallback, delCallback, setCallback);
}
/**
* Clean context parameters depending on general privacy
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @private
*/
function _cleanContextParams() {
var getCallback = function (context) {
return tag.getContext(context);
};
var delCallback = function (context, param) {
tag.delContext(context, param);
};
var setCallback = function (context, param) {
tag.setContext(context, param);
};
ATInternet.Utils.privacy.processContextParams(getCallback, delCallback, setCallback);
}
/**
* Clean properties parameters depending on general privacy
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @private
*/
function _cleanPropertiesParams() {
var delCallback = function (param) {
tag.delProp(param);
};
ATInternet.Utils.privacy.processPropertiesParams(delCallback);
}
/**
* Add parameter(s) to exclude to current visitor mode
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @param param {Object|string|array} Parameter(s) to add
* @param key {string} Name of the object concerned (storage, buffer, context, properties)
* @param clean {function} Function to execute after processing
* @private
*/
function _extendRemove(param, key, clean) {
if (_visitorMode && _visitorMode.remove) {
if (_visitorMode.remove[key] instanceof Array) {
if (param instanceof Array) {
_visitorMode.remove[key] = _visitorMode.remove[key].concat(param);
} else if (param) {
_visitorMode.remove[key].push(param);
}
} else {
if (param instanceof Array) {
_visitorMode.remove[key] = param;
} else if (param) {
_visitorMode.remove[key] = [param];
}
}
_privacyParameters[key + 'Params'] = _visitorMode.remove[key];
ATInternet.Utils.privacy.setParameters(_privacyParameters);
clean && clean();
}
}
/**
* Tests if the current visitor mode is a consent mode
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @private
*/
function _isConsentVisitorMode() {
var _consentMode = false;
if (_visitorMode && _visitorMode.add && _visitorMode.add.buffer && _visitorMode.add.buffer.visitorConsent) {
_consentMode = !!_visitorMode.add.buffer.visitorConsent.value;
}
return _consentMode;
}
/**
* Add one or more parameters to be excluded from the current visitor mode (for all lists)
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @private
*/
function _extendRemoveListsFromConfig() {
if (!_isConsentVisitorMode() && _config.parametersToExclude.length > 0) {
_thisAuthority.extendRemoveStorage(_config.parametersToExclude);
_thisAuthority.extendRemoveBuffer(_config.parametersToExclude);
_thisAuthority.extendRemoveContext(_config.parametersToExclude);
_thisAuthority.extendRemoveProperties(_config.parametersToExclude);
}
}
/**
* Store current userid
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @private
*/
function _storeUserId() {
tag.clientSideUserId.store();
}
/**
* Clear current userid
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @private
*/
function _clearUserId() {
tag.clientSideUserId.clear();
}
/**
* Process new visitor mode
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @param authority {string} Authority name
* @param visitorMode {string} Visitor mode
* @param clearUserId {boolean} Clear current userid
* @param resetCurrentMode {boolean} Reset current context before applying new one
* @function
* @private
*/
function _processNewVisitorMode(authority, visitorMode, clearUserId, resetCurrentMode) {
if (_config.authorities && _config.authorities[authority] && _config.authorities[authority][visitorMode]) {
clearUserId && _clearUserId();
resetCurrentMode && _thisAuthority.setVisitorOptin();
_authority = _config.authorities[authority];
_visitorMode = _authority[visitorMode];
_processTrackerSettings();
_processParamsToAdd();
_processParamsToRemove();
_cleanStorageParams();
_cleanBufferParams();
_cleanContextParams();
_cleanPropertiesParams();
_extendRemoveListsFromConfig();
}
}
/* -------- Authority helpers -------- */
/**
* Set OPTOUT mode
* @alias Authority.setVisitorOptout
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @public
* @example
* tag.privacy.setVisitorOptout();
*/
_thisAuthority.setVisitorOptout = function () {
ATInternet.Utils.consentReceived(true);
_processNewVisitorMode(DEFAULT, OPTOUT, false, false);
ATInternet.Utils.userOptedOut();
};
/**
* Set OPTIN mode
* @alias Authority.setVisitorOptin
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @public
* @example
* tag.privacy.setVisitorOptin();
*/
_thisAuthority.setVisitorOptin = function () {
ATInternet.Utils.consentReceived(true);
_storeUserId();
_processNewVisitorMode(DEFAULT, OPTIN, false, false);
ATInternet.Utils.userOptedIn();
};
/**
* Set consent received mode
* @alias Authority.setVisitorRandomID
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @public
* @example
* tag.privacy.setVisitorRandomID();
*/
_thisAuthority.setVisitorRandomID = function () {
ATInternet.Utils.consentReceived(false);
_processNewVisitorMode(DEFAULT, RANDOM, false, false);
ATInternet.Utils.userOptedIn();
};
/**
* Set visitor mode
* @alias Authority.setVisitorMode
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @param authority {string} Authority name
* @param visitorMode {string} Visitor mode
* @function
* @public
* @example
* tag.privacy.setVisitorMode('default', 'no-consent');
*/
_thisAuthority.setVisitorMode = function (authority, visitorMode) {
var clearUserId = true;
if (_authority && _visitorMode) {
clearUserId = (authority !== _authority.name) || (visitorMode !== _visitorMode.name);
}
_processNewVisitorMode(authority, visitorMode, clearUserId, true);
};
/**
* Get current authority
* @alias Authority.getAuthority
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @return {Object|null}
* @public
* @example
* var authority = tag.privacy.getAuthority();
*/
_thisAuthority.getAuthority = function () {
return _authority;
};
/**
* Get current visitor mode
* @alias Authority.getVisitorMode
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @return {Object|null}
* @public
* @example
* var visitorMode = tag.privacy.getVisitorMode();
*/
_thisAuthority.getVisitorMode = function () {
return _visitorMode;
};
/**
* Add new authority
* @alias Authority.addAuthority
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @param authority {Object} Authority object
* @function
* @public
* @example
* tag.privacy.addAuthority(customAuthority);
*/
_thisAuthority.addAuthority = function (authority) {
if (authority && typeof authority === 'object') {
_config.authorities = _config.authorities || {};
_config.authorities[authority.name] = authority;
}
};
/**
* Add storage parameter(s) to exclude to current visitor mode
* @alias Authority.extendRemoveStorage
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @param storageParam {Object|string|array} Storage properties
* @function
* @public
* @example
* tag.privacy.extendRemoveStorage('atidvistor'); // entire atidvistor storage
* tag.privacy.extendRemoveStorage({'atidvistor': ['an', 'ac']}); // only 'an' and 'ac' from atidvistor
* tag.privacy.extendRemoveStorage([{'atidvistor': ['an', 'ac']}, {'atredir'}]); // 'an' and 'ac' from atidvistor and entire atredir
* tag.privacy.extendRemoveStorage([{'atidvistor': ['an', 'ac'], 'atredir': ['an', 'ac']}]); // 'an' and 'ac' from atidvistor and atredir
*/
_thisAuthority.extendRemoveStorage = function (storageParam) {
_extendRemove(storageParam, 'storage', _cleanStorageParams);
};
/**
* Add buffer parameter(s) to exclude to current visitor mode
* @alias Authority.extendRemoveBuffer
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @param bufferParam {string|array|Object} Buffer parameters
* @function
* @public
* @example
* tag.privacy.extendRemoveBuffer('an'); // buffer parameter 'an'
* tag.privacy.extendRemoveBuffer(['an', 'ac']); // buffer parameters 'an' and 'ac'
* tag.privacy.extendRemoveBuffer({stc: ['custom1', 'custom2']}); // buffer parameter 'stc', keys 'custom1' and 'custom2'
*/
_thisAuthority.extendRemoveBuffer = function (bufferParam) {
_extendRemove(bufferParam, 'buffer', _cleanBufferParams);
};
/**
* Add context parameter(s) to exclude to current visitor mode
* @alias Authority.extendRemoveContext
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @param contextParam {string|array|Object} Context parameters
* @function
* @public
* @example
* tag.privacy.extendRemoveContext('campaigns'); // 'campaigns' context
* tag.privacy.extendRemoveContext(['campaigns', 'page']); // 'campaigns' and page contexts
* tag.privacy.extendRemoveContext({page: 'vrn'}); // vrn parameter in page context
* tag.privacy.extendRemoveContext({page: ['vrn', 'weborama']}); // vrn and weborama parameters in page context
*/
_thisAuthority.extendRemoveContext = function (contextParam) {
_extendRemove(contextParam, 'context', _cleanContextParams);
};
/**
* Add properties parameter(s) to exclude to current visitor mode
* @alias Authority.extendRemoveProperties
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @param propertiesParam {string|array} Properties parameters
* @function
* @public
* @example
* tag.privacy.extendRemoveProperties('custom'); // 'custom' property
* tag.privacy.extendRemoveProperties(['custom1', 'custom2']); // 'custom1' and custom2 properties
*/
_thisAuthority.extendRemoveProperties = function (propertiesParam) {
_extendRemove(propertiesParam, 'properties', _cleanPropertiesParams);
};
/**
* Update storage duration for authority context
* @alias Authority.updateStorageDuration
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @param storageDuration {number} Storage duration in days
* @function
* @public
* @example
* tag.privacy.updateStorageDuration(90);
*/
_thisAuthority.updateStorageDuration = function (storageDuration) {
if (_visitorMode) {
_visitorMode.storageDuration = storageDuration;
_processAuthorityStorage(true);
}
};
/* -------- Authority init -------- */
_initAuthorityContext();
// For unit tests on private elements !!!
/* @if test */
_thisAuthority._authority = _authority;
_thisAuthority._visitorMode = _visitorMode;
_thisAuthority._privacyParameters = _privacyParameters;
_thisAuthority._initAuthorityContext = _initAuthorityContext;
_thisAuthority._setAuthorityStorage = _setAuthorityStorage;
_thisAuthority._processAuthorityStorage = _processAuthorityStorage;
_thisAuthority._processTrackerSettings = _processTrackerSettings;
_thisAuthority._processParamsToAdd = _processParamsToAdd;
_thisAuthority._processParamsToRemove = _processParamsToRemove;
_thisAuthority._cleanStorageParams = _cleanStorageParams;
_thisAuthority._cleanBufferParams = _cleanBufferParams;
_thisAuthority._cleanContextParams = _cleanContextParams;
_thisAuthority._cleanPropertiesParams = _cleanPropertiesParams;
_thisAuthority._extendRemove = _extendRemove;
_thisAuthority._isConsentVisitorMode = _isConsentVisitorMode;
_thisAuthority._extendRemoveListsFromConfig = _extendRemoveListsFromConfig;
_thisAuthority._processNewVisitorMode = _processNewVisitorMode;
_thisAuthority._storeUserId = _storeUserId;
_thisAuthority._clearUserId = _clearUserId;
/* @endif */
};
var _authorityObject = null;
/* -------- Tag Authority helpers -------- */
/**
* [Object added by plugin {@link ATInternet.Tracker.Plugins.Privacy Privacy}] Tags to manage visitor mode context
* @name privacy
* @inner
* @type {Object}
* @memberof! ATInternet.Tracker.Tag
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#privacy.setVisitorOptout}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#privacy.setVisitorOptin}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#privacy.setVisitorRandomID}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#privacy.setVisitorMode}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#privacy.getAuthority}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#privacy.getVisitorMode}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#privacy.addAuthority}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#privacy.extendRemoveStorage}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#privacy.extendRemoveBuffer}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#privacy.extendRemoveContext}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#privacy.extendRemoveProperties}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#privacy.updateStorageDuration}
* @public
*/
tag.privacy = {
setVisitorOptout: function () {
},
setVisitorOptin: function () {
},
setVisitorRandomID: function () {
},
setVisitorMode: function () {
},
getAuthority: function () {
},
getVisitorMode: function () {
},
addAuthority: function () {
},
extendRemoveStorage: function () {
},
extendRemoveBuffer: function () {
},
extendRemoveContext: function () {
},
extendRemoveProperties: function () {
},
updateStorageDuration: function () {
}
};
/* -------- Plugin init -------- */
/**
* Launch plugin when all dependencies are loaded.
* @memberof ATInternet.Tracker.Plugins.Privacy#
* @function
* @private
*/
var _init = function () {
var dependencies = ['Storage', 'Utils', 'ClientSideUserId'];
tag.plugins.waitForDependencies(dependencies, function () {
// Plugin configuration.
var config = null;
tag.configPlugin('Privacy', dfltPluginCfg || {}, function (newConf) {
config = ATInternet.Utils.cloneSimpleObject(newConf);
});
if (config !== null) {
_authorityObject = new Authority(config);
tag.privacy.setVisitorOptout = _authorityObject.setVisitorOptout;
tag.privacy.setVisitorOptin = _authorityObject.setVisitorOptin;
tag.privacy.setVisitorRandomID = _authorityObject.setVisitorRandomID;
tag.privacy.setVisitorMode = _authorityObject.setVisitorMode;
tag.privacy.getAuthority = _authorityObject.getAuthority;
tag.privacy.getVisitorMode = _authorityObject.getVisitorMode;
tag.privacy.addAuthority = _authorityObject.addAuthority;
tag.privacy.extendRemoveStorage = _authorityObject.extendRemoveStorage;
tag.privacy.extendRemoveBuffer = _authorityObject.extendRemoveBuffer;
tag.privacy.extendRemoveContext = _authorityObject.extendRemoveContext;
tag.privacy.extendRemoveProperties = _authorityObject.extendRemoveProperties;
tag.privacy.updateStorageDuration = _authorityObject.updateStorageDuration;
}
});
};
_init();
// For unit tests on private elements !!!
/* @if test */
this._authorityObject = _authorityObject;
this._init = _init;
/* @endif */
};
ATInternet.Tracker.addPlugin('Privacy');