Search Event

Overview

This section explains how Pulse tracks search-related interactions on your website, including standard text-based search and visual search. These events capture user intent at the discovery stage and play a critical role in improving search relevance, analytics, and personalization.

Workflow for Search Event

The mandatory query payload is captured from the search input box, and the event is triggered when the shopper either presses the Enter key or clicks the search submit button.

In this reference markup, the query value is extracted from the input value using the class selector.

<form id="searchQueryForm" method="method" action="/action">
  <input
    class="search-inputbox"
    id="searchInput"
    type="text"
    placeholder="find amazing products"
  />
  <button class="search-submit-button" id="searchBtn" type="submit">
    <i class="fas fa-search-icon"></i>
  </button>
</form>

Example markup of the category page:

window.UnbxdAnalyticsConf = window.UnbxdAnalyticsConf || {};
window.UnbxdAnalyticsConf["page"] =
  "{{categoryPath used for category api call (value of 'p' parameter)}}";
window.UnbxdAnalyticsConf["page_type"] = "BOOLEAN";

Visual Search Event

Payload Details

Attribute NameDatatypeValue to Pass
imageIdstringId of the image, to be retrieved from the response of visualSearch API
boxIdstringOptional, the ID of the bounding box that has been selected. Look for the selected key in the visualSearch API response

Refer to the following code snippet to call the Unbxd.track function to trigger the visualSearch event.

<script type="text/javascript">
   	var payload = 
		{
   	imageId: 'ad85491c-9d2b-4cab-900a-df96aa11f0d9',
     	boxId: '1089',
   	}


   	if(Unbxd && typeof Unbxd.track === 'function')
	 {
   		Unbxd.track('visualSearch', payload)
   	} else 
		{
   		console.error('Pulse SDK is missing or initialized out of sequence; ensure it is fully loaded before using it.')
    }
</script>

📘

Refer here for details on Visual Search API.

Click Event

The mandatory pid payload is captured from the product element of the Products Listing Page, and the click event is triggered when the shopper clicks on the product.

Key points:

  • The pid can be obtained from an HTML attribute or a URL, such as the img_url or href on the product card.
  • If the unique ID for the product has not been added to the product element, refer to the Netcore Unbxd Search API response to pass it.
<div class="search-results-grid" pageType="search">
  <div class="search-result" data-item-id="371823">
    <a href="https://www.example.com/product/productname">
      <img src="https://www.example.com/images/productname.png" />
      <span>Organic Honeycrisp Apple</span>
    </a>
  </div>
  <div class="search-result" data-item-id="371811">
    <a href="https://www.example.com/product/productname">
      <img src="https://www.example.com/images/productname.png" />
      <span>Organic Banana</span>
    </a>
  </div>
</div>

Facets Event

Pulse tracks facet and filter interactions on your website, including filter clicks, clears, applies, pre-selected filters from the URL, and range sliders. These events capture how shoppers refine results on listing pages and play a critical role in improving relevance, analytics, and personalisation.

Pulse listens on mouseup for the elements you list under triggers. When a shopper changes a filter, it reads each facet's group name and value from the DOM (or from callbacks you provide), and then emits the facet event according to your analytics setup.

👍

Important Point to Remember

Pulse resolves the facet group name and option value from the DOM using closest() from the click target. Both must resolve inside a single facet group wrapper. If your CSS class names are unstable (for example, generated hashes), add stable data-* attributes on facet groups or options so selectors remain reliable.

Integrate Facets Tracking

  1. Review prerequisites: Every facet interaction requires the group name and option value to be resolvable from the DOM, plus a way to read pre-selected filters from the URL. Ensure these values are present in the page, DOM, or URL before sending the event. Refer to the prerequisites section below for detailed information.
  2. Provide selectors and callbacks: Share the CSS selectors and the getDataFromCB, onFacetClick, and onPreSelectedAtURL callbacks for your storefront so group names and option values resolve correctly from your markup.
  3. Validate facet data retrieval: Verify that Pulse can retrieve the facet group name, option value, and pre-selected filters from the DOM and URL.

