Enable on-site search signals in the Connect web library
The on-site search signal captures the search terms visitors use on your website and the number of results returned. This helps identify what users are looking for, discover content gaps and understand search effectiveness.
Reasons to enable:
- Track popular search terms
- Identify zero-result searches for content optimization
- Segment users based on search behavior
- Trigger campaigns for users who can't find what they're looking for
Availability: Premium and Ultimate
Implementation considerations
Data extraction approaches
- From URL query string. Many sites include search terms in the URL (for example,
?searchTerm=headphones). Extract the term by parsing the query string. Remember to decode URL encoding and replace+with spaces. - From page content. Scrape the search term displayed on the results page. Often shown in headings or result summaries.
- From input field. Capture the value from the search input field. Useful if search doesn't navigate to a new page.
Number of results
The number of search results is typically available in the page body. Consider these scenarios:
- Direct result count. Most sites display total results (for example, "Showing 47 results"). Scrape this number directly.
- Page-based display. Some sites only show number of pages (for example, "Page 1 of 5"). If this is the case, calculate total results: pages × results per page.

Example from bbc.co.uk
- Zero results. Set
effecttonegativewhen no results are found. This helps identify content gaps and failed searches.
Relationship to page view signal
If you've already enabled the page view signal, you can adopt a similar approach for the on-site search signal by capturing the URL of the search results page.
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: Object - Key-value pairs mapping the signal to a contact and optionally updating contact attributes. Keys must match attribute names exactly as they appear in Connect, including capitalization and spacing.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,smsorwhatsapp.description: String - Description of the signaleffect: String - Describes the effect of the signal on engagement. Valid values:negative,positive. If a search term returns results, sendpositive. If there are no results, sendnegative.name: String - Name to differentiate this signal from others (for example, "onSiteSearch from online store"). Max length - 256 chars.signalType(required): String - Valid value -onSiteSearch.
Audience object
Create a flat key-value object where each key is a contact attribute name and each value is the new value for that attribute. Include at least one identifier for contact mapping (recommended) and any number of additional pairs to update other contact attributes.
Important:
The audience object must be a flat key-value object — not an array of name/value pairs. If the format doesn't match, the contact will not be created or updated.
Note
- Attribute keys must match exactly how they appear in Connect — including capitalization and spacing. Use the Contact attributes query to look up attribute names.
- The format of each value depends on the attribute type: text, number, Boolean, or date.
- 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.- Sending an empty or null value is ignored — the contact attribute will not be updated.
- Consent object
Each channel accepts multiple entries to set different consent statuses per consent group in a single call.
enableOverrideExistingOptOut(required): Boolean - Whentrue, current opt-out statuses will be overridden by new statuses. Whenfalse, 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
numberOfResults(required): Number - The number of results that matched the search termsearchTerm(required): String - The word or phrase that the visitor searched forsignalCustomAttributes: Array of objects - Additional custom attributes. Each object hasnameandvaluestring fields.
Basic example
// Initialize the Connect library
if (window.TLT) {
TLT.initPremium({
appKey: "APP_KEY",
postUrl: "COLLECTOR_URL",
callback: function() {
const signal = {
// Required fields
signalType: "onSiteSearch",
searchTerm: "wireless headphones",
numberOfResults: 24,
// Optional fields
category: "Behavior",
name: "onSiteSearch from website",
effect: "positive",
// Contact mapping
audience: {
"Customer ID": localStorage.getItem('customerId')
}
};
// Send the signal
TLT.logSignal(signal);
}
});
}
Complete implementation example
This example extracts the search term from the URL query string, scrapes the result count and sets the effect based on whether results were found. The audience identifier is extracted from a URL parameter.
// Initialize the Connect library
if (window.TLT) {
TLT.initPremium({
appKey: "APP_KEY",
postUrl: "COLLECTOR_URL",
callback: function() {
const href = window.location.href;
// Check if we are on the search results page
if (href.includes("s?searchTerm=")) {
// Extract and clean search term from query string
let searchTerm = href.split("s?searchTerm=")[1] || "";
searchTerm = searchTerm.replaceAll("+", " ");
searchTerm = decodeURIComponent(searchTerm);
// Scrape number of results from the page
const numberOfResults = Number(document.querySelector(".itemCount")?.innerText) || 0;
const signal = {
signalType: "onSiteSearch",
category: "Behavior",
name: "onSiteSearch generated by website",
// Required fields
searchTerm: searchTerm,
numberOfResults: numberOfResults,
// Set effect based on whether results were found
effect: numberOfResults ? "positive" : "negative"
};
// Add contact mapping from URL parameter
const urlParams = new URLSearchParams(window.location.search);
const customerId = urlParams.get("customerId");
if (customerId) {
signal.audience = {
"Customer ID": customerId
};
}
// Optional: Log signal for debugging
console.log("onSiteSearch signal:", JSON.stringify(signal, null, 2));
// Send signal to Connect
TLT.logSignal(signal);
}
}
});
}
Troubleshooting
Search term not captured correctly?
- Verify the URL parameter name matches your site's search implementation.
- Decode URL encoding and replace + with spaces before sending.
- Test with multi-word queries and special characters.
Result count incorrect or missing?
- Verify the selector matches the element that displays the result count.
- Check if the count is rendered asynchronously — you may need to wait for it to load.
- For page-based display, calculate total results: pages × results per page.
Signal not firing on search pages?
- Confirm your page detection logic matches the URL pattern of your search results page.
- Verify the Connect library loads on search result pages.
- Use console.log() to verify the signal object before sending.
Contact not created or updated?
- Verify the audience field is a flat key-value object — if the format doesn't match, the contact will not be created or updated.
- Confirm attribute key names match exactly how they appear in Connect — including capitalization and spacing.
- Confirm the attribute value type matches the field type defined in Connect (text, number, Boolean, or date).
Related pages
Updated 7 days ago
