Enable rich media interaction signals in the Connect web library

The rich media interaction signal captures user interactions with video and audio content on your website. This enables audience segmentation based on content consumption patterns and engagement levels.

Reasons to enable:

  • Track customer video review engagement
  • Monitor product video consumption
  • Measure tutorial or demo video completion
  • Understand audio content engagement
  • Segment users based on media interaction behavior

Availability: Premium and Ultimate


Implementation considerations

Capturing data

Most video players offer well-documented APIs that you can use to capture interaction events. Consult your video player API documentation to identify available events and how to access media information.

Interaction types

The signal supports these interaction types:

  • LOAD - Media file begins loading
  • LAUNCH - User initiates playback
  • PAUSE - User pauses playback
  • CONTINUE - User resumes playback after pausing
  • COMPLETE - User reaches the end of the media
  • STOP - User stops playback before completion
  • ENLARGE - User enters fullscreen or expands player

Event timing

Some players fire events multiple times (for example, multiple pause/play cycles). Decide whether to track every interaction or only significant milestones.

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 rich media interactions.
  • name: String - Name to differentiate this signal from others (for example, "Product review interaction from website"). Max length - 256 chars.
  • signalType (required): String - Valid value - richMediaInteraction.

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

  • interactionType: String - The type of user interaction with the media. Valid values: LOAD, LAUNCH, PAUSE, CONTINUE, COMPLETE, STOP, ENLARGE.
  • mediaCategory: String - The category the media falls into (for example, "video", "audio", "product demo").
  • mediaId (required): String - The URL or unique identifier of the media file. You can extract the ID from video element attributes or retrieve it from the video player API.
  • mediaName: String - The title of the audio or video file
  • signalCustomAttributes: Array of objects - Additional custom attributes. Each object has name and value string fields.
  • url: String - The URL of the page where the media file is embedded.

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: "richMediaInteraction",
                category: "Behavior",
                name: "richMediaInteraction from website",
                mediaId: "https://example.com/videos/product-demo.mp4",
                effect: "positive",

                // Optional fields
                interactionType: "LAUNCH",
                mediaCategory: "Product Demo",
                mediaName: "Wireless Headphones Demo",
                url: window.location.href,

                // Contact mapping
                audience: [
                    {
                        name: "Customer ID",
                        value: "AAUN-1417508"
                    }
                ]
            };

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

Complete implementation example - Video.js

This example tracks video interactions using the Video.js player API. The audience identifier is retrieved from the data layer. When the user selects a language from the dropdown, their preference is passed to the "Communication language" contact attribute.

