Enable add-to-cart signals in the Connect web library

You can enable the Connect library to record add-to-cart activity on your website. This activity represents the selection of a product, service or similar offering for purchase or application.

This signal is quite advanced in terms of implementation. There is no one-size-fits-all approach because on one website the Add to Cart button is displayed only on product pages while on another it's on multiple pages.

The "Buy" button in a product list at Beefcakeswimwear.com

The "Quick add" button in a product list at Beefcakeswimwear.com

There can be variations of the button like in the examples below.

Variations of the "Buy" button at Potgang.co.uk

Two variations of the "Buy" button at Potgang.co.uk

Three variations of the "Buy" button at Amazon.com

Three variations of the "Buy" button at Amazon.com

Be aware of cases when products are bundled as a special offer.

Product grouping at Amazon.com

Product grouping at Amazon.com

Availability

The add-to-cart signal is included into all Connect subscriptions (Pro, Premium and Ultimate).

Configuration

The Connect library provides a method, TLT.logSignal() with which to send the signal to the Acoustic Connect endpoint, as a JSON object. The Connect library must be initialized before the method is called.

There are multiple ways to trigger the signal, for example as soon as a user clicks on the Add to cart button or later when they open the shopping cart. It all depends on how your website is structured and on the purchasing flows it supports.

Required fields

You must populate the required fields before sending the signal: the name, ID, quantity and price of the product as well as the currency. If just one required value is missing, the signal gets discarded. If a field isn’t applicable to your business, use a hardcoded value as a placeholder.

On some websites, you may need separate pieces of logic to support all available purchasing flows (for example, from the product list page, from the product view page and from the product view modal).

If there is a data layer on your website, it will make your work easier.

FieldValuesDefinition
categoryString. Valid value - Behavior. The category of the signal. Do not edit.
currencyString. Valid values - ISO 4217 currency codes.The currency in which the price of the product is represented
effectString. Valid values:

- negative
- positive
Describes the effect of the signal on engagement. It is intended to be used for engagement index scoring.

We suggest sending positive for all add-to-cart signals.
nameString, up to 256 charactersAssign a name to the signal to differentiate it from other signals.
productIdStringThe identifier of the product. It may coincide with the SKU.
productNameStringThe name of the product
quantity NumberCaptures the quantity of the product added to the cart.
signalTypeString. Valid value -
addToCart.
The type of signal to enable. Do not edit.
unitPriceNumberThe unit price of the product

Optional fields

FieldValuesDefinition
discountNumberDiscount from the original price. If the exact amount is not provided, you could calculate the difference between the original and the current price.
productCategoryStringThe category that the product falls in based on the product catalog
productDescriptionStringThe description of the product
productImageUrlStringThe URL of the product image
productUrlStringThe URL of the product page
promotionIdStringFor the use case of on-site marketing like hero images and other calls-to-action, those calls-to-action would have a promotion ID that would "stick" to the behaviors after it.
signalCustomAttributesArray of objectsAllows for additional custom attributes. For each custom attribute, add an object with two string fields:name and value.
shoppingCartUrlStringThe URL of the shopping cart that the add-to-carts are contributing to
virtualCategoryStringThe category is based on how the visitor got to the page, for example from "New arrivals" or "Sale".

Example

/* eslint-disable padded-blocks */
/* eslint-disable one-var */
(function () {

    const signal = {
        signalType: "addToCart", // Required
        name: "addToCart generated by web site",
        category: "Behavior",
        productId: "", // Required
        productName: "", // Required
        productDescription: "",
        quantity: 1, // Required
        unitPrice: 0, // Required
        currency: "USD", // Required
        discount: 0,
        productCategory: "", // Important, useful for segmentation
        productUrl: "",
        productImageUrl: "",
        shoppingCartUrl: "https://" + window.location.host + "/shopping-cart",
        virtualCategory: "",
        promotionId: "",
        actionState: "",
        resumedCartItem: "",
        effect: "positive", // Required
        signalCustomAttributes: [
            {
                name: "type",
                value: ""
            }
        ]
    };

    // Array of CSS selectors and configurationTypes
    const addToCartButtons = [
        { selector: "#add-to-cart", type: "Product details page" },
        { selector: ".quick-add-button-rounded", type: "Quick add button" }
    ];

    // Attach click listeners to all elements matching selectors, send signal on clicks
    addToCartButtons.forEach((addToCartButton) => {
        const elements = document.querySelectorAll(addToCartButton.selector);
        if (!elements.length) return;
        elements.forEach((element) => {
            element.addEventListener("click", () => {
                // If the click was on a product details page button
                if (addToCartButton.type === "Product details page") {
                    const article = document.querySelector(".product--detailPage");
                    if (article) {
                        signal.signalCustomAttributes[0].value = "Product details page";
                        signal.productId = article.getAttribute("data-sku");
                        signal.productName = article.getAttribute("data-name");
                        signal.productUrl = article.getAttribute("data-url");
                        signal.productImageUrl = article.getAttribute("data-image-url");
                        signal.quantity = Number(article.querySelector(".cartItem--success").innerText) || 0;
                        const discountedPrice = Number(article.querySelector(".price-sale").innerText) || 0;
                        const regularPrice = Number(article.querySelector(".price-default").innerText) || 0;
                        if (discountedPrice) {
                            signal.unitPrice = discountedPrice;
                            signal.discount = Math.round((regularPrice - discountedPrice) * 100) / 100;
                        } else {
                            signal.unitPrice = regularPrice;
                        }
                        // Optional: display signal in console
                        console.log("addToCart signal: " + JSON.stringify(signal, undefined, 2));
                        // Send signal to Acoustic
                        window.TLT.logSignal(signal);
                    }
                }
                if (addToCartButton.type === "Quick add button") {
                    // Each article in a product grid has its own Quick Add button. Find the closest .product-tile
                    // element ancestor from the clicked button to identify the correct article in the list.
                    const article = addToCartButton.closest(".product-tile");
                    if (article) {
                        signal.signalCustomAttributes[0].value = "Quick add button";
                        signal.productId = article.querySelector(".thumbnail_code").innerText || "";
                        signal.productName = article.querySelector(".thumbnail_name").innerText || "";
                        signal.productUrl = article.querySelector(".thumbnail_link").href || "";
                        signal.productImageUrl = article.querySelector(".thumbnail_image").src.split("?")[0] || "";
                        signal.quantity = 1; // Only one item can be added at a time using Quick Add
                        const discountedPrice = Number(article.querySelector(".price-sale", "innerText")) || 0;
                        const regularPrice = Number(article.querySelector(".price-default", "innerText")) || 0;
                        if (discountedPrice) {
                            signal.unitPrice = discountedPrice;
                            signal.discount = Math.round((regularPrice - discountedPrice) * 100) / 100;
                        } else {
                            signal.unitPrice = regularPrice;
                        }
                        // Optional: display signal in console
                        console.log("addToCart signal: " + JSON.stringify(signal, undefined, 2));
                        // Send signal to Acoustic
                        window.TLT.logSignal(signal);
                    }
                }
            });
        });
    });
}());