Enable product configuration signals in the Connect web library

The product configuration signal captures user interactions with products that suggest evaluation and preparation to purchase. This signal helps track engagement beyond simple page views, identifying users who are actively considering a product.

Common interaction examples:

  • Selecting a size, color or variant
  • Completing customization fields (engraving, personalization)
  • Reading product reviews or FAQs
  • Clicking through product image galleries
  • Adjusting quantity selectors

Availability: Premium and Ultimate


Implementation considerations

Relationship to product view signal

The product configuration signal works in conjunction with the product view signal.

  • Product view - Collects data about the product itself.
  • Product configuration - Tracks user interactions indicating engagement.

Capture the same productName and productId values that you use for the product view signal. This ensures consistent tracking across related signals. You can scrape these values from the DOM or from the data layer if your website has one.

Triggering approach

Fire the signal each time a user interacts with a product element. This typically involves attaching event listeners to interactive elements on the product page.

Configuration type labels

Use the configurationType field to identify what the user interacted with. You can label by:

  • Product parameter - best for understanding which product attributes users care about. Examples: size, color, quantity, material, finish.
  • UI element - best for understanding which interface components get the most interactions. Examples: Size dropdown, Quantity stepper, Size chart link, Zoom button, Add to wish list button.
  • Action - best for understanding user intent and behavior patterns. Examples: read reviews, select color, view enlarged image, change quantity.

💡 Choose a consistent labeling approach across your implementation for better analytics.

Contact mapping

Any signal can be mapped to a contact. Use the audience object to provide a customer ID (contact key) or an addressable attribute (email or phone number). You can provide several identification records in the same signal — for example, a contact key and an email address. For details on how Connect processes identification records, see How behavior signals are processed in Connect.

Several sources of identification are available:

  • User identification stored in browser cookies
  • Temporary session-based storage
  • Persistent client-side storage
  • Data layer (for example, Google Tag Manager dataLayer)
  • URL parameters passed during navigation
  • Login API monitoring (capture identifier during successful authentication)

If none of these options are available, work with your development team to make the identifier accessible to the Connect library.

🚧

Important

We recommend attaching identifiers to as many signals as possible. However, if an identifier is missing, the system falls back on other signals from the same user session in order to identify the website visitor.


Configuration

Method

TLT.logSignal(signalObject)

Sends the signal to the Acoustic Connect endpoint as a JSON object. The Connect library must be initialized before calling this method.

Signal structure

Top-level fields

  • audience: Array of objects - Create an object for contact mapping and any number of additional objects to update contact attributes.
  • category: String - Valid value - Behavior.
  • consent: Object - Consent preferences to update for the contact. At least one of the following channel fields is required: email, sms or whatsapp.
  • description: String - Description of the signal
  • effect: String - Describes the effect of the signal on engagement. Valid values: negative, positive. Use positive for all product configuration signals.
  • name: String - Name to differentiate this signal from others (for example, "product configuration from website"). Max length - 256 chars.
  • signalType (required): String - Valid value - productConfiguration.

Audience object

Create an object with one or more identifiers for contact mapping (recommended) and any number of additional objects for other contact attributes you want to update.

  • name (required): String - Name of contact attribute. To get the full list of available attributes, use the Contact attributes query.
  • value: The new value of the contact attribute. Its format depends on the attribute type (text, number, Boolean or date). If you send an empty or null value, it will be ignored and the contact attribute won't be updated.

📘

Note

  • For date attributes, use the following format: yyyy-MM-dd'T'HH:mm:ssXXX.
  • For phone number attributes, use the ISO E.164 format: +[country code][area code][phone number] — no spaces, dashes or special characters. If the + symbol is omitted, Connect adds it automatically.
  • Consent object

Each channel accepts multiple entries to set different consent statuses per consent group in a single call.

  • enableOverrideExistingOptOut (required): Boolean - When true, current opt-out statuses will be overridden by new statuses. When false, contacts who have unsubscribed from communications won't have their consent status updated.
  • email: Array of objects - Consent entries for the email channel. The objects support the following fields:
    • status (required): Enum - Consent status for the email channel. Valid values: OPT_IN, OPT_OUT, OPT_IN_UNVERIFIED.
    • consentGroupIds: Array of strings - The IDs of consent groups a new status applies to. If you skip this field or send an empty array, the new consent status will be applied to all consent groups.
  • sms: Array of objects - Consent entries for the SMS channel. The objects support the following fields:
    • status (required): Enum - Consent status for the SMS channel. Valid values: OPT_IN, OPT_OUT, OPT_IN_UNVERIFIED.
    • consentGroupIds: Array of strings - The IDs of consent groups a new status applies to. If you skip this field or send an empty array, the new consent status will be applied to all consent groups.
  • whatsapp: Array of objects - Consent entries for the WhatsApp channel. The objects support the following fields:
    • status (required): Enum - Consent status for the WhatsApp channel. Valid values: OPT_IN, OPT_OUT, OPT_IN_UNVERIFIED.
    • consentGroupIds: Array of strings - The IDs of consent groups a new status applies to. If you skip this field or send an empty array, the new consent status will be applied to all consent groups.

📘

Note

To get the IDs of consent groups, use the dataSets query.