// Initialize the Connect library
if (window.TLT) {
    TLT.initPremium({
        appKey: "APP_KEY",
        postUrl: "COLLECTOR_URL",
        callback: function() {
            if (typeof window.videojs !== "function") return;

            // Initialize video player and attach event listeners
            // See Video.js player API documentation: https://docs.videojs.com/
            const player = window.videojs("example_video");

            player.ready(function() {
                const mediaId = player.currentSrc() || player.cache_.src;
                const mediaName = mediaId.substring(mediaId.lastIndexOf("/") + 1);

                function sendRichMediaInteractionSignal(interactionType) {
                    const signal = {
                        signalType: "richMediaInteraction",
                        category: "Behavior",
                        name: "richMediaInteraction generated by website",
                        effect: "positive",

                        // Required fields
                        mediaId: mediaId,

                        // Optional fields
                        interactionType: interactionType,
                        mediaCategory: "Video",
                        mediaName: mediaName,
                        url: window.location.href
                    };

                    // Add contact mapping from the data layer
                    const customerId = window.dataLayer?.customerId;
                    if (customerId) {
                        signal.audience = [
                            {
                                name: "Customer ID",
                                value: customerId
                            }
                        ];

                        // Add communication language preference from dropdown
                        const language = document.querySelector(".language-select")?.value;
                        if (language) {
                            signal.audience.push({
                                name: "Communication language",
                                value: language
                            });
                        }
                    }

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

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

                // Track play event
                player.on("play", function() {
                    sendRichMediaInteractionSignal("CONTINUE");
                });

                // Track pause event
                player.on("pause", function() {
                    sendRichMediaInteractionSignal("PAUSE");
                });

                // Track completion event
                player.on("ended", function() {
                    sendRichMediaInteractionSignal("COMPLETE");
                });
            });
        }
    });
}

Extended example - HTML5 video element

This example tracks interactions using the native HTML5 video element. The audience identifier is retrieved from the data layer. When the user selects a language from the dropdown, their preference is passed to the "Communication language" contact attribute.

// Initialize the Connect library
if (window.TLT) {
    TLT.initPremium({
        appKey: "APP_KEY",
        postUrl: "COLLECTOR_URL",
        callback: function() {
            // Find all video elements on the page
            const videos = document.querySelectorAll("video");

            videos.forEach(function(video) {
                function sendRichMediaInteractionSignal(interactionType) {
                    const signal = {
                        signalType: "richMediaInteraction",
                        category: "Behavior",
                        name: "richMediaInteraction generated by website",
                        effect: "positive",

                        // Required fields
                        mediaId: video.currentSrc,

                        // Optional fields
                        interactionType: interactionType,
                        mediaCategory: "Video",
                        mediaName: video.getAttribute("data-video-title") || "Untitled Video",
                        url: window.location.href
                    };

                    // Add contact mapping from the data layer
                    const customerId = window.dataLayer?.customerId;
                    if (customerId) {
                        signal.audience = [
                            {
                                name: "Customer ID",
                                value: customerId
                            }
                        ];

                        // Add communication language preference from dropdown
                        const language = document.querySelector(".language-select")?.value;
                        if (language) {
                            signal.audience.push({
                                name: "Communication language",
                                value: language
                            });
                        }
                    }

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

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

                // Track when video starts loading
                video.addEventListener("loadstart", function() {
                    sendRichMediaInteractionSignal("LOAD");
                });

                // Track when user starts playback
                video.addEventListener("play", function() {
                    // Distinguish between initial launch and resume
                    if (video.currentTime === 0) {
                        sendRichMediaInteractionSignal("LAUNCH");
                    } else {
                        sendRichMediaInteractionSignal("CONTINUE");
                    }
                });

                // Track when user pauses
                video.addEventListener("pause", function() {
                    sendRichMediaInteractionSignal("PAUSE");
                });

                // Track when video completes
                video.addEventListener("ended", function() {
                    sendRichMediaInteractionSignal("COMPLETE");
                });

                // Track fullscreen toggle
                video.addEventListener("fullscreenchange", function() {
                    if (document.fullscreenElement) {
                        sendRichMediaInteractionSignal("ENLARGE");
                    }
                });
            });
        }
    });
}

Best practices

  1. Ensure the same media file always uses the same identifier across pages.
  2. Populate mediaName for better reporting and analysis.
  3. Use mediaCategory to group related content (product videos, tutorials, reviews).
  4. If your page has multiple videos, ensure each is tracked independently.
  5. Test the signal on desktop and mobile players.

Troubleshooting

Signals not firing for video interactions?

  • Verify the video player API is loaded before your signal code runs.
  • Check that event listeners are properly attached to the player.
  • Confirm the player fires the expected events (check player documentation).
  • Use console.log() to verify events are triggered.

Media ID not captured correctly?

  • Check the player API method for retrieving the video source.
  • Verify the video element has the src attribute or source element.
  • Look for alternative methods like currentSrc() or cache_.src.
  • Test with both directly embedded videos and playlist scenarios.

Duplicate signals for single interaction?

  • Some players fire events multiple times during state changes.
  • Add debouncing logic to prevent duplicate signals.
  • Check if multiple event listeners are attached accidentally.
  • Consider tracking only key milestones rather than every state change.

Player not detected?

  • Ensure the video player library loads before your signal code.
  • Check for correct player initialization syntax.
  • Verify player ID or selector matches your HTML.
  • Test with both ready events and direct initialization.

Related pages

How behavior signals are processed in Connect