Source: SalesTracker/salestracker.js

/**
 * @class
 * @classdesc SalesTracker Plugin is used to track orders, aisle or products.
 * @name SalesTracker
 * @memberof ATInternet.Tracker.Plugins
 * @type {function}
 * @param tag {object} Instance of the Tag used
 * @public
 */
ATInternet.Tracker.Plugins.SalesTracker = function (tag) {
    'use strict';

    var _productsQuantity = 0;

    // Debug object error
    var _error = {
        level: 'ERROR',
        messageBoolean: 'Not a boolean',
        messageObject: 'Not an object',
        messageArray: 'Not an array'
    };

    var _debug = {
        level: 'DEBUG',
        messageEnd: 'method ended'
    };

    /**
     * Convert value to string.
     * @memberof ATInternet.Tracker.Plugins.SalesTracker#
     * @function
     * @param value {object} Value to convert
     * @return {string}
     * @private
     */
    var _value2strIfExist = function (value) {
        if (value === undefined || value === null) return "";
        return value + "";
    };

    /**
     * Add parameter from tag to buffer.
     * @memberof ATInternet.Tracker.Plugins.SalesTracker#
     * @function
     * @param tagObject {object} Object from tag
     * @param param {string} Name of the parameter in buffer
     * @param key {string} Name of the property to get
     * @private
     */
    var _setParamIfExist = function (tagObject, param, key) {
        if (tagObject.hasOwnProperty(key)) {
            var value = _value2strIfExist(tagObject[key]);
            tag.setParam(param, value, {hitType: ['page']});
        }
    };

    /**
     * Check if tag object contains needed properties.
     * @memberof ATInternet.Tracker.Plugins.SalesTracker#
     * @function
     * @param tagObject {object} Object from tag
     * @param neededProperties {Array} List of needed properties
     * @return {boolean}
     * @private
     */
    var _tagObjectInvalid = function (tagObject, neededProperties) {
        for (var i = 0; i < neededProperties.length; i++) {
            if (tagObject[neededProperties[i]] === undefined) {
                return true;
            }
        }
        return false;
    };

    /**
     * Set new customer parameter.
     * @memberof ATInternet.Tracker.Plugins.SalesTracker#
     * @function
     * @param tagObject {object} Object from tag
     * @private
     */
    var _setNewCustomer = function (tagObject) {
        if (typeof tagObject.newCustomer === 'boolean') {
            var newcus = tagObject.newCustomer ? '1' : '0';
            tag.setParam('newcus', newcus, {hitType: ['page']});
        } else if (tagObject.newCustomer) {
            /* @if debug */
            tag.debug('SalesTracker:order:set:newCustomer:Error', _error.level, _error.messageBoolean, tagObject);
            /* @endif */
            if (typeof tag.getParams('newcus') === 'undefined') {
                tag.setParam('newcus', '0', {hitType: ['page']});
            }
        }
    };

    /**
     * Set amount values.
     * @memberof ATInternet.Tracker.Plugins.SalesTracker#
     * @function
     * @param amount {object} Object from tag
     * @private
     */
    var _setAmount = function (amount) {
        if (ATInternet.Utils.isObject(amount)) {
            _setParamIfExist(amount, 'mtht', 'amountTaxFree');
            _setParamIfExist(amount, 'mtttc', 'amountTaxIncluded');
            _setParamIfExist(amount, 'tax', 'taxAmount');
        } else if (amount) {
            /* @if debug */
            tag.debug('SalesTracker:order:set:amount:Error', _error.level, _error.messageObject, {value: amount});
            /* @endif */
        }
    };

    /**
     * Set delivery values.
     * @memberof ATInternet.Tracker.Plugins.SalesTracker#
     * @function
     * @param delivery {object} Object from tag
     * @private
     */
    var _setDelivery = function (delivery) {
        if (ATInternet.Utils.isObject(delivery)) {
            _setParamIfExist(delivery, 'fp', 'shippingFeesTaxIncluded');
            _setParamIfExist(delivery, 'fpht', 'shippingFeesTaxFree');
            _setParamIfExist(delivery, 'dl', 'deliveryMethod');
        } else if (delivery) {
            /* @if debug */
            tag.debug('SalesTracker:order:set:delivery:Error', _error.level, _error.messageObject, {value: delivery});
            /* @endif */
        }
    };

    /**
     * Set discount values.
     * @memberof ATInternet.Tracker.Plugins.SalesTracker#
     * @function
     * @param discount {object} Object from tag
     * @private
     */
    var _setDiscount = function (discount) {
        if (ATInternet.Utils.isObject(discount)) {
            _setParamIfExist(discount, 'dsc', 'discountTaxIncluded');
            _setParamIfExist(discount, 'dscht', 'discountTaxFree');
            _setParamIfExist(discount, 'pcd', 'promotionalCode');
        } else if (discount) {
            /* @if debug */
            tag.debug('SalesTracker:order:set:discount:Error', _error.level, _error.messageObject, {value: discount});
            /* @endif */
        }
    };

    /**
     * Set 'tp' parameter to 'pre1' if current page order need further confirmation.
     * @memberof ATInternet.Tracker.Plugins.SalesTracker#
     * @function
     * @param tagObject {object} Object from tag
     * @private
     */
    var _setConfirmationRequired = function (tagObject) {
        if (typeof tagObject.confirmationRequired === 'boolean') {
            var tp = tagObject.confirmationRequired ? 'pre1' : '';
            tag.setParam('tp', tp, {hitType: ['page']});
        } else if (tagObject.confirmationRequired) {
            /* @if debug */
            tag.debug('SalesTracker:order:set:confirmationRequired:Error', _error.level, _error.messageBoolean, tagObject);
            /* @endif */
            if (typeof tag.getParams('tp') === 'undefined') {
                tag.setParam('tp', '', {hitType: ['page']});
            }
        }
    };

    /**
     * Set custom variables for the order.
     * @memberof ATInternet.Tracker.Plugins.SalesTracker#
     * @function
     * @param orderCustomVariables {Array} List of custom variables to set
     * @private
     */
    var _setCustomVariables = function (orderCustomVariables) {
        var ocv = orderCustomVariables;
        if (ocv instanceof Array) {
            for (var i = 0; i < ocv.length; i++) {
                _setParamIfExist(ocv, "o" + (i + 1), i);
            }
        } else if (ocv) {
            /* @if debug */
            tag.debug('SalesTracker:order:set:orderCustomVariables:Error', _error.level, _error.messageArray, {value: ocv});
            /* @endif */
        }
    };

    /**
     * Set 'tp' parameter to 'cart' if current page is basket.
     * @memberof ATInternet.Tracker.Plugins.SalesTracker#
     * @function
     * @param tagObject {object} Object from tag
     * @private
     */
    var _setIsBasketPage = function (tagObject) {
        if (typeof tagObject.isBasketPage === 'boolean') {
            if (tag.getParams('tp') !== 'pre1') {
                var tp = tagObject.isBasketPage ? 'cart' : '';
                tag.setParam('tp', tp, {hitType: ['page']});
            }
        } else if (tagObject.isBasketPage) {
            /* @if debug */
            tag.debug('SalesTracker:cart:set:isBasketPage:Error', _error.level, _error.messageBoolean, tagObject);
            /* @endif */
            if (typeof tag.getParams('tp') === 'undefined') {
                tag.setParam('tp', '', {hitType: ['page']});
            }
        }
    };

    /**
     * Build full product name from categories and ID.
     * @memberof ATInternet.Tracker.Plugins.SalesTracker#
     * @function
     * @param tagObject {object} Object from tag
     * @private
     */
    var _productIdMaker = function (tagObject) {
        var _product = (tagObject['productId'] ? tagObject['productId'] : '');
        var _category = (tagObject['category'] ? tagObject['category'] + '::' : '');

        var data = tag.utils.manageChapters(tagObject, 'category', 6);
        if (data) {
            _category = data;
        }

        return _category + _product;
    };

    /**
     * Set product values.
     * @memberof ATInternet.Tracker.Plugins.SalesTracker#
     * @function
     * @param product {object} Object from tag
     * @private
     */
    var _addProduct = function (product) {
        if (ATInternet.Utils.isObject(product)) {
            _productsQuantity++;
            var _idx = _productsQuantity;
            var productId = _productIdMaker(product);
            tag.setParam('pdt' + _idx, productId, {hitType: ['page']});
            _setParamIfExist(product, 'qte' + _idx, 'quantity');
            _setParamIfExist(product, 'mt' + _idx, 'unitPriceTaxIncluded');
            _setParamIfExist(product, 'mtht' + _idx, 'unitPriceTaxFree');
            _setParamIfExist(product, 'dsc' + _idx, 'discountTaxIncluded');
            _setParamIfExist(product, 'dscht' + _idx, 'discountTaxFree');
            _setParamIfExist(product, 'pcode' + _idx, 'promotionalCode');
        } else if (product) {
            /* @if debug */
            tag.debug('SalesTracker:cart:add:product:Error', _error.level, _error.messageObject, {value: product});
            /* @endif */
        }
    };

    /**
     * Set viewed product values.
     * @memberof ATInternet.Tracker.Plugins.SalesTracker#
     * @function
     * @param tagObject {object} Object from tag
     * @private
     */
    var _addViewedProduct = function (tagObject) {
        var _str = '';
        var data = tag.utils.manageChapters(tagObject, 'category', 6);
        if (data) {
            _str = data;
        }
        _str += tagObject.productId;

        var _context = tag.getContext('product') || {};
        if (_context.viewedProducts) {
            _context.viewedProducts.push(_str);
        } else {
            _context.viewedProducts = [_str];
        }
        tag.setContext('product', _context);
    };

    /**
     * Get page label with chapters
     * @name _getFullName
     * @memberof ATInternet.Tracker.Plugins.SalesTracker#
     * @function
     * @param tagObject {object} tag object
     * @returns string {string} Click name completed with chapters present in tag object
     * @private
     */
    var _getFullName = function (tagObject) {
        return tag.utils.manageChapters(tagObject, 'chapter', 3) + (tagObject['name'] ? tagObject['name'] : '');
    };

    /**
     * [Object added by plugin {@link ATInternet.Tracker.Plugins.SalesTracker SalesTracker}] Tags to track order values.
     * @name order
     * @memberof ATInternet.Tracker.Tag
     * @inner
     * @type {object}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#order.set}
     * @public
     */
    tag.order = {};

    /**
     * [Object added by plugin {@link ATInternet.Tracker.Plugins.SalesTracker SalesTracker}] Tags to track cart values.
     * @name cart
     * @memberof ATInternet.Tracker.Tag
     * @inner
     * @type {object}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#cart.set}
     * @property {function} add Tag helper, see details here {@link ATInternet.Tracker.Tag#cart.add}
     * @public
     */
    tag.cart = {};

    /**
     * [Object added by plugin {@link ATInternet.Tracker.Plugins.SalesTracker SalesTracker}] Tags to track aisle values.
     * @name aisle
     * @memberof ATInternet.Tracker.Tag
     * @inner
     * @type {object}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#aisle.set}
     * @public
     */
    tag.aisle = {};

    /**
     * [Object added by plugin {@link ATInternet.Tracker.Plugins.SalesTracker SalesTracker}] Tags to manage salesTracker.
     * @name salesTracker
     * @memberof ATInternet.Tracker.Tag
     * @inner
     * @type {object}
     * @private
     */
    tag.salesTracker = {};


    /**
     * [Object added by plugin {@link ATInternet.Tracker.Plugins.SalesTracker SalesTracker}] Tags to track viewed products.
     * @name product
     * @memberof ATInternet.Tracker.Tag
     * @inner
     * @type {object}
     * @property {function} add Tag helper, see details here {@link ATInternet.Tracker.Tag#product.add}
     * @public
     */
    tag.product = {};

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.SalesTracker SalesTracker}] Set order properties.
     * @alias order.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} 10 properties : orderId, turnover, status, newCustomer, amount, delivery, paymentMethod, discount, confirmationRequired, orderCustomVariables
     * @example
     * <pre><code class="javascript">tag.order.set({
     *      orderId: 8235,
     *      turnover: 2049,
     *      status: 1,
     *      newCustomer: true,
     *      amount: {
     *          amountTaxIncluded: 2049,
     *          amountTaxFree: 1649.36,
     *          taxAmount: 339.64
     *      },
     *      delivery: {
     *          shippingFeesTaxIncluded: 19.9,
     *          shippingFeesTaxFree: 16,
     *          deliveryMethod: "1[Colissimo]"
     *      },
     *      paymentMethod: 1,
     *      discount: {
     *          discountTaxIncluded: 9.9,
     *          discountTaxFree: 7.96,
     *          promotionalCode: "CDPR15485Q"
     *      },
     *      confirmationRequired: false,
     *      orderCustomVariables: [5, 30 ,14, "[contact tel]", 1],
     * });
     * </code></pre>
     * @public
     */
    tag.order.set = function (tagObject) {
        var valid = false;
        if (ATInternet.Utils.isObject(tagObject) && !ATInternet.Utils.isEmptyObject(tagObject)) {
            valid = true;
            tag.dispatchSubscribe('page'); //Register helper to final call to send hit
            tag.dispatchSubscribe('salesTracker'); //Register helper to final call
            _setParamIfExist(tagObject, 'cmd', 'orderId');
            _setParamIfExist(tagObject, 'roimt', 'turnover');
            _setParamIfExist(tagObject, 'st', 'status');
            _setNewCustomer(tagObject);
            _setAmount(tagObject.amount);
            _setDelivery(tagObject.delivery);
            _setParamIfExist(tagObject, 'mp', 'paymentMethod');
            _setDiscount(tagObject.discount);
            _setConfirmationRequired(tagObject);
            _setCustomVariables(tagObject.orderCustomVariables);
        }
        /* @if debug */
        tag.debug('SalesTracker:order:set', _debug.level, _debug.messageEnd, tagObject);
        /* @endif */
        return valid;
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.SalesTracker SalesTracker}] Set cart properties.
     * @alias cart.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} 2 properties : cartId, isBasketPage
     * @example
     * <pre><code class="javascript">tag.cart.set({
     *      cartId: 8235,
     *      isBasketPage: true
     * });</code></pre>
     * @public
     */
    tag.cart.set = function (tagObject) {
        var valid = false;
        if (ATInternet.Utils.isObject(tagObject) && !ATInternet.Utils.isEmptyObject(tagObject)) {
            valid = true;
            tag.dispatchSubscribe('page'); //Register helper to final call to send hit
            tag.dispatchSubscribe('salesTracker'); //Register helper to final call
            _setParamIfExist(tagObject, 'idcart', 'cartId');
            _setIsBasketPage(tagObject);
        }
        /* @if debug */
        tag.debug('SalesTracker:cart:set', _debug.level, _debug.messageEnd, tagObject);
        /* @endif */
        return valid;
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.SalesTracker SalesTracker}] Add product to cart.
     * @alias cart.add
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} 1 property : product
     * @example
     * <pre><code class="javascript">tag.cart.add({
     *      product: {
     *          category1: "1[Computers_and_Networking]",
     *          category2: "25[Computers]",
     *          category3: "56[Laptops]",
     *          ...
     *          category6: "300[Chromebook]",
     *          productId: "564[laptop_ACER_A56]",
     *          quantity: 1,
     *          unitPriceTaxIncluded: 549,
     *          unitPriceTaxFree: 456.2,
     *          discountTaxIncluded: 10,
     *          discountTaxFree: 8.04,
     *          promotionalCode: "Offre_New_Customer"
     *      }
     * });
     * </code></pre>
     * @public
     */
    tag.cart.add = function (tagObject) {
        var valid = false;
        if (ATInternet.Utils.isObject(tagObject) && !ATInternet.Utils.isEmptyObject(tagObject)) {
            valid = true;
            _addProduct(tagObject.product);
        }
        /* @if debug */
        tag.debug('SalesTracker:cart:add', _debug.level, _debug.messageEnd, tagObject);
        /* @endif */
        return valid;
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.SalesTracker SalesTracker}] Set aisle properties.
     * @alias aisle.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} 6 properties : level1, level2, level3, level4, level5, level6
     * @example
     * <pre><code class="javascript">tag.aisle.set({
     *      level1: "10[high_tech]",
     *      level2: "20[Computers_network]",
     *      level3: "30[Computers]",
     *      level4: "40[Laptops]",
     *      level5: "50[Asus]",
     *      level6: "60[17]"
     * });
     * </code></pre>
     * @public
     */
    tag.aisle.set = function (tagObject) {
        var valid = false;
        if (ATInternet.Utils.isObject(tagObject) && !ATInternet.Utils.isEmptyObject(tagObject)) {
            valid = true;
            tag.dispatchSubscribe('page'); //Register helper to final call to send hit
            var aisl = tag.utils.manageChapters(tagObject, 'level', 6);
            aisl = aisl.replace(/::$/gi, '');
            tag.setParam('aisl', aisl, {hitType: ['page']});
        }
        /* @if debug */
        tag.debug('SalesTracker:aisle:set', _debug.level, _debug.messageEnd, tagObject);
        /* @endif */
        return valid;
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.SalesTracker SalesTracker}] Add viewed product.
     * @alias product.add
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} 4 properties : productId, category1, category2, category3
     * @example
     * <pre><code class="javascript">tag.product.add({
     *      productId: "564[laptop_ACER_A56]",
     *      category1: "1[Computers_and_Networking]",
     *      category2: "25[Computers]",
     *      category3: "56[Laptops]"
     * });
     * </code></pre>
     * @public
     */
    tag.product.add = function (tagObject) {
        var valid = false;
        if (ATInternet.Utils.isObject(tagObject) && !ATInternet.Utils.isEmptyObject(tagObject) && !_tagObjectInvalid(tagObject, ['productId'])) {
            valid = true;
            _addViewedProduct(tagObject);
            tag.dispatchSubscribe('salesTracker');
        } else {
            /* @if debug */
            tag.debug('SalesTracker:product:add:Error', _error.level, 'Product object content problem', tagObject);
            /* @endif */
        }
        /* @if debug */
        tag.debug('SalesTracker:product:add', _debug.level, _debug.messageEnd, tagObject);
        /* @endif */
        return valid;
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.SalesTracker SalesTracker}] Will be called by tracker.dispatch if any SalesTracker has been set.
     * @alias salesTracker.onDispatch
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param callback {function} Callback to execute
     * @private
     */
    tag.salesTracker.onDispatch = function (callback) {
        var productContext = tag.getContext('product');
        if (productContext && productContext.viewedProducts) {
            var hitType = ['product'];
            var pageContext = tag.getContext('page');
            if (typeof pageContext !== 'undefined') {
                tag.setParam('p', _getFullName(pageContext), {'hitType': hitType});
                tag.setParam('s2', pageContext.level2 || '', {'hitType': hitType});
            }
            tag.setParam('pdtl', productContext.viewedProducts.join('|'), {'truncate': true, 'hitType': hitType});
            tag.setParam('type', 'pdt', {'hitType': hitType});
            tag.sendHit(null, [['hitType', hitType]], callback, null, null);
        }
        /* @if debug */
        if (tag.getParams('cmd') === '') {
            tag.debug('SalesTracker:order:onDispatch:Error', _error.level, 'Required "orderId" parameter is not defined');
        }
        if (!tag.getParams('idcart') && ((tag.getParams('tp') === 'cart') || (tag.getParams('tp') === 'pre1'))) {
            tag.debug('SalesTracker:cart:onDispatch:Error', _error.level, 'Required "cartId" parameter is not defined');
        }
        /* @endif */
    };

    // For unit tests on private elements !!!
    /* @if test */
    var _this = this;
    _this._value2strIfExist = _value2strIfExist;
    _this._setParamIfExist = _setParamIfExist;
    _this._tagObjectInvalid = _tagObjectInvalid;
    _this._setNewCustomer = _setNewCustomer;
    _this._setAmount = _setAmount;
    _this._setDelivery = _setDelivery;
    _this._setDiscount = _setDiscount;
    _this._setConfirmationRequired = _setConfirmationRequired;
    _this._setCustomVariables = _setCustomVariables;
    _this._setIsBasketPage = _setIsBasketPage;
    _this._productIdMaker = _productIdMaker;
    _this._addProduct = _addProduct;
    _this._addViewedProduct = _addViewedProduct;
    _this._getFullName = _getFullName;
    /* @endif */
};
ATInternet.Tracker.addPlugin('SalesTracker');