Skip to main content

Templating in Zoovu Search

Option 2: Using templates for custom result cards

If the default card structure does not meet your needs, you can fully customize the search result card layout using templates.

How templating works:

  1. Choose the most complex product card from your site as a reference.
  2. Format the HTML and replace specific data (e.g., product title, price) with placeholders.
  3. Use template variables to dynamically insert data.

Templating lets you create a custom HTML structure for search suggestions and results. This helps you match the Zoovu Search JS plugin to your site's design while giving you more control over the layout.

Using custom templates only modifies the markup of search results and suggestions. Other settings, such as grid layout and tabbed navigation, remain unchanged.

Configuring templating

To enable templating, add a configuration object to the block of your zoovuSearchConfig:

  • suggestTemplate (for search suggestions)
  • resultTemplate (for search results)

Version requirements:

  • Search result templates require Zoovu Search plugin v12.3.1+.
  • Search suggestion templates require v13.1.1+.

Configuration object structure

PropertyDescription
templateThe HTML template string.
preRenderCallbackCalled before the result is built.
templateBuiltCallbackCalled after the result is built but before it's converted to a DOM node.
postRenderCallbackCalled after the DOM node is created.
variableReplacementPatternRegex pattern to remove matching text before creating a DOM node.
dataPointDefaultsDefines default values for missing data points. Example: {isNew: false}.

Templating rules

Zoovu's templating syntax is similar to the Mustache templating engine. Each search result or suggestion includes properties you can use in the template:

PropertyDescription
nameThe result title.
imageThe result image URL.
linkThe result URL.
contentThe result snippet (only for search results).
imagesAlternative images (array of { "type": "alternative", "url": "<image_url>" }).
dataPointsAn array of data points: { "key": "Data Point Name", "value": "Data Point Value", "show": true }.
dataPointHashA mapping of data point keys to values.
attributesA mapping of concept identifiers to values (e-commerce only, v15 and later). All spaces in concept identifiers are replaced with an underscore.
highlightedNameThe result title with highlighted query terms (for search suggestions).
variantsAn array of product variants (e-commerce only).
isResultTypeCustomBoolean indicating if the result has custom HTML.

Injecting content:

  • Use {{variableName}} to insert content (HTML characters will be escaped).
  • Use {{{variableName}}} to insert raw HTML.

Example:

<div class="result">
<h3 class="result__title">{{name}}</h3>
<a class="result__link" href="{{link}}">See more</a>
<p class="result__snippet">{{{content}}}</p>
</div>

Use {{#array}}...{{/array}} to loop through an array.

Example: Displaying all data point values

<ul class="result__datapoints">
{{#dataPoints}}
<li class="result__datapoint"><strong>{{key}}:</strong> {{value}}</li>
{{/dataPoints}}
</ul>

Conditional rendering:

Show content only if a condition is met:

{{#condition}}I am true{{/condition}}

Show content if a condition is false:

{{!#condition}}I am false{{/condition}}

Example:

<div class="result {{#image : "result--has-img" #}}">
<h2>{{name}}</h2>
<p>
{{#link}}
<a href="{{link}}">Here you go</a>
{{/link}}
{{!#link}}
Sorry, we can't take you to the search result.
{{/link}}
</p>
</div>

Accessing specific array elements

  • Use {{array[0]}} to get the first item.
  • Use {{object.property}} to get a property from an object.
  • Combine both to query an array value of an object: {{dataPointHash.price[0]}} or {{attributes.PRICE[0]}}.

Callbacks

Callbacks let you customize templates before, during, and after rendering.

  1. preRenderCallback - Called before the template is processed.

Arguments:

  • suggest (Object): The full search result/suggestion.
  • globalStore (Object): Shared storage for all results.
  • contentGroup (String): The content group name.
  1. templateBuiltCallback - Called after applying templating rules but before creating a DOM node.

Arguments:

  • template (String): The processed template string.
  • suggest, globalStore, contentGroup: Same as preRenderCallback.

Example: Modifying template text

function(template, suggest) {
return template.replace("Old Text", "New Text");
}
  1. postRenderCallback - Called after creating the DOM node.

Arguments:

  • node (Node): The generated DOM node.
  • suggest, globalStore, contentGroup: Same as above.

Example: Adding an event listener

function(node) {
node.addEventListener("click", () => {
console.log("Search result clicked!");
});
}

Tips & tricks

Highlighting custom templates

Default hover/keyboard selection highlighting won’t work. Add unibox__highlight-container to apply a grey background when selected.

Or use custom CSS:

.unibox__selectable--active, .unibox__selectable:hover {
background-color: lightgray;
}

Using a <template> tag for large templates

Instead of storing large templates in JavaScript, use an HTML <template>:

<template id="zoovu-result-template">
<div class="my-search-result">
<!-- Template Code -->
</div>
</template>

<script>
var zoovuSearchConfig = {
results: {
resultTemplate: {
template: document.getElementById("zoovu-result-template").innerHTML
}
}
}
</script>

Example: Implementing result and suggestion templates

var zoovuSearchConfig = {
results: {
resultTemplate: {
template: '<article class="my-search-result"><h2>{{name}}</h2></article>'
}
},
suggestions: {
suggestTemplate: {
template: '<article class="my-search-suggestion"><h3>{{name}}</h3></article>'
}
}
}