Mandatory Configuration

Below are the items you must supply so the facets configuration can be written and maintained.

DeliverableWhat to provide
Per-group wrapperA selector that matches one facet group at a time (for example, one "Color" block). Pulse uses closest() from the click target, so name and value must resolve inside that wrapper.
Click targetsSelector(s) for each clickable option: checkbox row, link, swatch, slider handle, and so on.
Selected stateHow a chosen option is indicated in the DOM (for example, input:checked or a selected class).
Facet group labelWhere the visible group title appears (for example, the heading for "Color" or "Brand").
Option label / valueWhere the visible or attributable value appears for each option (text node, label, or stable data-*).
Clear / Apply controlsIf the UI has clear-all, clear-group, apply-group, or apply-all controls, the selectors for those controls. Omit if not present.
Filter URL rulesHow selected filters appear in the URL when a user lands on a pre-filtered link (query string layout, which keys are facets vs. navigation). Used to implement onPreSelectedAtURL.
Range / slider UIIf price or other ranges use sliders or min/max inputs, describe that UI separately from checkbox-style facets.

Configuration Shape

The facets configuration is a top-level array on the customer analytics config object. Use a separate array entry when the layout differs (for example, desktop sidebar vs. mobile filter sheet) or when checkbox-style facets and range facets need different selector and callback patterns.

Required Fields

FieldPurpose
elemWrapperSelector for one facet group container.
triggersObject of action selectors; must include facetElem.
triggers.facetElemThe clickable facet option element(s).
selected{ selector: "..." } — how Pulse detects a selected option.
nameHow to read the facet group name (selector, and/or attr, getDataFromCB).
valueHow to read the facet option value (selector, and/or attr, getDataFromCB).
facetCBCallback object; must include onPreSelectedAtURL.

Optional Triggers

KeyWhen to include
clearAllControl that clears all filters.
clearFacetsControl that clears one facet group.
applyFacets"Apply" for one group (apply-style UI).
applyAll"Apply all" for pending changes.

If you omit apply-related triggers, tracking follows each facet click. If you include them, Pulse uses accumulate-then-apply behavior for those controls.

Optional Fields

KeyPurpose
facetCB.onFacetClickCustom handling for a click; typically required for range/slider facets.
miscOptional extra configuration supported by your analytics build, if applicable.

Check if facet payload data is retrieved

Click-driven facets (checkbox, link, swatch)

The mandatory facet group name and option value are captured from the DOM when the shopper clicks a filter option. The event is triggered on mouseup on any element matching triggers.facetElem.

Key points:

  • Each elemWrapper instance must contain a node the name configuration can read as the group label.
  • Each elemWrapper instance must contain nodes matching triggers.facetElem for every selectable value.
  • The markup inside the wrapper must satisfy the selected rule when an option is chosen.
  • Avoid a single elemWrapper around the entire filter column if that causes name to always resolve to the first group's title only. Prefer the repeating root element of each facet group (accordion section, card, column block, and so on).
  • For collapsed content where styling such as visibility: hidden prevents normal text reads, use getDataFromCB on name or value with a fallback (for example, textContent on a known descendant).

Example markup of a facet group on the listing page

<div class="filter-group">
  <h4 class="filter-heading">Color</h4>
  <ul>
    <li class="filter-option">
      <label>
        <input type="checkbox" />
        <span class="option-label">Red (24)</span>
      </label>
    </li>
    <li class="filter-option">
      <label>
        <input type="checkbox" checked />
        <span class="option-label">Blue (12)</span>
      </label>
    </li>
  </ul>
</div>