Signal content

  • configurationType: String - Label for the interaction that happened (for example, "size", "color", "reviews", "image gallery").
  • currency: String - ISO 4217 currency code (for example, "USD", "EUR", "GBP"). If there is only one currency on your website, provide a static value. If there is a selection, use dynamic values. If a product configuration signal comes without a value, the system will fall back on the default currency set for your Connect subscription.
  • discount: Number - Discount amount
  • imageUrls: Array of strings - URLs of product images
  • inventoryQuantity: Number - The number of units available
  • productCategory: String - Product category from catalog
  • productCategoryId: String - Product category identifier
  • productDescription: String - Description of the product
  • productId (required): String - Unique product identifier (may match SKU)
  • productName (required): String - Name of the product
  • productUrls: Array of strings - URLs of product pages
  • promotionId: String - ID from marketing campaigns that influenced the purchase
  • shoppingCartUrl: String - URL of the shopping cart
  • signalCustomAttributes: Array of objects - Additional custom attributes. Each object has name and value string fields.
  • unitPrice: Number - Unit price of the product
  • virtualCategory: String - Category based on navigation path (e.g., "New arrivals", "Sale")

Notes:

  • If any required field is missing or invalid, the entire signal will be discarded.
  • Optional fields enhance the signal but won't prevent processing if omitted or invalid.

Basic example

// Initialize the Connect library
if (window.TLT) {
    TLT.initPremium({
        appKey: "APP_KEY",
        postUrl: "COLLECTOR_URL",
        callback: function() {
            const signal = {
                // Required fields
                signalType: "productConfiguration",
                productId: "SKU-12345",
                productName: "Classic Crew Neck Sweater",

                // Optional fields
                name: "productConfiguration from website",
                configurationType: "Select size",
                unitPrice: 79.99,
                category: "Behavior",
                currency: "USD",
                inventoryQuantity: 42,
                effect: "positive",

                // Contact mapping
                audience: [
                    {
                        name: "Phone",
                        value: "+12025550194"
                    }
                ]
            };

            // Send the signal
            TLT.logSignal(signal);
        }
    });
}

Complete implementation example

This example tracks multiple types of product interactions on a clothing product detail page. The audience identifier and preferred size are retrieved from session storage, where they were stored during login.

// Capture the phone number from the login API response and store it
function monitorLoginApi(phone) {
    if (phone) {
        sessionStorage.setItem("phone", phone);
    }
}

// Initialize the Connect library
if (window.TLT) {
    TLT.initPremium({
        appKey: "APP_KEY",
        postUrl: "COLLECTOR_URL",
        callback: function() {
            // Scrape product details from the page
            const productId = document.getElementById("sku")?.innerText || "";
            const productName = document.querySelector(".data-product-name")?.innerText || "";
            const priceElement = document.querySelector(".product-price");
            const unitPrice = priceElement ? parseFloat(priceElement.innerText.replace(/[^0-9.]/g, "")) || 0 : 0;

            // Define selectors for different interaction types
            const productConfigurations = [
                { selector: ".faq-button", type: "Read FAQ" },
                { selector: ".size-select", type: "Select size" },
                { selector: "p.reviews", type: "Read reviews" },
                { selector: ".color-swatch", type: "Select color" },
                { selector: ".image-thumbnail", type: "View image" },
                { selector: ".quantity-selector", type: "Adjust quantity" }
            ];

            // Attach click listeners to all matching elements
            productConfigurations.forEach((productConfiguration) => {
                const elements = document.querySelectorAll(productConfiguration.selector);
                if (!elements.length) return;

                elements.forEach((element) => {
                    element.addEventListener("click", () => {
                        const signal = {
                            signalType: "productConfiguration",
                            category: "Behavior",
                            name: "productConfiguration generated from website",
                            effect: "positive",

                            // Required fields
                            productId: productId,
                            productName: productName,

                            // Configuration details
                            configurationType: productConfiguration.type,
                            unitPrice: unitPrice,
                            currency: "USD"
                        };

                        // Add contact mapping and preferred size from session storage
                        const phone = sessionStorage.getItem("phone");
                        if (phone) {
                            signal.audience = [
                                {
                                    name: "Phone",
                                    value: phone
                                }
                            ];

                            // If the user selected a size, add it to audience
                            if (productConfiguration.type === "Select size") {
                                const selectedSize = element.getAttribute("data-size") ||
                                    element.innerText.trim();
                                if (selectedSize) {
                                    signal.audience.push({
                                        name: "Preferred size",
                                        value: selectedSize
                                    });
                                }
                            }
                        }

                        // Optional: Log signal for debugging
                        console.log("productConfiguration signal:", JSON.stringify(signal, null, 2));

                        // Send signal to Connect
                        TLT.logSignal(signal);
                    });
                });
            });
        }
    });
}

Best practices

  1. Track meaningful interactions - Focus on interactions that indicate purchase intent (size/color selection, reviews) rather than trivial actions.
  2. Test interaction coverage - Verify signals fire for all important product interactions on your pages.
  3. Consider mobile interactions - Ensure touch events are properly captured on mobile devices.

Troubleshooting

Signals not firing on certain interactions?

  • Verify CSS selectors match the actual elements in your DOM.
  • Check if elements are dynamically loaded after page load.
  • Use querySelectorAll results to confirm elements are found.
  • Test both click and touch events for mobile compatibility.

Product data not captured correctly?

  • Confirm product details exist in the DOM when script runs.
  • Verify selectors match your site's HTML structure.
  • Use console.log() to debug extracted values.

Related pages

How behavior signals are processed in Connect