Templating

Templating can be used to define a custom HTML structure for your search suggestions and results.

This allows for virtually seamless integration of the Site Search 360 JS plugin into your site's theme and makes the layout customization even more flexible.

Defining custom templates will only override the search suggestion/result markup without having an impact on most of the plugin settings (e.g. grid layout or tabbed navigation).

Configuration

To configure templating you need to add a configuration object to the suggestions (suggestTemplate property) or results (resultTemplate property) block of your ss360Config.

The configuration object for search suggestions and search results has the same structure and looks as follows:

  • template is the HTML template string.

  • preRenderCallback is a callback called before the result is built.

  • templateBuiltCallback is a callback called after the result HTML is built but before it was converted to a DOM Node.

  • postRenderCallback is a callback after the DOM Node has been created.

  • variableReplacementPattern is a regex pattern, everything matching this pattern will be replaced with an empty string before a DOM node is created.

  • dataPointDefaults is an object mapping of data point names to default values. Every search result missing a data point given in this property will be assigned a new data point containing the default value (e.g. {isNew: false}).

Check the Callbacks section for more information.

Please note: to use custom search result templates, you need to run at least version 12.3.1 of the plugin, and to use custom search suggestion templates - version 13.1.1 and later.

Templating rules

To fill in your HTML template with content, you can use syntax similar to the Mustache templating engine. The render context is always a single search result/suggestion with the following properties:

  • name - the result title.

  • image - the result image url.

  • link - the result url.

  • content - the search result snippet (this property is not set for search suggestions).

  • images - an array containing the URLs of the alternative images for the result. Each element has the following structure: { "type": "alternative", "url": "https://link-to-the-result-image.jpg" }. The first element, images[0].url, is (normally) the same as image.

  • dataPoints - an array of data points, each data point has the following structure: {"key": "Data Point Name", "value": "Data Point Value", "show": true}

  • dataPointHash - an object mapping data point keys (camelcase) to an array of data point values.

  • highlightedName - the result title with highlighted query terms. This property is only available for search suggestions. The highlighted query terms can be styled by using the unibox__highlight class name (e.g. .unibox__highlight { font-weight: 700 }.

  • variants - an array of all available product variants (ecommerce only). The name , image, link, content, images, and dataPoints properties are available within a single variant object.

  • isResultTypeCustom - a boolean indicating whether a single result is a custom result (provides custom html that should be rendered).

To inject content into the HTML template you can use the {{variableName}} rule. This will lead to all special HTML characters to be escaped. If you do want to inject the HTML content into your template without escaping special characters, you can use the {{{variableName}}} rule.

Undefined properties will be replaced with an empty string.

<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>

If the target property is an array, you can use loops (the {{#array}}{{item}}{{/array}} rule) to iterate over every item, which will become the new render context (use @value to target an element of a string array). This can be useful for displaying all data point values:

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

To render a specific block under a certain condition, you can use the {{#condition}}I am true{{/condition}}> rule. The condition evaluates to false if it is false, undefined, null, or an empty array. To invert conditions, you can use the {{!#condition}}I am false{{/condition}} rule.

Conditional statements can also be inlined directly into an HTML tag: <span class="{{# condition : "condition__true" #}}">Test</span>, or<span class="{{!# condition : "condition__false" #!}}">Test</span>

<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>

To inject content from an array you can directly query a specific index {{array[0]}} (0 based), specific values from object properties can be injected by using {{object.myProperty}}. Both can also be combined to query an array value of an object, e.g. {{dataPointHash.price[0]}}.

Callbacks

You can use one of the three available callbacks to customize your templates even further.

The preRenderCallback is called before the template string is processed and it receives three arguments:

  • suggest - (Object) the full search result/suggestion object, can be modified to set custom properties for the content interpolation.

  • globalStore - (Object) the store that's shared across all search results/suggestions, can be used to set global variables, e.g. result counter.

  • contentGroup - (String) the content group name.

The templateBuiltCallback is called after the template is built (all templating rules were applied). The callback receives four arguments:

  • template - (String) the string template.

  • suggest - (Object) the full search result/suggestion object.

  • globalStore - (Object) the store that's shared across all search results/suggestions, can be used to set global variables, e.g. result counter.

  • contentGroup - (String) the content group name.

This can be useful to do more complex replacements on the template string:

The postRenderCallback is called after the DOM node was created. It receives 4 arguments:

  • node - (Node) the DOM node.

  • suggest - (Object) the full search result/suggestion object.

  • globalStore - (Object) the store that's shared across all search results/suggestions, can be used to set global variables, e.g. result counter.

  • contentGroup - (String) the content group name.

This can be useful to bind custom events on search results/suggestions:

Tips & tricks

The default highlighting of search suggestions (on hover, or keyboard select) won't work for custom templates.

Add the class unibox__highlight-container to the content you want to highlight on selection and it will automatically receive a grey background when selected.

Alternatively, you can use custom CSS to target a selected suggestion by using the following CSS selector: .unibox__selectable--active, .unibox__selectable:hover.

As the ss360Config needs to be a valid JavaScript object, long templates might be difficult to modify. If you don't use string literals and a JS compiler to ensure cross-browser compatibility, you can also put the full template into a <template> tag and read it directly from the DOM:

<!-- ... -->
<template id="ss360-result-template" style="display: none;">
   <div class="my-search-result">
      <!-- Template Code -->
   </div>
</template>
<script>
var ss360Config = {
   /* ... configuration ... */
   results: {
      /* ... result configuration ...*/
      resultTemplate: {
         template: document.getElementById("ss360-result-template").innerHTML
      }
   }
}
</script>
<!-- ... -->

Example

Suggestions-templating works almost exactly in the same way as for search results.

In this example below are shown how results and suggestions templates can be implemented:

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