<div class="filter-group">
  <h4 class="filter-heading">Brand</h4>
  <ul>
    <li class="filter-option">
      <label>
        <input type="checkbox" checked />
        <span class="option-label">Nike (8)</span>
      </label>
    </li>
    <li class="filter-option">
      <label>
        <input type="checkbox" />
        <span class="option-label">Adidas (5)</span>
      </label>
    </li>
  </ul>
</div>

<div class="filters-toolbar">
  <button class="clear-all" type="button">Clear all</button>
</div>

Range and slider facets

Implement range facets as a separate entry in the facets array (do not combine with checkbox-style markup in one entry unless one selector pattern truly covers both).

Key points:

  • Scope elemWrapper to range/slider blocks only.
  • Place triggers.facetElem on controls that receive mouseup when the user finishes a change (handles, track, inputs).
  • Implement facetCB.onFacetClick to read min/max (or your site's equivalent) from the DOM and return a facets object in the callback shape (see the returned shape below).
  • Implement onPreSelectedAtURL to reflect the range from the URL or compare current values to defaults, per your URL and DOM design.
  • Checkbox-style selected rules are usually insufficient for sliders; onFacetClick is the standard approach.

Example markup of a price range slider

<div class="filter-group filter-range" data-facet="price">
  <h4 class="filter-heading">Price</h4>
  <div class="range-slider">
    <span class="range-handle handle-min" data-min="0"></span>
    <span class="range-handle handle-max" data-max="500"></span>
  </div>
  <div class="range-values">
    <input type="number" class="range-min-input" value="0" />
    <input type="number" class="range-max-input" value="500" />
  </div>
</div>

Pre-selected filters from URL

The facetCB.onPreSelectedAtURL callback is mandatory. It reads the current page URL (or equivalent) when filters may already be applied and returns the structure the facets callbacks expect.

Key points:

  • Use the same facet keys as in click-driven resolution.
  • Exclude URL parameters that are not filters (your site defines which keys to skip — commonly search pagination, sort-only params, and so on).
  • Return undefined when there is nothing to return.

Return shape from onPreSelectedAtURL or onFacetClick

{
  facets: {
    Color: ["Red", "Blue"],
    Brand: ["Nike"],
    Price: ["0 TO 500"],
  },
}

Same filters across different surfaces

ScenarioWhat to do
Same DOM and same URL encoding on two surfaces (for example, search vs. category listing)One facets object may suffice.
Different DOM or different URL encodingAdd a second facets object with its own selectors and onPreSelectedAtURL.

Example configuration

The fragment below is illustrative. Your deployment attaches this as the facets property of the full customer config; surrounding keys are omitted on purpose. Replace selectors, URL parsing, and excluded keys with your storefront's real behaviour.

facets: [
  {
    elemWrapper: ".filter-group",
    triggers: {
      facetElem: ".filter-group .filter-option",
      clearAll: ".filters-toolbar .clear-all",
    },
    selected: { selector: ".filter-group input[type='checkbox']:checked" },
    name: { selector: ".filter-group .filter-heading" },
    value: {
      selector: ".filter-group .option-label",
      getDataFromCB: function (data) {
        return (data || "").replace(/\s*\(.*?\)\s*/g, "").trim();
      },
    },
    facetCB: {
      onPreSelectedAtURL: function () {
        var params = new URLSearchParams(window.location.search);
        var facets = {};
        params.forEach(function (value, key) {
          if (key !== "q" && key !== "page") {
            facets[key] = value.split(",");
          }
        });
        if (Object.keys(facets).length > 0) {
          return { facets: facets };
        }
      },
    },
  },
],

Validation checklist

CheckGoal
Click a filter valueGroup name and option value resolve as intended for that UI.
Another configured surface (for example, mobile)Same behavior for the matching facets array entry.
Open a bookmarked URL with filtersonPreSelectedAtURL returns the expected structure for that URL.
Deselect one valueBehavior matches your agreed test plan for the analytics version in use.
Clear allThe clear-all control behaves as configured.
Range / sliderDrag/commit and pre-filtered URL cases are both covered by the range entry.

Cart Event

Quick view/Product details page

The mandatory pid and variantid (if your catalog contains product variants) payloads are captured from the DOM or from a URL, such as the browser URL, img_url, or href in the product details section. The event is triggered when the respective CTA button is clicked.

Example browser URL: https://www.example.com/product/product_107440/107440_green?sale=clearance

<div class="pdp-page" id="quickLook">
  <div
    class="product-details"
    data-item-id="107440"
    data-variant-id="107440_green"
  >
    <div class="hero-img">
      <img
        src="https://www.example.com/images/product_107440/107440_green.png"
      />
    </div>
    <div id="productInfo">
      <h3>Fresh Blackberry Holland 125 gm</h3>
      <input type="number" class="qty-inputbox" />
      <span class="price">$10.99</span>
      <button class="add-to-wishlist" type="button"></button>
      <button class="add-to-cart" type="button"></button>
    </div>
  </div>
</div>

Cart dropdown/Cart page

The mandatory pid and variantid (if your catalog contains product variants) payloads are captured from the DOM or from a URL, such as the browser URL, img_url, or href in the product details section. The event is triggered when the quantities are modified.

<div class="cart-list-grid">
  <div class="cart-item" data-item-id="107440">
    <a href="https://www.example.com/product/product_107440">
      <img src="https://www.example.com/images/product_107440.png" />
    </a>
    <div id="productInfo">
      <h3>Fresh Blackberry Holland 125 gm</h3>
      <span class="qty">2</span>
      <span class="price">$10.99</span>
      <div class="qty-wrap">
        <span class="quantity-increase"> + </span>
        <input type="text" class="quantity-value" />
        <span class="quantity-decrease"> - </span>
      </div>
    </div>
  </div>

  <div class="cart-item" data-item-id="245102">
    <a href="https://www.example.com/product/product_245102">
      <img src="https://www.example.com/images/product_245102.png" />
    </a>
    <div id="productInfo">
      <h3>Fresh Orange Navel Box</h3>
      <span class="qty">1</span>
      <span class="price">$20.99</span>
      <div class="qty-wrap">
        <span class="quantity-increase"> + </span>
        <input type="text" class="quantity-value" />
        <span class="quantity-decrease"> - </span>
      </div>
    </div>
  </div>
</div>
window.unbxdOrderData = [
  {
    pid: "107440", // Required - Product ID
    variantId: "107440_01", // Required only if your catalog has variants
    qty: "1",
    price: "29.99",
  },
  {
    pid: "245102", // Required - Product ID
    variantId: "245102_red", // Required only if your catalog has variants
    qty: "2",
    price: "10.99",
  },
];

Order Event

It should ideally be tracked on the order-success page. The script below demonstrates how to use the Unbxd.trackMultiple analytics API, which allows one or more products to be passed into the payload to trigger the event.

Payload Details

Attribute NameDatatypeValue to Pass
pidstringUnique ID for the product, to be taken from the Search API response.
variantIdstringVariant ID of the selected product variant.
qtystringQuantity being added by the user.
pricestringUnit price of the product.

Refer to the following code snippet.

 <script type="text/javascript">
       var payload = [
       {
           pid: '{{uniqueId-of-the-product}}',
           variantId: '{{variantId-of-selected-variant}}',
           qty: '{{quantity-selected}}',
           price: '{{unit-price-for-product}}'
       },
       {
           pid: '{{uniqueId-of-the-product}}',
           variantId: '{{variantId-of-selected-variant}}',
           qty: '{{quantity-selected}}',
           price: '{{unit-price-for-product}}'
       }]


       if(Unbxd && typeof Unbxd.track === 'function') {
           Unbxd.trackMultiple('order', payload)
       } else {
           console.error('Pulse SDK is missing or initialized out of sequence; ensure it is fully loaded before using it.')
       }
   </script>