Track external search interfaces
Zoovu's script lets you track external search interfaces like search boxes, search results, product detail pages, and checkout interfaces - that aren't directly linked to the JavaScript plugin. It's helpful if you're using the API to render search results and want to track searches that lead to sales.
KPI configurations for tracking
KPI | Configuration |
---|---|
Search query volume | searchBox |
Click-through rates (CTR) on results | searchResults |
Add to cart events | productDetailPage |
Conversion rate from search | productDetailPage , checkout |
Average order value from search | checkout |
Related queries | searchBox |
Filter engagement | searchResults |
Search suggestions engagement | searchSuggestions |
Product detail page visits | productDetailPage |
Connect your interface to zoovu tracking
To connect your custom interface to Zoovu's tracking system, add the external tracking configuration to your zoovuSearchConfig
:
window.zoovuSearchConfig = {
siteId: 'mysite.com',
tracking: {
external: { /*...*/ }
}
}
If you're not using the Zoovu search plugin, you can also add a dedicated tracking script:
<script>
window.zoovuSearchTrackingConfiguration = {
siteId: '123', // your project ID
baseUrl: 'https://api.search.zoovu.com/insights/insights?projectId={PROJECT_ID}', // replace {PROJECT_ID} with your project ID
interface: {
/*...*/
}
}
</script>
<script defer src="https://cdn.search-studio.zoovu.com/zoovu-tracker.min.js"></script>
All statistics tracked via external tracking will be merged with your general search stats under the same Site ID.
Initialization strategies
You can specify when events should be attached to your search interface using one of the following strategies:
On load
Attach events when the script is executed (default).
{
type: 'onload'
}
Rendered element
Attach events when a specific element appears in the DOM.
{
type: 'interval',
waitForElem: '#serp',
duration: 250
}
Mutated element
Attach events when an element (or document) changes.
This strategy can be helpful for example if your pagination loads and renders the next page of search results without a page reload.
{
type: 'observer',
wrapper: '#serp'
}
Expected conditions
Expected conditions define one or multiple conditions that need to be fulfilled in order for a specific set of events to be attached. For example if your search result page is available under https://mydomain.com/search
you can specify the /search
regular expression the URL has to match for the search result page tracking to be initialized.
There are three types of expected conditions you can define. if multiple conditions are provided, all have to be fulfilled in order for the events to be initialized:
-
URL Regex — a regular expression the URL must match
-
Search Param — a query parameter that must be present in the URL
-
DOM Element — a CSS selector, a matching element must be present in DOM
{
urlRegex: '/search',
searchParam: 'q',
domElement: '#search-results'
}
Data sources
A data source defines where a particular information (for example the search query) should be extracted from.
Query Parameter
The data is extracted from a query parameter:
{
type: 'urlParam',
paramName: 'q'
}
URL Regex
A regular expression is applied on the URL and the data get extracted from a matching group:
{
type: 'urlRegex',
groupIndex: 0,
regex: '/search/(.*)'
}
DOM Element
The data is extracted from the first DOM element matching a given CSS selector. By default the inner text is extracted. An attribute value can be extracted by providing the attribute name prefixed by the @
sign. If a source is given, and it is not prefixed by the @
sign, a property of the element will be used (e.g. clientWidth
).
If the data source is being extracted after a search suggestion or search result is selected, after a product has been added to a cart, or within the checkout, the CSS selector will be relative to the single result/product node:
{
type: 'domElement',
selector: '#product',
source: '@data-article-number'
}
Getter
The data is provided by a custom function. If the getter is called after a search suggestion or search result is selected, after a product has been added to a cart, or within the checkout, it will receive a DOM element (a single result/product) as a first argument:
{
type: 'getter',
getter: function(result) {
return result.getAttribute('id').split('-')[0];
}
}
DOM Object
The data is extracted from a JSON object that is present in the DOM (inner text of a node), you need to specify a JPath to point to the property you want to extract:
{
type: 'domJson',
objectSelector: '#products-json',
jpath: 'products[0]/price'
}
Window Object
The data is extracted from an object that is attached to the window, you need to specify a JPath to point to the property you want to extract:
{
type: 'windowJson',
propertyName: 'Products',
jpath: 'data/price'
}
Static
The data is a static value:
{
type: 'static',
value: '€'
}
Configuration
Search box
By connecting your search box (zoovuSearchTrackingConfiguration.interface.searchBox
) to the Zoovu Search tracking, you will get an overview of what queries were submitted to the search. A search box and search button CSS selector, and an initialization strategy can be configured:
{
selector: '#searchBox',
button: '#searchButton',
initializationStrategy: {
type: 'onload'
},
initCallback() {
console.log('Search Box events initialized');
}
}
Search suggestions
By connecting your search suggestions dropdown (zoovuSearchTrackingConfiguration.interface.searchSuggestions
), you will get an overview of what pages were followed from your suggestion box and what queries led to those.
To connect your search suggestions to the Zoovu Search tracking, you need to specify the suggestion block, suggestion item, and active suggestion item CSS selectors. Additionally, you can set an initialization strategy, and data sources pointing to the article number and/or unique identifier of the selected search suggestion (to connect your suggestions to the checkout tracking):
{
blockSelector: '.search-suggest',
itemSelector: '.search-suggest__item',
activeItemSelector: '.search-suggest__item--selector',
initializationStrategy: {
type: 'observer',
wrapper: '.search-suggest'
},
articleNumberSource: {
type: 'domElement',
selector: 'input[name="sku"]',
source: '@value'
},
identifierSource: {
type: 'domElement',
selector: 'input[name="product-id"]',
source: '@value'
},
initCallback() {
console.log('Search Suggestion events initialized');
}
}
Search result page
By connecting your search result page (zoovuSearchTrackingConfiguration.interface.searchResults
), you will get an overview of all the queries, their CTRs, and what results have been selected. To connect your search result page to the Zoovu Search tracking, you need to provide a block CSS selector, a result item CSS selector, a query data source, and expected conditions.
You can also adjust the tracking with the following settings:
-
Exclude selector — a CSS selector pointing to nodes within a single search results that should not be tracked as a click-through (e.g. add to wishlist button)
-
Group selector — a CSS selector pointing to a single content group (e.g. if you split your search results into multiple tabs groupped by a category)
-
Initialization strategy
-
Article number and identifier data sources — to connect your search result page to checkout tracking
{
blockSelector: '.search-result',
itemSelector: '.search-result__item',
singleGroupSelector: '.search-result__group',
querySource: {
type: 'urlParam',
paramName: 'q'
},
expectedConditions: {
urlRegex: '/search',
searchParam: 'q'
},
articleNumberSource: {
type: 'domElement',
selector: 'input[name="sku"]',
source: '@value'
},
initCallback() {
console.log('SERP events initialized');
}
}
Product detail page
By connecting your product detail page (zoovuSearchTrackingConfiguration.interface.productDetailPage
), you will be able to track those "Add to Cart" events which are triggered after a user navigates from search suggestions or the search results page.
For a product to be considered as followed from search suggestions or search result page, the link, identifier, or article number must match the data tracked on the Search Result Page/within Search Suggestions.
For tracking to be working on the product detail page make sure that you didn't disable cookies by setting zoovuSearchConfig.allowCookies = false
; or disabling "Tracking -> Allow cookies".
To connect your product detail page to the Zoovu Search tracking, you need to add the following settings:
-
Trigger — a CSS selector pointing to your add to cart button or form
-
Article Number Data Source or Identifier Data Source — the source of an article number or unique identifier
-
Price Data Source — the source of the product price (for a single unit)
-
Price Unit Data Source — the source of the price unit
-
Count Data Source — the source of the number of products being added to cart
-
Expected Conditions — the conditions identifying a product detail page
You can also add the following settings:
-
Wrapper CSS Selector — specifying this will make all DOM element data source selectors relative to the given node
-
Link Data Source — by default the URL open in the browser is tracked as the product link, you can specify a data source for the link to track a normalized value
-
Initialization Strategy
{
trigger: '#add-to-cart',
expectedConditions: {
urlRegex: '/p/'
},
articleNumberSource: {
type: 'domElement',
selector: 'input[name="sku"]',
source: '@value'
},
priceSource: {
type: 'domElement',
selector: 'meta[name="price"]',
source: '@content'
},
priceUnitSource: {
type: 'static',
value: '€'
},
countSource: {
type: 'domElement',
selector: 'input[name="count"]',
source: 'value'
},
initCallback() {
console.log('PDP events initialized');
}
}
Checkout
By connecting your checkout interface (zoovuSearchTrackingConfiguration.interface.checkout
), you will be able to track what products have been bought after a product has been followed from your search suggestions and/or search results. You can also set the trackAll property to true to track every single product bought.
For a product to be considered as followed from search suggestions or search result page, the link, identifier, or article number must match the data tracked on the Search Result Page/within Search Suggestions.
For tracking to be working on the checkout page make sure that you didn't disable cookies by setting zoovuSearchConfig.allowCookies = false
; or disabling "Tracking -> Allow cookies".
To connect your checkout interface to the Zoovu Search tracking, you need to add the following settings:
-
Trigger — a CSS selector pointing to a button or form which completes the order
-
Expected Conditions
You also need to specify one of the following three data sources that can be used to collect the information about all products that are in the cart (see type definitions below):
-
Checkout item source (
CheckoutItemSource
interface)-
CSS selector pointing to a single product in cart
-
article number, link, identifier, unit price, price unit, and count data sources
-
-
Checkout item object source (
CheckoutItemObjectSource
interface)-
a CSS selector pointing to a DOM element that includes a JSON array holding the cart data, or a window property name pointing to a global array holding the cart data
-
article number, link, identifier, unit price, price unit, and count JPaths
-
-
Checkout data getter (
CheckoutDataGetter
interface)-
a custom function returning an array of products in cart
-
every entry should have the following properties:
articleNumber
,link
,identifier
,unitPrice
,priceUnit
, andcount
-
If your checkout page is dynamic, you can also provide an Initialization Strategy.
{
expectedConditions: {
urlRegex: '/cart$'
},
trigger: '#checkout',
itemSource: {
selector: '.order__item',
articleNumberSource: {
type: 'domElement',
selector: '.link',
source: '@data-sku'
},
linkSource: {
type: 'domElement',
selector: '.link',
source: '@href'
},
unitPriceSource: {
type: 'domElement',
selector: '.link',
source: '@data-price'
},
priceUnitSource: {
type: 'static',
value: 'EUR'
},
countSource: {
type: 'domElement',
selector: 'input[name="quantity"]',
source: '@value'
}
},
initCallback() { console.log('Checkout events initialized'); }
}
Type definitions
/* external-tracking.types.ts */
enum InitializationStrategyType {
Onload = 'onload',
Interval = 'interval',
Observer = 'observer'
}
interface InitializationStrategy {
type: InitializationStrategyType,
duration?: number,
waitForElem?: string,
wrapper?: string
}
enum DataSourceType {
UrlParam = 'urlParam',
UrlRegex = 'urlRegex',
DomElement = 'domElement',
Getter = 'getter',
DomObject = 'domJson',
WindowObject = 'windowJson',
Static = 'static'
}
interface Getter {
(domElement? : Element) : any
}
interface DataSource {
type: DataSourceType,
paramName?: string,
regex?: string,
groupIndex?: number,
selector?: string,
source?: string,
getter?: Getter,
objectSelector?: string,
propertyName?: string,
jpath?: string,
value?: string
}
interface ExpectedConditions {
urlRegex?: string,
searchParam?: string,
domElement?: string
}
interface SearchBoxConfiguration {
selector: string,
button?: string,
initializationStrategy?: InitializationStrategy
}
interface SuggestionsConfiguration {
blockSelector: string,
itemSelector: string,
activeItemSelector: string,
initializationStrategy?: InitializationStrategy,
articleNumberSource?: DataSource,
identifierSource?: DataSource
}
interface ProductDetailPageConfiguration {
trigger: string,
wrapper?: string,
articleNumberSource?: DataSource,
identifierSource?: DataSource,
linkSource?: DataSource,
priceSource: DataSource,
priceUnitSource: DataSource,
countSource: DataSource,
expectedConditions: ExpectedConditions,
initializationStrategy?: InitializationStrategy
}
interface SearchResultsConfiguration {
blockSelector: string,
itemSelector: string,
excludeActiveSelector?: string,
singleGroupSelector?: string,
querySource: DataSource,
expectedConditions: ExpectedConditions,
initializationStrategy?: InitializationStrategy,
articleNumberSource?: DataSource,
identifierSource?: DataSource
}
interface CheckoutEntry {
articleNumber?: string,
link?: string,
identifier?: string,
unitPrice?: number,
priceUnit?: string,
count?: number
}
interface CheckoutDataGetter {
() : Array<CheckoutEntry>
}
interface CheckoutItemSource {
selector: string,
articleNumberSource?: DataSource,
linkSource?: DataSource,
identifierSource?: DataSource,
unitPriceSource?: DataSource,
priceUnitSource?: DataSource,
countSource?: DataSource
}
interface CheckoutItemObjectSource {
selector?: string,
windowProperty?: string,
entryJPath: string,
articleNumberJPath?: string,
linkJPath?: string,
identifierJPath?: string,
unitPriceJPath?: string,
priceUnitJPath?: string,
countJPath?: string
}
interface CheckoutConfiguration {
trigger: string,
expectedConditions: ExpectedConditions,
getter?: CheckoutDataGetter,
itemSource?: CheckoutItemSource,
itemObject?: CheckoutItemObjectSource,
initializationStrategy?: InitializationStrategy,
trackAll?: boolean
}
interface TrackingConfiguration {
searchBox?: SearchBoxConfiguration,
searchSuggestions?: SuggestionsConfiguration,
searchResults?: SearchResultsConfiguration,
productDetailPage?: ProductDetailPageConfiguration,
checkout?: CheckoutConfiguration
}
Manual tracking
If the declarative tracking configuration doesn't fit your use case (e.g., you need to wait for an asynchronous request to complete), you can use the ZoovuSearchInsightsTracker
attached to the window to manually track events. You can combine both approaches, allowing you to declaratively define tracking for some events while manually tracking others.
Note: If you manually track the add-to-cart or checkout events, set window.zoovuSearchTrackingConfiguration.interface.hasCheckoutTracking
to true
.
Tracking methods
Use these methods to track search interactions. Each method captures specific user actions, helping you analyze search behavior.
Track when the search box is focused
Triggered when a user clicks or taps on the search box.
window.ZoovuSearchInsightsTracker.trackSearchBoxFocus(searchBoxNode)
Track when a user abandons the search box
Triggered when a user starts typing but doesn't submit a search.
window.ZoovuSearchInsightsTracker.trackSearchBoxAbandon(query, numAutocompleteResults, searchBoxNode)
Track when autocomplete suggestions are displayed
Triggered when search suggestions appear in the dropdown.
window.ZoovuSearchInsightsTracker.trackShowSuggests(searchBoxNode, undefined, undefined, query, numAutocompleteResults, queryDuration)
Track when a user selects an autocomplete suggestion
Triggered when a user clicks on a suggestion from the autocomplete dropdown.
window.ZoovuSearchInsightsTracker.trackSelectSuggest(searchBoxNode, undefined, selectedNode, query, numAutocompleteResults, position, link, undefined, undefined, sku, sku)
Track when a search is submitted
Triggered when a user presses enter or clicks the search button.
window.ZoovuSearchInsightsTracker.trackSubmitSearch(query, searchBoxNode, searchButtonNode)
Track when search results are displayed (SERP shown)
Triggered when search results are loaded and displayed to the user. Triggered only when a new search is performed (not when paginating).
window.ZoovuSearchInsightsTracker.trackSerpShow(undefined, undefined, query, numResults)
numResults
- results on the current page only
query
- only the search term, excluding active filters
Track when a user abandons the SERP
Triggered when a user sees the search results but does not interact (no clicks, no filtering).
window.ZoovuSearchInsightsTracker.trackSerpLeave(undefined, undefined, query, numResults)
Track when a user clicks on a search result (SERP clickthrough)
Triggered when a user clicks a search result to visit its product detail page (PDP).
window.ZoovuSearchInsightsTracker.trackSerpClick(query, resultNode, undefined, numResults, position, positionInGroup, link, undefined, sku, sku)
position
- reflects actual position across all pagessku
- product article number, repeated for compatibilityresultNode
can be:- The
<a>
tag inside the result. - The
<div>
containing the result. - Left undefined (no longer actively used).
- The
Track when a user adds a product to the cart
Triggered when a user adds a product to the cart after interacting with search.
window.ZoovuSearchInsightsTracker.trackAddToCart(sku, sku, link, count, price, priceUnit, isSerp, isAutocomplete)
isSerp = true
if the add-to-cart action happens from a search result pageisAutocomplete = true
if the add-to-cart action happens from autocomplete suggestions
Track when a user completes a checkout
Triggered when a user successfully completes a purchase.
window.ZoovuSearchInsightsTracker.trackBuy(products)
Example: Call the following method to track a checkout event with multiple purchased items:
window.ZoovuSearchInsightsTracker.trackBuy([{
articleNumber: 'sku',
identifier: 'sku',
link: 'https://mysite.com/p/sku',
unitPrice: 14,
priceUnit: '€',
count: 5
}]);
sku
refers to the article number and should match the identifier in the data platform (it is not the product name). The method includes sku
twice for historical compatibility reasons.