Source: IdentifiedVisitor/identifiedvisitor.js

/**
 * @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');