Source: Ecommerce/ecommerce.js

/**
 * @class
 * @classdesc Plugin used to manage ecommerce event sending.
 * @name Ecommerce
 * @memberof ATInternet.Tracker.Plugins
 * @type {function}
 * @param parent {object} Instance of the Tag used
 * @public
 */
window['ATInternet']['Tracker']['Plugins']['Ecommerce'] = function (parent) {
    "use strict";

    var _config = null;
    var _utility = null;
    var _salesTracker = null;
    var _salesInsights = null;

    /* ---------------------------------- Utility properties ------------------------------------------------- */

    // Types of SalesInsights events
    var Types = {
        product: {
            awaiting_payment: 'product.awaiting_payment',
            add_to_cart: 'product.add_to_cart',
            click: 'product.click',
            display: 'product.display',
            page_display: 'product.page_display',
            purchased: 'product.purchased',
            remove_from_cart: 'product.remove_from_cart'
        },
        cart: {
            awaiting_payment: 'cart.awaiting_payment',
            creation: 'cart.creation',
            delivery: 'cart.delivery',
            display: 'cart.display',
            payment: 'cart.payment',
            update: 'cart.update'
        },
        transaction: {
            confirmation: 'transaction.confirmation'
        }
    };

    //  Main keys of SalesInsights objects
    var Keys = {
        product: 'j:product',
        cart: 'j:cart',
        shipping: 'j:shipping',
        payment: 'j:payment',
        transaction: 'j:transaction'
    };

    //  Property keys of SalesInsights objects
    var Properties = {
        product: {
            id: {
                event: 's:id',
                tag: 'id'
            },
            variant: {
                event: 's:variant',
                tag: 'variant'
            },
            $: {
                event: 's:$',
                tag: '$'
            },
            brand: {
                event: 's:brand',
                tag: 'brand'
            },
            discount: {
                event: 'b:discount',
                tag: 'discount'
            },
            pricetaxincluded: {
                event: 'f:pricetaxincluded',
                tag: 'pricetaxincluded'
            },
            pricetaxfree: {
                event: 'f:pricetaxfree',
                tag: 'pricetaxfree'
            },
            currency: {
                event: 's:currency',
                tag: 'currency'
            },
            stock: {
                event: 'b:stock',
                tag: 'stock'
            },
            quantity: {
                event: 'n:quantity',
                tag: 'quantity'
            },
            category1: {
                event: 's:category1',
                tag: 'category1'
            },
            category2: {
                event: 's:category2',
                tag: 'category2'
            },
            category3: {
                event: 's:category3',
                tag: 'category3'
            },
            category4: {
                event: 's:category4',
                tag: 'category4'
            },
            category5: {
                event: 's:category5',
                tag: 'category5'
            },
            category6: {
                event: 's:category6',
                tag: 'category6'
            },
            cartcreation: {
                event: 'b:cartcreation',
                tag: 'cartcreation'
            }
        },
        cart: {
            id: {
                event: 's:id',
                tag: 'id'
            },
            version: {
                event: 's:version',
                tag: 'version'
            },
            currency: {
                event: 's:currency',
                tag: 'currency'
            },
            turnovertaxincluded: {
                event: 'f:turnovertaxincluded',
                tag: 'turnovertaxincluded'
            },
            turnovertaxfree: {
                event: 'f:turnovertaxfree',
                tag: 'turnovertaxfree'
            },
            quantity: {
                event: 'n:quantity',
                tag: 'quantity'
            },
            nbdistinctproduct: {
                event: 'n:nbdistinctproduct',
                tag: 'nbdistinctproduct'
            },
            creation_utc: {
                event: 'd:creation_utc',
                tag: 'creation_utc'
            }
        },
        shipping: {
            delivery: {
                event: 's:delivery',
                tag: 'delivery'
            },
            costtaxincluded: {
                event: 'f:costtaxincluded',
                tag: 'costtaxincluded'
            },
            costtaxfree: {
                event: 'f:costtaxfree',
                tag: 'costtaxfree'
            }
        },
        payment: {
            mode: {
                event: 's:mode',
                tag: 'mode'
            }
        },
        customer: {
            'new': {
                event: 'b:new',
                tag: 'new'
            }
        },
        transaction: {
            id: {
                event: 's:id',
                tag: 'id'
            },
            promocode: {
                event: 'a:s:promocode',
                tag: 'promocode'
            },
            firstpurchase: {
                event: 'b:firstpurchase',
                tag: 'firstpurchase'
            }
        }
    };

    // Debug object error
    var _error = {
        trigger: 'Event:event:set:Error',
        level: 'ERROR',
        messageArray: 'Not an array',
        messageObject: 'Not an object'
    };

    /* ---------------------------------- Utility methods ------------------------------------------------- */

    /**
     * Object used to manage utility methods
     * @name Utility
     * @memberof ATInternet.Tracker.Plugins.Ecommerce#
     * @inner
     * @type {function}
     * @property {function} isObject Tag helper, see details here {@link ATInternet.Tracker.Tag#Utility.isObject}
     * @property {function} objectKeysToLowercase Tag helper, see details here {@link ATInternet.Tracker.Tag#Utility.objectKeysToLowercase}
     * @property {function} arrayObjectKeysToLowercase Tag helper, see details here {@link ATInternet.Tracker.Tag#Utility.arrayObjectKeysToLowercase}
     * @property {function} setValueFromKey Tag helper, see details here {@link ATInternet.Tracker.Tag#Utility.setValueFromKey}
     * @private
     */
    var Utility = function () {

        /**
         * Check if type of tag is object.
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param tagObject {object} Object from tag
         * @return {boolean}
         * @private
         */
        this.isObject = function (tagObject) {
            return ((typeof tagObject === 'object') && !(tagObject instanceof Array));
        };

        /**
         * Change tag object properties to lowercase
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param tagObject {object} Object from tag
         * @return {object}
         * @private
         */
        this.objectKeysToLowercase = function (tagObject) {
            var tagObjectUtil = {};
            var newKey;
            for (var tagKey in tagObject) {
                if (tagObject.hasOwnProperty(tagKey)) {
                    newKey = tagKey.toLowerCase();
                    newKey = ((newKey === 'name') ? '$' : newKey);
                    tagObjectUtil[newKey] = tagObject[tagKey];
                }
            }
            return tagObjectUtil;
        };

        /**
         * Change array tag object properties to lowercase
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param tagObject {object} Object from tag
         * @return {object}
         * @private
         */
        this.arrayObjectKeysToLowercase = function (tagObject) {
            var tagObjectUtil = [];
            for (var i = 0; i < tagObject.length; i++) {
                tagObjectUtil.push(_utility.objectKeysToLowercase(tagObject[i]));
            }
            return tagObjectUtil;
        };

        /**
         * Get parameter value.
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param tagObject {object} Object from tag
         * @param hitKey {string} Name of the parameter in buffer
         * @param tagKey {string} Name of the property to get
         * @param hitObject {object} Hit object
         * @private
         */
        this.setValueFromKey = function (tagObject, hitKey, tagKey, hitObject) {
            if (tagObject.hasOwnProperty(tagKey)) {
                if (typeof tagObject[tagKey] !== 'undefined') {
                    hitObject[hitKey] = tagObject[tagKey];
                }
            }
        };
    };

    /* ---------------------------------- SalesTracker methods ------------------------------------------------- */

    /**
     * Object used to manage SalesTracker methods
     * @name SalesTracker
     * @memberof ATInternet.Tracker.Plugins.Ecommerce#
     * @inner
     * @type {function}
     * @property {function} processCartAmounts Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesTracker.processCartAmounts}
     * @property {function} processCartId Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesTracker.processCartId}
     * @property {function} processTransactionId Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesTracker.processTransactionId}
     * @property {function} processPromotionalCode Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesTracker.processPromotionalCode}
     * @property {function} processShipping Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesTracker.processShipping}
     * @property {function} processCustomer Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesTracker.processCustomer}
     * @property {function} processProductCategories Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesTracker.processProductCategories}
     * @property {function} processCartProducts Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesTracker.processCartProducts}
     * @property {function} processViewedProducts Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesTracker.processViewedProducts}
     * @private
     */
    var SalesTracker = function () {

        /**
         * Set SalesTracker order amounts from cart object
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param cartObject {object} Cart object
         * @private
         */
        this.processCartAmounts = function (cartObject) {
            var cart = cartObject || {};
            var turnovertaxincluded = Number(cart['turnovertaxincluded']) || 0;
            var turnovertaxfree = Number(cart['turnovertaxfree']) || 0;
            var taxAmount = (turnovertaxincluded || turnovertaxfree) - (turnovertaxfree || turnovertaxincluded);
            parent.order.set({
                turnover: turnovertaxincluded,
                amount: {
                    amountTaxIncluded: turnovertaxincluded,
                    amountTaxFree: turnovertaxfree,
                    taxAmount: taxAmount.toFixed(2)
                }
            });
        };

        /**
         * Set SalesTracker cart from cart object
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param cartObject {object} Cart object
         * @param isBasketPage {Boolean}
         * @private
         */
        this.processCartId = function (cartObject, isBasketPage) {
            var cart = cartObject || {};
            parent.cart.set({
                cartId: cart['id'],
                isBasketPage: isBasketPage
            });
        };

        /**
         * Set order for SalesTracker from transaction object
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param transactionObject {object} Sales Insights object
         * @private
         */
        this.processTransactionId = function (transactionObject) {
            var transaction = transactionObject || {};
            parent.order.set({
                orderId: transaction['id'],
                status: 3,
                paymentMethod: '',
                confirmationRequired: false
            });
        };

        /**
         * Process promotional code object for SalesTracker order
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param promotionalCodeArray {Array} Promotional code array
         * @private
         */
        this.processPromotionalCode = function (promotionalCodeArray) {
            parent.order.set({
                discount: {
                    promotionalCode: encodeURIComponent((promotionalCodeArray || []).join('|'))
                }
            });
        };

        /**
         * Process shipping object for SalesTracker order
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param shippingObject {object} Shipping object
         * @private
         */
        this.processShipping = function (shippingObject) {
            var shipping = shippingObject || {};
            parent.order.set({
                delivery: {
                    shippingFeesTaxIncluded: shipping['costtaxincluded'],
                    shippingFeesTaxFree: shipping['costtaxfree'],
                    deliveryMethod: encodeURIComponent(shipping['delivery'])
                }
            });
        };

        /**
         * Process customer object for SalesTracker order
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param customerObject {object} Customer object
         * @private
         */
        this.processCustomer = function (customerObject) {
            var customer = customerObject || {};
            parent.order.set({
                newCustomer: !!customer['firstpurchase'] || !!customer['new']
            });
        };

        /**
         * Process product categories
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param salesTrackerProduct {object} SalesTracker object
         * @param salesInsightsProduct {object} SalesInsights object
         * @private
         */
        this.processProductCategories = function (salesTrackerProduct, salesInsightsProduct) {
            for (var x = 1; x <= 6; x++) {
                if (typeof salesInsightsProduct['category' + x] !== 'undefined') {
                    salesTrackerProduct['category' + x] = salesInsightsProduct['category' + x] ? '[' + encodeURIComponent(salesInsightsProduct['category' + x]) + ']' : '';
                }
            }
        };

        /**
         * Process products array for SalesTracker cart
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param productsArray {Array} Products array
         * @private
         */
        this.processCartProducts = function (productsArray) {

            var products = productsArray || [];
            var salesTrackerProduct;

            for (var i = 0; i < products.length; i++) {
                salesTrackerProduct = {
                    productId: products[i]['id'] + (products[i]['$'] ? '[' + encodeURIComponent(products[i]['$']) + ']' : ''),
                    quantity: products[i]['quantity'],
                    unitPriceTaxIncluded: products[i]['pricetaxincluded'],
                    unitPriceTaxFree: products[i]['pricetaxfree']
                };
                this.processProductCategories(salesTrackerProduct, products[i]);
                parent.cart.add({
                    product: salesTrackerProduct
                });

            }
        };

        /**
         * Process products array for SalesTracker viewed products
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param productsArray {Array} Products array
         * @private
         */
        this.processViewedProducts = function (productsArray) {

            var products = productsArray || [];
            var salesTrackerProduct;

            for (var i = 0; i < products.length; i++) {
                salesTrackerProduct = {
                    productId: products[i]['id'] + (products[i]['$'] ? '[' + encodeURIComponent(products[i]['$']) + ']' : '')
                };

                this.processProductCategories(salesTrackerProduct, products[i]);
                parent.product.add(salesTrackerProduct);
            }
        };

    };

    /* ---------------------------------- Ecommerce methods ------------------------------------------------- */

    /**
     * Object used to manage SalesInsights methods
     * @name SalesInsights
     * @memberof ATInternet.Tracker.Plugins.Ecommerce#
     * @inner
     * @type {function}
     * @property {function} initCartWithId Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesInsights.initCartWithId}
     * @property {function} getObjectValueFromType Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesInsights.getObjectValueFromType}
     * @property {function} setEventFromProductsAndCart Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesInsights.setEventFromProductsAndCart}
     * @property {function} setProductAwaitingPayment Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesInsights.setProductAwaitingPayment}
     * @property {function} updateProductAwaitingPayment Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesInsights.updateProductAwaitingPayment}
     * @property {function} setProductDisplay Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesInsights.setProductDisplay}
     * @property {function} setProductClick Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesInsights.setProductClick}
     * @property {function} setProductPageDisplay Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesInsights.setProductPageDisplay}
     * @property {function} setProductAddToCart Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesInsights.setProductAddToCart}
     * @property {function} setProductRemoveFromCart Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesInsights.setProductRemoveFromCart}
     * @property {function} setCartCreation Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesInsights.setCartCreation}
     * @property {function} updateCartCreation Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesInsights.updateCartCreation}
     * @property {function} setProductPurchased Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesInsights.setProductPurchased}
     * @property {function} updateProductPurchased Tag helper, see details here {@link ATInternet.Tracker.Tag#SalesInsights.updateProductPurchased}
     * @private
     */
    var SalesInsights = function () {

        /**
         * Init cart object with cart ID
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param id {String} cart ID
         * @return {object}
         * @private
         */
        this.initCartWithId = function (id) {
            var cart = {};
            cart[Properties.cart.id.event] = id;
            cart[Properties.cart.currency.event] = "";
            cart[Properties.cart.turnovertaxincluded.event] = 0;
            cart[Properties.cart.turnovertaxfree.event] = 0;
            cart[Properties.cart.quantity.event] = 0;
            cart[Properties.cart.nbdistinctproduct.event] = 0;
            return cart;
        };

        /**
         * Get object from type
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param type {String} Type name
         * @param key {String} Key name ('transaction', 'cart', etc.)
         * @return {object}
         * @private
         */
        this.getObjectValueFromType = function (type, key) {
            var typeObject;
            var transaction = {};
            var contextEcommerceObject = parent.getContext('ecommerce') || [];
            for (var i = 0; i < contextEcommerceObject.length; i++) {
                typeObject = contextEcommerceObject[i][type] || {};
                if (typeObject[key]) {
                    transaction = typeObject[key];
                    break;
                }
            }
            return transaction;
        };

        /**
         * Generate events from products array and cart object
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param type {string} Event type
         * @param productsArray {Array} Products array
         * @param cart {object} cart object
         * @private
         */
        this.setEventFromProductsAndCart = function (type, productsArray, cart) {
            var products = productsArray || [];
            var addObject = {};
            for (var i = 0; i < products.length; i++) {
                if (i === 0) {
                    parent.event.set(type, products[i], Keys.product, 'ecommerce');
                    if (cart && Object.keys(cart).length !== 0) {
                        parent.event.set(type, cart, Keys.cart, 'ecommerce');
                    }
                }
                else {
                    addObject[Keys.product] = products[i];
                    if (cart && Object.keys(cart).length !== 0) {
                        addObject[Keys.cart] = cart;
                    }
                    parent.event.add(type, addObject, 'ecommerce');
                }
                addObject = {};
            }
        };

        /**
         * Generate 'product.awaiting_payment' events
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param productsArray {Array} Products array
         * @param cart {object} cart object
         * @private
         */
        this.setProductAwaitingPayment = function (productsArray, cart) {
            this.setEventFromProductsAndCart(Types.product.awaiting_payment, productsArray, cart);
        };

        /**
         * Set version to ProductAwaitingPayment from CartAwaitingPayment cart
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param cart {object} cart object
         * @private
         */
        this.updateProductAwaitingPayment = function (cart) {
            var idCart = cart ? cart[Properties.cart.id.event] : '';
            var versionCart = cart ? cart[Properties.cart.version.event] : '';
            if (idCart && versionCart) {
                // Complete 'product.awaiting' events
                var productAwaiting;
                var contextEcommerceObject = parent.getContext('ecommerce') || [];
                for (var i = 0; i < contextEcommerceObject.length; i++) {
                    productAwaiting = contextEcommerceObject[i][Types.product.awaiting_payment];
                    if (productAwaiting) {
                        productAwaiting[Keys.cart] = {};
                        productAwaiting[Keys.cart][Properties.cart.id.event] = idCart;
                        productAwaiting[Keys.cart][Properties.cart.version.event] = versionCart;
                        contextEcommerceObject[i][Types.product.awaiting_payment] = productAwaiting;
                    }
                }
            }
        };

        /**
         * Generate 'product.display' events
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param productsArray {Array} Products array
         * @private
         */
        this.setProductDisplay = function (productsArray) {
            this.setEventFromProductsAndCart(Types.product.display, productsArray, null);
        };

        /**
         * Generate 'product.click' events
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param productsArray {Array} Products array
         * @private
         */
        this.setProductClick = function (productsArray) {
            this.setEventFromProductsAndCart(Types.product.click, productsArray, null);
        };

        /**
         * Generate 'product.page_display' events
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param productsArray {Array} Products array
         * @private
         */
        this.setProductPageDisplay = function (productsArray) {
            this.setEventFromProductsAndCart(Types.product.page_display, productsArray, null);
        };

        /**
         * Generate 'product.add_to_cart' events
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param productsArray {Array} Products array
         * @param cart {object} cart object
         * @private
         */
        this.setProductAddToCart = function (productsArray, cart) {
            this.setEventFromProductsAndCart(Types.product.add_to_cart, productsArray, cart);
        };

        /**
         * Generate 'product.remove_from_cart' events
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param productsArray {Array} Products array
         * @param cart {object} cart object
         * @private
         */
        this.setProductRemoveFromCart = function (productsArray, cart) {
            this.setEventFromProductsAndCart(Types.product.remove_from_cart, productsArray, cart);
        };

        /**
         * Generate 'cart.creation' event
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param cart {object} cart
         * @private
         */
        this.setCartCreation = function (cart) {
            var cartCreation = {};
            cartCreation[Keys.cart] = cart;
            parent.event.set(Types.cart.creation, cartCreation, null, 'ecommerce');
        };

        /**
         * Complete 'cart.creation' events
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param cart {object} cart object
         * @private
         */
        this.updateCartCreation = function (cart) {
            var idCart = cart ? cart[Properties.cart.id.event] : '';
            if (idCart) {
                // Complete 'cart.creation' events if necessary
                var cartCreation;
                var contextEcommerceObject = parent.getContext('ecommerce') || [];
                for (var i = 0; i < contextEcommerceObject.length; i++) {
                    cartCreation = contextEcommerceObject[i][Types.cart.creation];
                    if (cartCreation && cartCreation[Keys.cart]) {
                        cartCreation[Keys.cart][Properties.cart.id.event] = idCart;
                        contextEcommerceObject[i][Types.cart.creation] = cartCreation;
                    }
                }
            }
        };

        /**
         * Generate 'product.purchased' events
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param productsArray {Array} Products array
         * @param transaction {object} transaction object
         * @param cart {object} cart object
         * @private
         */
        this.setProductPurchased = function (productsArray, transaction, cart) {
            var products = productsArray || [];
            var idTransaction = transaction ? transaction[Properties.transaction.id.event] : '';
            var idCart = cart ? cart[Properties.cart.id.event] : '';
            var eventObject = {};
            for (var i = 0; i < products.length; i++) {
                eventObject[Keys.transaction] = {};
                eventObject[Keys.transaction][Properties.transaction.id.event] = idTransaction;
                eventObject[Keys.cart] = {};
                eventObject[Keys.cart][Properties.cart.id.event] = idCart;
                eventObject[Keys.product] = products[i];
                if (i === 0) {
                    parent.event.set(Types.product.purchased, eventObject, null, 'ecommerce');
                }
                else {
                    parent.event.add(Types.product.purchased, eventObject, 'ecommerce');
                }
                eventObject = {};
            }
        };

        /**
         * Complete 'product.purchased' events
         * @memberof ATInternet.Tracker.Plugins.Ecommerce#
         * @function
         * @param transaction {object} transaction object
         * @param cart {object} cart object
         * @private
         */
        this.updateProductPurchased = function (transaction, cart) {
            // Complete 'product.purchased' events if necessary
            var idTransaction = transaction ? transaction[Properties.transaction.id.event] : '';
            var idCart = cart ? cart[Properties.cart.id.event] : '';
            var productPurchased;
            var contextEcommerceObject = parent.getContext('ecommerce') || [];
            for (var i = 0; i < contextEcommerceObject.length; i++) {
                productPurchased = contextEcommerceObject[i][Types.product.purchased];
                if (productPurchased) {
                    if (idTransaction && productPurchased[Keys.transaction]) {
                        productPurchased[Keys.transaction][Properties.transaction.id.event] = idTransaction;
                    }
                    else if (idCart && productPurchased[Keys.cart]) {
                        productPurchased[Keys.cart][Properties.cart.id.event] = idCart;
                    }
                    contextEcommerceObject[i][Types.product.purchased] = productPurchased;
                }
            }
        };

    };

    /* ---------------------------------- Ecommerce helpers ------------------------------------------------- */

    /**
     * [Object added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tags to manage ecommerce sending.
     * @name ecommerce
     * @memberof ATInternet.Tracker.Tag
     * @inner
     * @type {object}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.cartAwaitingPayment.cart.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.cartAwaitingPayment.products.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.cartAwaitingPayment.shipping.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.cartAwaitingPayment.payment.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.cartAwaitingPayment.transaction.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.displayProduct.products.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.displayPageProduct.products.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.addProduct.cart.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.addProduct.products.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.removeProduct.cart.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.removeProduct.products.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.displayCart.cart.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.displayCart.products.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.updateCart.cart.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.deliveryCheckout.cart.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.deliveryCheckout.shipping.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.paymentCheckout.cart.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.paymentCheckout.shipping.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.transactionConfirmation.cart.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.transactionConfirmation.discount.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.transactionConfirmation.transaction.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.transactionConfirmation.shipping.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.transactionConfirmation.payment.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.transactionConfirmation.customer.set}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.transactionConfirmation.products.set}
     * @property {function} reset Tag helper, see details here {@link ATInternet.Tracker.Tag#ecommerce.reset}
     * @public
     */
    parent.ecommerce = {
        cartAwaitingPayment: {},
        displayProduct: {},
        displayPageProduct: {},
        addProduct: {},
        removeProduct: {},
        displayCart: {},
        updateCart: {},
        deliveryCheckout: {},
        paymentCheckout: {},
        transactionConfirmation: {}
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Reset ecommerce context.
     * @alias ecommerce.reset
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @example
     * <pre><code class="javascript">tag.ecommerce.reset();
     * </code></pre>
     * @public
     */
    parent.ecommerce.reset = function () {
        parent.event.reset('ecommerce');
    };

    /* ---------------------------------- Type cart.awaiting_payment ------------------------------------------------- */

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for cart object on cart awaiting payment (helper).
     * @alias ecommerce.cartAwaitingPayment.cart.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {Array} Tag object
     * <pre><code class="javascript">tag.ecommerce.cartAwaitingPayment.cart.set({
                    "id": "34",
                    "currency": "EUR",
                    "turnovertaxincluded": 40.8,
                    "turnovertaxfree": 34,
                    "quantity": 1
                });
     * </code></pre>
     * @public
     */
    parent.ecommerce.cartAwaitingPayment.cart = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var cartAwaitingPayment = {};
                cartAwaitingPayment[Keys.cart] = {};

                _utility.setValueFromKey(tagObject, Properties.cart.id.event, Properties.cart.id.tag, cartAwaitingPayment[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.currency.event, Properties.cart.currency.tag, cartAwaitingPayment[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.turnovertaxincluded.event, Properties.cart.turnovertaxincluded.tag, cartAwaitingPayment[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.turnovertaxfree.event, Properties.cart.turnovertaxfree.tag, cartAwaitingPayment[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.creation_utc.event, Properties.cart.creation_utc.tag, cartAwaitingPayment[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.quantity.event, Properties.cart.quantity.tag, cartAwaitingPayment[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.nbdistinctproduct.event, Properties.cart.nbdistinctproduct.tag, cartAwaitingPayment[Keys.cart]);

                // Add a cart version
                var uuid = ATInternet.Utils.uuid();
                cartAwaitingPayment[Keys.cart][Properties.cart.version.event] = uuid.v4().split('-')[0];

                _salesInsights.updateProductAwaitingPayment(cartAwaitingPayment[Keys.cart]);

                // Ecommerce
                parent.event.set(Types.cart.awaiting_payment, cartAwaitingPayment[Keys.cart], Keys.cart, 'ecommerce');

                // SalesTracker
                if (_config.autoSalesTracker) {
                    _salesTracker.processTransactionId(tagObject);
                    _salesTracker.processCartId(tagObject, false);
                    _salesTracker.processCartAmounts(tagObject);
                }
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.cart.awaiting_payment,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for products object on cart awaiting payment (helper).
     * @alias ecommerce.cartAwaitingPayment.products.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {Array} Tag object
     * <pre><code class="javascript">tag.ecommerce.cartAwaitingPayment.products.set([{
                    "id": "2",
                    "variant": "2",
                    "$": "Chemisier",
                    "brand": "Fashion Manufacturer",
                    "discount": 0,
                    "pricetaxincluded": 32.4,
                    "pricetaxfree": 27,
                    "currency": "EUR",
                    "stock": 1,
                    "quantity": 1,
                    "category1": "Accueil",
                    "category2": "Femmes",
                    "category3": "Tops",
                    "category4": "Chemisiers"
                }]);
     * </code></pre>
     * @public
     */
    parent.ecommerce.cartAwaitingPayment.products = {
        set: function (tagObject) {
            if (tagObject instanceof Array) {

                tagObject = _utility.arrayObjectKeysToLowercase(tagObject);

                var product;
                var products = [];
                var fullCart = _salesInsights.getObjectValueFromType(Types.cart.awaiting_payment, Keys.cart);

                for (var i = 0; i < tagObject.length; i++) {
                    product = {};
                    _utility.setValueFromKey(tagObject[i], Properties.product.id.event, Properties.product.id.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.variant.event, Properties.product.variant.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.$.event, Properties.product.$.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.brand.event, Properties.product.brand.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.discount.event, Properties.product.discount.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.pricetaxincluded.event, Properties.product.pricetaxincluded.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.pricetaxfree.event, Properties.product.pricetaxfree.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.currency.event, Properties.product.currency.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.stock.event, Properties.product.stock.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.quantity.event, Properties.product.quantity.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category1.event, Properties.product.category1.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category2.event, Properties.product.category2.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category3.event, Properties.product.category3.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category4.event, Properties.product.category4.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category5.event, Properties.product.category5.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category6.event, Properties.product.category6.tag, product);
                    products.push(product);
                }
                var productCart = {};
                if (fullCart[Properties.cart.id.event]) {
                    productCart[Properties.cart.id.event] = fullCart[Properties.cart.id.event];
                }
                if (fullCart[Properties.cart.version.event]) {
                    productCart[Properties.cart.version.event] = fullCart[Properties.cart.version.event];
                }
                _salesInsights.setProductAwaitingPayment(products, productCart);

                // SalesTracker
                if (_config.autoSalesTracker) {
                    _salesTracker.processCartProducts(tagObject);
                }
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageArray, {
                    name: Types.product.cartAwaitingPayment,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for shipping object on cart awaiting payment (helper).
     * @alias ecommerce.cartAwaitingPayment.shipping.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.cartAwaitingPayment.shipping.set({
                    "delivery": "My carrier",
                    "costtaxincluded": 8.4,
                    "costtaxfree": 7
                });
     * </code></pre>
     * @public
     */
    parent.ecommerce.cartAwaitingPayment.shipping = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var cartAwaitingPayment = {};
                cartAwaitingPayment[Keys.shipping] = {};

                _utility.setValueFromKey(tagObject, Properties.shipping.delivery.event, Properties.shipping.delivery.tag, cartAwaitingPayment[Keys.shipping]);
                _utility.setValueFromKey(tagObject, Properties.shipping.costtaxincluded.event, Properties.shipping.costtaxincluded.tag, cartAwaitingPayment[Keys.shipping]);
                _utility.setValueFromKey(tagObject, Properties.shipping.costtaxfree.event, Properties.shipping.costtaxfree.tag, cartAwaitingPayment[Keys.shipping]);

                // Ecommerce
                parent.event.set(Types.cart.awaiting_payment, cartAwaitingPayment[Keys.shipping], Keys.shipping, 'ecommerce');

                // SalesTracker
                if (_config.autoSalesTracker) {
                    _salesTracker.processShipping(tagObject);
                }
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.cart.awaiting_payment,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for payment object on cart awaiting payment (helper).
     * @alias ecommerce.cartAwaitingPayment.payment.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.cartAwaitingPayment.payment.set({"mode": "Chèque"});
     * </code></pre>
     * @public
     */
    parent.ecommerce.cartAwaitingPayment.payment = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var cartAwaitingPayment = {};
                cartAwaitingPayment[Keys.payment] = {};

                _utility.setValueFromKey(tagObject, Properties.payment.mode.event, Properties.payment.mode.tag, cartAwaitingPayment[Keys.payment]);

                // Ecommerce
                parent.event.set(Types.cart.awaiting_payment, cartAwaitingPayment[Keys.payment], Keys.payment, 'ecommerce');
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.cart.awaiting_payment,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for transaction on cart awaiting payment (helper).
     * @alias ecommerce.cartAwaitingPayment.transaction.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.cartAwaitingPayment.transaction.set({"promocode": ["BIU4YTCR", "1WUY4TWX"], "firstpurchase": 0});
     * </code></pre>
     * @public
     */
    parent.ecommerce.cartAwaitingPayment.transaction = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var cartAwaitingPayment = {};
                cartAwaitingPayment[Keys.transaction] = {};

                _utility.setValueFromKey(tagObject, Properties.transaction.promocode.event, Properties.transaction.promocode.tag, cartAwaitingPayment[Keys.transaction]);
                _utility.setValueFromKey(tagObject, Properties.transaction.firstpurchase.event, Properties.transaction.firstpurchase.tag, cartAwaitingPayment[Keys.transaction]);

                // Ecommerce
                parent.event.set(Types.cart.awaiting_payment, cartAwaitingPayment[Keys.transaction], Keys.transaction, 'ecommerce');

                // SalesTracker
                if (_config.autoSalesTracker) {
                    if (tagObject.promocode instanceof Array) {
                        _salesTracker.processPromotionalCode(tagObject.promocode);
                    }
                    _salesTracker.processCustomer(tagObject);
                }
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.transaction.confirmation,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /* ---------------------------------- Type product.display ------------------------------------------------- */

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for product display (helper).
     * @alias ecommerce.displayProduct.products.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {Array} Tag object
     * @example
     * <pre><code class="javascript">tag.ecommerce.displayProduct.products.set([{
                    "id": "7",
                    "variant": "1",
                    "$": "Robe en mousseline imprimée",
                    "brand": "Fashion Manufacturer",
                    "discount": 1,
                    "pricetaxincluded": 19.68,
                    "pricetaxfree": 16.4,
                    "currency": "EUR",
                    "stock": 1,
                    "category1": "Accueil",
                    "category2": "Femmes",
                    "category3": "Robes",
                    "category4": "Robes d'été"
                }]);
     * </code></pre>
     * @public
     */
    parent.ecommerce.displayProduct.products = {
        set: function (tagObject) {
            if (tagObject instanceof Array) {

                tagObject = _utility.arrayObjectKeysToLowercase(tagObject);

                var product;
                var products = [];

                for (var i = 0; i < tagObject.length; i++) {
                    product = {};
                    _utility.setValueFromKey(tagObject[i], Properties.product.id.event, Properties.product.id.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.variant.event, Properties.product.variant.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.$.event, Properties.product.$.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.brand.event, Properties.product.brand.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.discount.event, Properties.product.discount.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.pricetaxincluded.event, Properties.product.pricetaxincluded.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.pricetaxfree.event, Properties.product.pricetaxfree.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.currency.event, Properties.product.currency.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.stock.event, Properties.product.stock.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category1.event, Properties.product.category1.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category2.event, Properties.product.category2.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category3.event, Properties.product.category3.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category4.event, Properties.product.category4.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category5.event, Properties.product.category5.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category6.event, Properties.product.category6.tag, product);
                    products.push(product);
                }
                _salesInsights.setProductDisplay(products);
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageArray, {
                    name: Types.product.display,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /* ---------------------------------- Type product.page_display ------------------------------------------------- */

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for product page display (helper).
     * @alias ecommerce.displayPageProduct.products.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {Array} Tag object
     * <pre><code class="javascript">tag.ecommerce.displayPageProduct.products.set([{
                    "id": "3",
                    "variant": "1",
                    "$": "Robe imprimée",
                    "brand": "Fashion Manufacturer",
                    "discount": 0,
                    "pricetaxincluded": 31.2,
                    "pricetaxfree": 26,
                    "currency": "EUR",
                    "stock": 1,
                    "category1": "Accueil",
                    "category2": "Femmes",
                    "category3": "Robes",
                    "category4": "Robes décontractées"
                }]);
     * </code></pre>
     * @public
     */
    parent.ecommerce.displayPageProduct.products = {
        set: function (tagObject) {
            if (tagObject instanceof Array) {

                tagObject = _utility.arrayObjectKeysToLowercase(tagObject);

                var product;
                var products = [];

                for (var i = 0; i < tagObject.length; i++) {
                    product = {};
                    _utility.setValueFromKey(tagObject[i], Properties.product.id.event, Properties.product.id.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.variant.event, Properties.product.variant.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.$.event, Properties.product.$.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.brand.event, Properties.product.brand.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.discount.event, Properties.product.discount.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.pricetaxincluded.event, Properties.product.pricetaxincluded.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.pricetaxfree.event, Properties.product.pricetaxfree.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.currency.event, Properties.product.currency.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.stock.event, Properties.product.stock.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category1.event, Properties.product.category1.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category2.event, Properties.product.category2.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category3.event, Properties.product.category3.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category4.event, Properties.product.category4.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category5.event, Properties.product.category5.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category6.event, Properties.product.category6.tag, product);
                    products.push(product);
                }
                _salesInsights.setProductPageDisplay(products);
                // SalesTracker
                if (_config.autoSalesTracker) {
                    _salesTracker.processViewedProducts(tagObject);
                }
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageArray, {
                    name: Types.product.page_display,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /* ---------------------------------- Type product.add_to_cart ------------------------------------------------- */

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for product add (helper).
     * @alias ecommerce.addProduct.cart.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.addProduct.cart.set({"id": "34"});
     * </code></pre>
     * @public
     */
    parent.ecommerce.addProduct.cart = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var addProduct = {};
                addProduct[Keys.cart] = {};

                _utility.setValueFromKey(tagObject, Properties.cart.id.event, Properties.cart.id.tag, addProduct[Keys.cart]);

                parent.event.set(Types.product.add_to_cart, addProduct[Keys.cart], Keys.cart, 'ecommerce');

                _salesInsights.updateCartCreation(addProduct[Keys.cart]);
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.product.add_to_cart,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for product add (helper).
     * @alias ecommerce.addProduct.products.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {Array} Tag object
     * <pre><code class="javascript">tag.ecommerce.addProduct.products.set([{
                    "id": "3",
                    "variant": "1",
                    "$": "Robe imprimée",
                    "brand": "Fashion Manufacturer",
                    "discount": 0,
                    "pricetaxincluded": 31.2,
                    "pricetaxfree": 26,
                    "currency": "EUR",
                    "stock": 1,
                    "category1": "Accueil",
                    "category2": "Femmes",
                    "category3": "Robes",
                    "category4": "Robes décontractées",
                    "quantity": 1,
                    "cartcreation": 1
                }]);
     * </code></pre>
     * @public
     */
    parent.ecommerce.addProduct.products = {
        set: function (tagObject) {
            if (tagObject instanceof Array) {

                tagObject = _utility.arrayObjectKeysToLowercase(tagObject);

                var product;
                var products = [];
                var isCartCreation = false;
                var idCart = _salesInsights.getObjectValueFromType(Types.product.add_to_cart, Keys.cart)[Properties.cart.id.event];
                var fullCart = _salesInsights.initCartWithId(idCart);

                for (var i = 0; i < tagObject.length; i++) {
                    product = {};
                    _utility.setValueFromKey(tagObject[i], Properties.product.id.event, Properties.product.id.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.variant.event, Properties.product.variant.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.$.event, Properties.product.$.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.brand.event, Properties.product.brand.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.discount.event, Properties.product.discount.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.pricetaxincluded.event, Properties.product.pricetaxincluded.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.pricetaxfree.event, Properties.product.pricetaxfree.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.currency.event, Properties.product.currency.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.stock.event, Properties.product.stock.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.quantity.event, Properties.product.quantity.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category1.event, Properties.product.category1.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category2.event, Properties.product.category2.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category3.event, Properties.product.category3.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category4.event, Properties.product.category4.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category5.event, Properties.product.category5.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category6.event, Properties.product.category6.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.cartcreation.event, Properties.product.cartcreation.tag, product);

                    fullCart[Properties.cart.currency.event] = product[Properties.product.currency.event];
                    fullCart[Properties.cart.turnovertaxincluded.event] += (Number(product[Properties.product.pricetaxincluded.event]) || 0) * (Number(product[Properties.product.quantity.event]) || 0);
                    fullCart[Properties.cart.turnovertaxfree.event] += (Number(product[Properties.product.pricetaxfree.event]) || 0) * (Number(product[Properties.product.quantity.event]) || 0);
                    fullCart[Properties.cart.quantity.event] += Number(product[Properties.product.quantity.event]) || 0;
                    fullCart[Properties.cart.nbdistinctproduct.event] += 1;

                    if (Boolean(Number(product[Properties.product.cartcreation.event]))) {
                        isCartCreation = true;
                    }

                    products.push(product);
                }
                var productCart = {};
                if (fullCart[Properties.cart.id.event]) {
                    productCart[Properties.cart.id.event] = fullCart[Properties.cart.id.event];
                }
                _salesInsights.setProductAddToCart(products, productCart);
                isCartCreation && _salesInsights.setCartCreation(fullCart);
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageArray, {
                    name: Types.product.add_to_cart,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /* ---------------------------------- Type product.remove_from_cart ------------------------------------------------- */

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for product remove (helper).
     * @alias ecommerce.removeProduct.cart.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.removeProduct.cart.set({"id": "34"});
     * </code></pre>
     * @public
     */
    parent.ecommerce.removeProduct.cart = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var removeProduct = {};
                removeProduct[Keys.cart] = {};

                _utility.setValueFromKey(tagObject, Properties.cart.id.event, Properties.cart.id.tag, removeProduct[Keys.cart]);
                parent.event.set(Types.product.remove_from_cart, removeProduct[Keys.cart], Keys.cart, 'ecommerce');
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.product.remove_from_cart,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for product remove (helper).
     * @alias ecommerce.removeProduct.products.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {Array} Tag object
     * <pre><code class="javascript">tag.ecommerce.removeProduct.products.set([{
                    "id": "4",
                    "variant": "1",
                    "$": "Robe imprimée",
                    "brand": "Fashion Manufacturer",
                    "discount": 0,
                    "pricetaxincluded": 61.19,
                    "pricetaxfree": 50.99,
                    "currency": "EUR",
                    "stock": 1,
                    "category1": "Accueil",
                    "category2": "Femmes",
                    "category3": "Robes",
                    "category4": "Robes de soirée",
                    "quantity": 1
                }]);
     * </code></pre>
     * @public
     */
    parent.ecommerce.removeProduct.products = {
        set: function (tagObject) {
            if (tagObject instanceof Array) {

                tagObject = _utility.arrayObjectKeysToLowercase(tagObject);

                var product;
                var products = [];
                var fullCart = {};
                fullCart[Properties.cart.id.event] = _salesInsights.getObjectValueFromType(Types.product.remove_from_cart, Keys.cart)[Properties.cart.id.event];

                for (var i = 0; i < tagObject.length; i++) {
                    product = {};
                    _utility.setValueFromKey(tagObject[i], Properties.product.id.event, Properties.product.id.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.variant.event, Properties.product.variant.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.$.event, Properties.product.$.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.brand.event, Properties.product.brand.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.discount.event, Properties.product.discount.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.pricetaxincluded.event, Properties.product.pricetaxincluded.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.pricetaxfree.event, Properties.product.pricetaxfree.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.currency.event, Properties.product.currency.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.stock.event, Properties.product.stock.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.quantity.event, Properties.product.quantity.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category1.event, Properties.product.category1.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category2.event, Properties.product.category2.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category3.event, Properties.product.category3.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category4.event, Properties.product.category4.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category5.event, Properties.product.category5.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category6.event, Properties.product.category6.tag, product);
                    products.push(product);
                }
                var productCart = {};
                if (fullCart[Properties.cart.id.event]) {
                    productCart[Properties.cart.id.event] = fullCart[Properties.cart.id.event];
                }
                _salesInsights.setProductRemoveFromCart(products, productCart);
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageArray, {
                    name: Types.product.remove_from_cart,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /* ---------------------------------- Type cart.display ------------------------------------------------- */

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for cart display (helper).
     * @alias ecommerce.displayCart.cart.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.displayCart.cart.set({
                    "id": "53",
                    "currency": "EUR",
                    "turnovertaxincluded": 10.81,
                    "turnovertaxfree": 9.01,
                    "quantity": 1
                });
     * </code></pre>
     * @public
     */
    parent.ecommerce.displayCart.cart = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var displayCart = {};
                displayCart[Keys.cart] = {};

                _utility.setValueFromKey(tagObject, Properties.cart.id.event, Properties.cart.id.tag, displayCart[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.currency.event, Properties.cart.currency.tag, displayCart[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.turnovertaxincluded.event, Properties.cart.turnovertaxincluded.tag, displayCart[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.turnovertaxfree.event, Properties.cart.turnovertaxfree.tag, displayCart[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.quantity.event, Properties.cart.quantity.tag, displayCart[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.nbdistinctproduct.event, Properties.cart.nbdistinctproduct.tag, displayCart[Keys.cart]);
                parent.event.set(Types.cart.display, displayCart[Keys.cart], Keys.cart, 'ecommerce');
                if (_config.autoSalesTracker) {
                    _salesTracker.processCartId(tagObject, true);
                }
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.cart.display,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for cart display (helper).
     * @alias ecommerce.displayCart.products.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {Array} Tag object
     * <pre><code class="javascript">tag.ecommerce.displayCart.products.set([{
                    "id": "1",
                    "$": "T-shirt délavé à manches courtes",
                    "pricetaxincluded": 10.81,
                    "pricetaxfree": 9.01,
                    "quantity": 1,
                    "category1": "Femmes",
                    "category2": "Tops",
                    "category3": "T-shirts",
                    "category4": "Manches Courtes",
                    "category5": "Cols Ronds",
                    "category6": "Coton"
                }]);
     * </code></pre>
     * @public
     */
    parent.ecommerce.displayCart.products = {
        set: function (tagObject) {
            // SalesTracker
            if (_config.autoSalesTracker) {
                if (tagObject instanceof Array) {

                    tagObject = _utility.arrayObjectKeysToLowercase(tagObject);

                    _salesTracker.processCartProducts(tagObject);
                }
                else if (tagObject) {
                    /* @if debug */
                    parent.debug(_error.trigger, _error.level, _error.messageArray, {
                        name: Types.cart.display,
                        data: tagObject,
                        origin: 'ecommerce'
                    });
                    /* @endif */
                }
            }
        }
    };

    /* ---------------------------------- Type cart.update ------------------------------------------------- */

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for cart update (helper).
     * @alias ecommerce.updateCart.cart.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.updateCart.cart.set({
                    "id": "34",
                    "currency": "EUR",
                    "turnovertaxincluded": 62.4,
                    "turnovertaxfree": 52,
                    "quantity": 2
                });
     * </code></pre>
     * @public
     */
    parent.ecommerce.updateCart.cart = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var updateCart = {};
                updateCart[Keys.cart] = {};

                _utility.setValueFromKey(tagObject, Properties.cart.id.event, Properties.cart.id.tag, updateCart[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.currency.event, Properties.cart.currency.tag, updateCart[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.turnovertaxincluded.event, Properties.cart.turnovertaxincluded.tag, updateCart[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.turnovertaxfree.event, Properties.cart.turnovertaxfree.tag, updateCart[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.quantity.event, Properties.cart.quantity.tag, updateCart[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.nbdistinctproduct.event, Properties.cart.nbdistinctproduct.tag, updateCart[Keys.cart]);
                parent.event.set(Types.cart.update, updateCart[Keys.cart], Keys.cart, 'ecommerce');
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.cart.update,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /* ---------------------------------- Type cart.delivery ------------------------------------------------- */

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for delivery checkout (helper).
     * @alias ecommerce.deliveryCheckout.cart.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.deliveryCheckout.cart.set({
                    "id": "34",
                    "currency": "EUR",
                    "turnovertaxincluded": 40.8,
                    "turnovertaxfree": 34,
                    "quantity": 1
                });
     * </code></pre>
     * @public
     */
    parent.ecommerce.deliveryCheckout.cart = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var deliveryCheckout = {};
                deliveryCheckout[Keys.cart] = {};

                _utility.setValueFromKey(tagObject, Properties.cart.id.event, Properties.cart.id.tag, deliveryCheckout[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.currency.event, Properties.cart.currency.tag, deliveryCheckout[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.turnovertaxincluded.event, Properties.cart.turnovertaxincluded.tag, deliveryCheckout[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.turnovertaxfree.event, Properties.cart.turnovertaxfree.tag, deliveryCheckout[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.quantity.event, Properties.cart.quantity.tag, deliveryCheckout[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.nbdistinctproduct.event, Properties.cart.nbdistinctproduct.tag, deliveryCheckout[Keys.cart]);
                parent.event.set(Types.cart.delivery, deliveryCheckout[Keys.cart], Keys.cart, 'ecommerce');
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.cart.delivery,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for delivery checkout (helper).
     * @alias ecommerce.deliveryCheckout.shipping.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.deliveryCheckout.shipping.set({
                    "delivery": "My carrier",
                    "costtaxincluded": 8.4,
                    "costtaxfree": 7
                });
     * </code></pre>
     * @public
     */
    parent.ecommerce.deliveryCheckout.shipping = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var deliveryCheckout = {};
                deliveryCheckout[Keys.shipping] = {};

                _utility.setValueFromKey(tagObject, Properties.shipping.delivery.event, Properties.shipping.delivery.tag, deliveryCheckout[Keys.shipping]);
                _utility.setValueFromKey(tagObject, Properties.shipping.costtaxincluded.event, Properties.shipping.costtaxincluded.tag, deliveryCheckout[Keys.shipping]);
                _utility.setValueFromKey(tagObject, Properties.shipping.costtaxfree.event, Properties.shipping.costtaxfree.tag, deliveryCheckout[Keys.shipping]);
                parent.event.set(Types.cart.delivery, deliveryCheckout[Keys.shipping], Keys.shipping, 'ecommerce');
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.cart.delivery,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /* ---------------------------------- Type cart.payment ------------------------------------------------- */

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for payment checkout (helper).
     * @alias ecommerce.paymentCheckout.cart.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.paymentCheckout.cart.set({
                    "id": "34",
                    "currency": "EUR",
                    "turnovertaxincluded": 40.8,
                    "turnovertaxfree": 34,
                    "quantity": 1
                });
     * </code></pre>
     * @public
     */
    parent.ecommerce.paymentCheckout.cart = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var paymentCheckout = {};
                paymentCheckout[Keys.cart] = {};

                _utility.setValueFromKey(tagObject, Properties.cart.id.event, Properties.cart.id.tag, paymentCheckout[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.currency.event, Properties.cart.currency.tag, paymentCheckout[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.turnovertaxincluded.event, Properties.cart.turnovertaxincluded.tag, paymentCheckout[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.turnovertaxfree.event, Properties.cart.turnovertaxfree.tag, paymentCheckout[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.quantity.event, Properties.cart.quantity.tag, paymentCheckout[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.nbdistinctproduct.event, Properties.cart.nbdistinctproduct.tag, paymentCheckout[Keys.cart]);
                parent.event.set(Types.cart.payment, paymentCheckout[Keys.cart], Keys.cart, 'ecommerce');
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.cart.payment,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for payment checkout (helper).
     * @alias ecommerce.paymentCheckout.shipping.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.paymentCheckout.shipping.set({
                    "delivery": "My carrier",
                    "costtaxincluded": 8.4,
                    "costtaxfree": 7
                });
     * </code></pre>
     * @public
     */
    parent.ecommerce.paymentCheckout.shipping = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var paymentCheckout = {};
                paymentCheckout[Keys.shipping] = {};

                _utility.setValueFromKey(tagObject, Properties.shipping.delivery.event, Properties.shipping.delivery.tag, paymentCheckout[Keys.shipping]);
                _utility.setValueFromKey(tagObject, Properties.shipping.costtaxincluded.event, Properties.shipping.costtaxincluded.tag, paymentCheckout[Keys.shipping]);
                _utility.setValueFromKey(tagObject, Properties.shipping.costtaxfree.event, Properties.shipping.costtaxfree.tag, paymentCheckout[Keys.shipping]);
                parent.event.set(Types.cart.payment, paymentCheckout[Keys.shipping], Keys.shipping, 'ecommerce');
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.cart.payment,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /* ---------------------------------- Type transaction.confirmation ------------------------------------------------- */

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for transaction confirmation (helper).
     * @alias ecommerce.transactionConfirmation.cart.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.transactionConfirmation.cart.set({
                    "id": "34",
                    "currency": "EUR",
                    "turnovertaxincluded": 40.8,
                    "turnovertaxfree": 34,
                    "quantity": 1,
                    "nbdistinctproduct": 1,
                    "creation_utc": 1514973161
                });
     * </code></pre>
     * @public
     */
    parent.ecommerce.transactionConfirmation.cart = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var transactionConfirmation = {};
                transactionConfirmation[Keys.cart] = {};

                _utility.setValueFromKey(tagObject, Properties.cart.id.event, Properties.cart.id.tag, transactionConfirmation[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.currency.event, Properties.cart.currency.tag, transactionConfirmation[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.turnovertaxincluded.event, Properties.cart.turnovertaxincluded.tag, transactionConfirmation[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.turnovertaxfree.event, Properties.cart.turnovertaxfree.tag, transactionConfirmation[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.creation_utc.event, Properties.cart.creation_utc.tag, transactionConfirmation[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.quantity.event, Properties.cart.quantity.tag, transactionConfirmation[Keys.cart]);
                _utility.setValueFromKey(tagObject, Properties.cart.nbdistinctproduct.event, Properties.cart.nbdistinctproduct.tag, transactionConfirmation[Keys.cart]);

                // Ecommerce
                parent.event.set(Types.transaction.confirmation, transactionConfirmation[Keys.cart], Keys.cart, 'ecommerce');
                _salesInsights.updateProductPurchased(null, transactionConfirmation[Keys.cart]);

                // SalesTracker
                if (_config.autoSalesTracker) {
                    _salesTracker.processCartId(tagObject, false);
                    _salesTracker.processCartAmounts(tagObject);
                }
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.transaction.confirmation,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for transaction confirmation (helper).
     * @alias ecommerce.transactionConfirmation.discount.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {Array} Tag object
     * <pre><code class="javascript">tag.ecommerce.transactionConfirmation.discount.set(["DQQYRZSJ", "UN1ENE27"]);
     * </code></pre>
     * @public
     * @deprecated
     */
    parent.ecommerce.transactionConfirmation.discount = {
        set: function (tagObject) {
            if (tagObject instanceof Array) {

                var transactionConfirmation = {};
                transactionConfirmation[Keys.transaction] = {};
                transactionConfirmation[Keys.transaction][Properties.transaction.promocode.event] = tagObject;

                // Ecommerce
                parent.event.set(Types.transaction.confirmation, transactionConfirmation[Keys.transaction], Keys.transaction, 'ecommerce');

                // SalesTracker
                if (_config.autoSalesTracker) {
                    _salesTracker.processPromotionalCode(tagObject);
                }
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageArray, {
                    name: Types.transaction.confirmation,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for transaction confirmation (helper).
     * @alias ecommerce.transactionConfirmation.transaction.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.transactionConfirmation.transaction.set({"id": "27", "promocode": ["BIU4YTCR", "1WUY4TWX"], "firstpurchase": 0});
     * </code></pre>
     * @public
     */
    parent.ecommerce.transactionConfirmation.transaction = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var transactionConfirmation = {};
                transactionConfirmation[Keys.transaction] = {};

                _utility.setValueFromKey(tagObject, Properties.transaction.id.event, Properties.transaction.id.tag, transactionConfirmation[Keys.transaction]);
                _utility.setValueFromKey(tagObject, Properties.transaction.promocode.event, Properties.transaction.promocode.tag, transactionConfirmation[Keys.transaction]);
                _utility.setValueFromKey(tagObject, Properties.transaction.firstpurchase.event, Properties.transaction.firstpurchase.tag, transactionConfirmation[Keys.transaction]);

                // Ecommerce
                parent.event.set(Types.transaction.confirmation, transactionConfirmation[Keys.transaction], Keys.transaction, 'ecommerce');

                _salesInsights.updateProductPurchased(transactionConfirmation[Keys.transaction], null);

                // SalesTracker
                if (_config.autoSalesTracker) {
                    _salesTracker.processTransactionId(tagObject);
                    if (tagObject.promocode instanceof Array) {
                        _salesTracker.processPromotionalCode(tagObject.promocode);
                    }
                    _salesTracker.processCustomer(tagObject);
                }
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.transaction.confirmation,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for transaction confirmation (helper).
     * @alias ecommerce.transactionConfirmation.shipping.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.transactionConfirmation.shipping.set({
                    "delivery": "My carrier",
                    "costtaxincluded": 8.4,
                    "costtaxfree": 7
                });
     * </code></pre>
     * @public
     */
    parent.ecommerce.transactionConfirmation.shipping = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var transactionConfirmation = {};
                transactionConfirmation[Keys.shipping] = {};

                _utility.setValueFromKey(tagObject, Properties.shipping.delivery.event, Properties.shipping.delivery.tag, transactionConfirmation[Keys.shipping]);
                _utility.setValueFromKey(tagObject, Properties.shipping.costtaxincluded.event, Properties.shipping.costtaxincluded.tag, transactionConfirmation[Keys.shipping]);
                _utility.setValueFromKey(tagObject, Properties.shipping.costtaxfree.event, Properties.shipping.costtaxfree.tag, transactionConfirmation[Keys.shipping]);

                // Ecommerce
                parent.event.set(Types.transaction.confirmation, transactionConfirmation[Keys.shipping], Keys.shipping, 'ecommerce');

                // SalesTracker
                if (_config.autoSalesTracker) {
                    _salesTracker.processShipping(tagObject);
                }
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.transaction.confirmation,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for transaction confirmation (helper).
     * @alias ecommerce.transactionConfirmation.payment.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.transactionConfirmation.payment.set({"mode": "Chèque"});
     * </code></pre>
     * @public
     */
    parent.ecommerce.transactionConfirmation.payment = {
        set: function (tagObject) {
            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var transactionConfirmation = {};
                transactionConfirmation[Keys.payment] = {};

                _utility.setValueFromKey(tagObject, Properties.payment.mode.event, Properties.payment.mode.tag, transactionConfirmation[Keys.payment]);
                parent.event.set(Types.transaction.confirmation, transactionConfirmation[Keys.payment], Keys.payment, 'ecommerce');
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.transaction.confirmation,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for transaction confirmation (helper).
     * @alias ecommerce.transactionConfirmation.customer.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} Tag object
     * <pre><code class="javascript">tag.ecommerce.transactionConfirmation.customer.set({
                    "new": 0
                });
     * </code></pre>
     * @public
     * @deprecated
     */
    parent.ecommerce.transactionConfirmation.customer = {
        set: function (tagObject) {

            if (_utility.isObject(tagObject)) {

                tagObject = _utility.objectKeysToLowercase(tagObject);

                var transactionConfirmation = {};
                transactionConfirmation[Keys.transaction] = {};

                _utility.setValueFromKey(tagObject, Properties.transaction.firstpurchase.event, Properties.customer['new'].tag, transactionConfirmation[Keys.transaction]);

                // Ecommerce
                parent.event.set(Types.transaction.confirmation, transactionConfirmation[Keys.transaction], Keys.transaction, 'ecommerce');

                // SalesTracker
                if (_config.autoSalesTracker) {
                    _salesTracker.processCustomer(tagObject);
                }
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageObject, {
                    name: Types.transaction.confirmation,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Tagging method for transaction confirmation (helper).
     * @alias ecommerce.transactionConfirmation.products.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {Array} Tag object
     * <pre><code class="javascript">tag.ecommerce.transactionConfirmation.products.set([{
                    "id": "2",
                    "variant": "2",
                    "$": "Chemisier",
                    "brand": "Fashion Manufacturer",
                    "discount": 0,
                    "pricetaxincluded": 32.4,
                    "pricetaxfree": 27,
                    "currency": "EUR",
                    "stock": 1,
                    "quantity": 1,
                    "category1": "Accueil",
                    "category2": "Femmes",
                    "category3": "Tops",
                    "category4": "Chemisiers"
                }]);
     * </code></pre>
     * @public
     */
    parent.ecommerce.transactionConfirmation.products = {
        set: function (tagObject) {
            if (tagObject instanceof Array) {

                tagObject = _utility.arrayObjectKeysToLowercase(tagObject);

                var product;
                var products = [];
                var cart = _salesInsights.getObjectValueFromType(Types.transaction.confirmation, Keys.cart);
                var transaction = _salesInsights.getObjectValueFromType(Types.transaction.confirmation, Keys.transaction);

                for (var i = 0; i < tagObject.length; i++) {
                    product = {};
                    _utility.setValueFromKey(tagObject[i], Properties.product.id.event, Properties.product.id.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.variant.event, Properties.product.variant.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.$.event, Properties.product.$.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.brand.event, Properties.product.brand.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.discount.event, Properties.product.discount.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.pricetaxincluded.event, Properties.product.pricetaxincluded.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.pricetaxfree.event, Properties.product.pricetaxfree.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.currency.event, Properties.product.currency.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.stock.event, Properties.product.stock.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.quantity.event, Properties.product.quantity.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category1.event, Properties.product.category1.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category2.event, Properties.product.category2.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category3.event, Properties.product.category3.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category4.event, Properties.product.category4.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category5.event, Properties.product.category5.tag, product);
                    _utility.setValueFromKey(tagObject[i], Properties.product.category6.event, Properties.product.category6.tag, product);
                    products.push(product);
                }
                // Create 'product.purchased' events
                _salesInsights.setProductPurchased(products, transaction, cart);

                // SalesTracker
                if (_config.autoSalesTracker) {
                    _salesTracker.processCartProducts(tagObject);
                }
            }
            else if (tagObject) {
                /* @if debug */
                parent.debug(_error.trigger, _error.level, _error.messageArray, {
                    name: Types.transaction.confirmation,
                    data: tagObject,
                    origin: 'ecommerce'
                });
                /* @endif */
            }
        }
    };

    /**
     * Launch plugin when all dependencies are loaded.
     * @memberof ATInternet.Tracker.Plugins.Ecommerce#
     * @function
     * @private
     */
    var _init = function () {
        // Plugin configuration.
        parent.configPlugin('Ecommerce', dfltPluginCfg || {}, function (newConf) {
            _config = newConf;
        });
        _utility = new Utility();
        _salesTracker = new SalesTracker();
        _salesInsights = new SalesInsights();
    };

    _init();

    /* ---------------------------------- onDispatch ------------------------------------------------- */

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Ecommerce Ecommerce}] Will be called by tracker.dispatch if any event has been set.
     * @alias ecommerce.onDispatch
     * @memberof! ATInternet.Tracker.Tag#
     * @param callback {function} Callback to execute
     * @function
     * @private
     */
    parent.ecommerce.onDispatch = function (callback) {
        parent.event.onDispatch(callback, 'ecommerce');
    };

// For unit tests on private elements !!!
    /* @if test */
    var _this = this;
    _this.Types = Types;
    _this.Keys = Keys;
    _this.Properties = Properties;
    _this.debugError = _error;
    _this.isObject = _utility.isObject;
    _this.arrayObjectKeysToLowercase = _utility.arrayObjectKeysToLowercase;
    _this.objectKeysToLowercase = _utility.objectKeysToLowercase;
    _this.setValueFromKey = _utility.setValueFromKey;
    _this.processCartId = _salesTracker.processCartId;
    _this.processCartAmounts = _salesTracker.processCartAmounts;
    _this.processPromotionalCode = _salesTracker.processPromotionalCode;
    _this.processTransactionId = _salesTracker.processTransactionId;
    _this.processShipping = _salesTracker.processShipping;
    _this.processCustomer = _salesTracker.processCustomer;
    _this.processProductCategories = _salesTracker.processProductCategories;
    _this.processCartProducts = _salesTracker.processCartProducts;
    _this.processViewedProducts = _salesTracker.processViewedProducts;
    _this.getObjectValueFromType = _salesInsights.getObjectValueFromType;
    _this.setProductAwaitingPayment = _salesInsights.setProductAwaitingPayment;
    _this.updateProductAwaitingPayment = _salesInsights.updateProductAwaitingPayment;
    _this.setEventFromProductsAndCart = _salesInsights.setEventFromProductsAndCart;
    _this.setProductDisplay = _salesInsights.setProductDisplay;
    _this.setProductClick = _salesInsights.setProductClick;
    _this.setProductPageDisplay = _salesInsights.setProductPageDisplay;
    _this.setProductAddToCart = _salesInsights.setProductAddToCart;
    _this.setProductRemoveFromCart = _salesInsights.setProductRemoveFromCart;
    _this.setCartCreation = _salesInsights.setCartCreation;
    _this.updateCartCreation = _salesInsights.updateCartCreation;
    _this.setProductPurchased = _salesInsights.setProductPurchased;
    _this.updateProductPurchased = _salesInsights.updateProductPurchased;
    _this._init = _init;
    /* @endif */

};
window['ATInternet']['Tracker']['addPlugin']('Ecommerce');