We have a new support portal! Visit the updated version here: support.doofinder.com

In this article, you will learn two ways in which you can improve your Doofinder layer functionality.

 📌 Note: You will need some programming knowledge to be able to use this article to customise the layer further.

Doofinder Script has many configuration parameters to modify the default behaviour and events and related callbacks that you can customise.

Doofinder Layer triggers some events in the following situations:

  • loaded: when the layer is in place, and account options have been loaded successfully.
  • resultsReceived: When, after a search action, results have been received by the layer.
  • hit: When a result is clicked inside the results list shown.

Additionally, you can attach your own handlers, the so-called callbacks.

Callbacks in Script

Once set in your script, the callbacks should be as follows:

dfClassicLayers = [{
     // your previous script options
     callbacks: {
         resultsReceived: function(res){
             console.log(res);
         },
         hit: function(event, url){
             console.log(url);
         },
         loaded: function(config){
             console.log(config);
         }
     }
 }]

As you can see, once you add your own functions (callbacks), your layer modification possibilities increase substantially.

Here are two examples you may want to consider for your layer modification:

Example #1: Adding Extra Content to the Results Layer

Suppose you want your customers to see the products you sell and see links to other products you think they could be interested in. You don’t want to mix them all as they could get confused. Besides, page links don’t have the same fields as products, and you want to give your layer a nice look.

Solution:

This automatically means that you will require two feeds to display: a product feed and an articles’ feed. Here’s how you can put the two together:

Using Doofinder Library:

Here you will make use of the Doofinder JavaScript Library and callbacks.

📌 Note: Doofinder layer already uses this library, so it is already there for you.

This is the basic code required to make this idea start working. First, you need to define a custom layer template so you can modify it as you prefer. This would be a Mustache template to be put inside your page as follows:

<script type="text/x-mustache-template" id="custom-layer-template">
  <div class="df-classic df-hidden" id="{{ mainContainerId }}">
    <div class="df-classic__content df-layer__content">
      <div class="df-aside">
        <div class="df-aside__header">
          <a class="df-icon df-icon--close" href="#" data-role="close">
            <svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
                <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
                <path d="M0 0h24v24H0z" fill="none"/>
            </svg>
          </a>
        </div>
        <div class="df-aside__content">
          <div id="df-aside__content__{{ mainContainerId }}"></div>
        </div>
      </div>
      <div class="df-main">
        {{#showHeader}}
          <div class="df-header" id="df-header__{{ mainContainerId }}"></div>
        {{/showHeader}}
        <div class="df-results" id="df-results__{{ mainContainerId }}">
          <div id="df-results__content__{{ mainContainerId }}" class="df-results__content"></div>
        </div>
        <!-- EXTRA CONTENT STARTS -->
        <div id="df-extra-content"></div>
        <!-- EXTRA CONTENT ENDS -->
        <div id="doofinderLogo">
          <a href="https://www.doofinder.com?mktcod=REF1" target="_blank">
            Powered&nbsp;by&nbsp;<i class="doofinder-logo-small">Doofinder</i>
          </a>
        </div>
      </div>
   </div>
  </div>
</script>

📌 Note: In the above template, there is an additional empty div #df-extra-content included for the purpose of this example. That is where you will insert the results list from the second searchEngine.

You will also need to alert the Doofinder Layer to use this custom template instead of the default one. This is done through this other layer option:

dfClassicLayers = [{
     // your previous script options
     display:{
         template: document.getElementById('custom-layer-template')
     }
 }]

Now that the layer template is in place add your custom callback to fill it. The event selected to include this function will be loaded as it will be executed once Doofinder is properly set. Include it in your layer options as follows:

dfClassicLayers = [{
     // your previous script options
     display:{
         template: document.getElementById('custom-layer-template').innerHTML
     }
     callbacks:{
         loaded: function(config){
                  // A new library client, similar to the one already living in your layer
                  var second_client = new doofinder.core.Client('theHashidOfSecondSerchEngine', config.layerOptions.zone);
                  // A new place to put results on. The empty container we set inside the template
                  var second_resultsWidget = new doofinder.core.widgets.ScrollResults('#df-extra-content');
                  // Another Controller to rule the new elements.
                  var second_controller = new doofinder.core.Controller(second_client, [config.layer.queryInputWidget, second_resultsWidget]);
                  }
     }
 }]

📌 Note: The second_controller is «listening» to the same input as the initial layer, so it will react to the same search words but show results in a different place.

If you do some test search, you will find that the second SearchEngine is attached below the first ones. Now go and play a little more to make it look prettier. Keep the layer reference close; it could be useful.

Example #2: Displaying a custom message when a search is not accurate.

To obtain the best possible search results, Doofinder tries several modes of searching. One of those is the «fuzzy» searching. This is a «last resource» searching mode that Doofinder tries when none of the standard search modes is successful. The «fuzzy» search mode tries to find «close enough» results, rather than perfect matches, and you may want to let the user know – when this is the chosen search mode by Doofinder – that search results are more «diffuse».

Solution

You would need to accomplish two things:

  • Know when Doofinder’s search has been done in fuzzy mode: That information can be obtained from Doofinder’s server response.
  • When fuzzy mode has been used, display a message inside the layer saying the search is inaccurate. You probably want a custom template for this.

Let’s start by creating a custom results template with a placeholder for our custom message.

<script type="text/x-mustache-template" id="custom-results-template">
{{#is_first}}
  {{#banner}}
    <div class="df-banner">
      <a {{#blank}}target="_blank"{{/blank}} href="{{link}}" data-role="banner" data-banner="{{id}}">
        <img src="{{#remove-protocol}}{{image}}{{/remove-protocol}}">
      </a>
    </div>
  {{/banner}}
{{/is_first}}
{{#total}}
  <p id="df-query-name" hidden>The results yielded for &#34;<span id="df-query"></span>&#34; are not very accurate</p>
  {{#results}}
    <div class="df-card" data-role="result">
      <a class="df-card__main" href="{{#url-params}}{{{link}}}{{/url-params}}" data-role="result-link" data-dfid="{{dfid}}">
        {{#image_link}}
          <figure class="df-card__image">
            <img src="{{#remove-protocol}}{{image_link}}{{/remove-protocol}}" alt="{{title}}">
          </figure>
        {{/image_link}}
        <div class="df-card__content">
          <div class="df-card__title">{{title}}</div>
          <div class="df-card__description">{{{description}}}</div>
          {{#price}}
          <div class="df-card__pricing">
           <span class="df-card__price {{#sale_price}}df-card__price--old{{/sale_price}}">
              {{#format-currency}}{{price}}{{/format-currency}}
            </span>
            {{#sale_price}}
              <span class="df-card__price df-card__price--new">
                {{#format-currency}}{{sale_price}}{{/format-currency}}
              </span>
            {{/sale_price}}
          </div>
          {{/price}}
          {{#df_rating}}
          <div>
            <div class="df-rating" title="{{df_rating}}">
              <div class="df-rating__value" style="width: {{#rating-percent}}{{df_rating}}{{/rating-percent}}">
                <i>★</i><i>★</i><i>★</i><i>★</i><i>★</i>
              </div>
              <div class="df-rating__placeholder">
                <i>★</i><i>★</i><i>★</i><i>★</i><i>★</i>
              </div>
            </div>
          </div>
         {{/df_rating}}
        </div>
      </a>
    </div>
  {{/results}}
{{/total}}
{{^total}}
  {{#noResultsHTML}}{{{noResultsHTML}}}{{/noResultsHTML}}
  {{^noResultsHTML}}
    <p class="df-no-results">{{#translate}}Sorry, no results found.{{/translate}}</p>
  {{/noResultsHTML}}
{{/total}}
</script>

📌 Note: You can see the placeholder for the message at the p#df-query-name CSS selector. That element is hidden by default.

As with the previous example, you need to tell Doofinder to use this custom results layer instead of the default results layer.

dfClassicLayers = [{
   // your previous script options
  display: {
    // some display options
    results: {
      template: document.getElementById('custom-results-template')
    }
  }
}]

Then you have to make that placeholder element visible whenever the search results are from a «fuzzy» query. For that, you will use the resultsReceived callback, which is called every time search results are received, and the handler is provided with a response object with details about the obtained search results.

dfClassicLayers = [{
     // your previous script options
     display:{
        results: {
          template: document.getElementById('custom-results-template').innerHTML
        }
     }
     callbacks:{
         resultsReceived: function(response){
             // are there results??
              if (response.total > 0) {
                  // is this a "fuzzy" query??
                  if (response.query_name === "fuzzy") { // yes: show the message!!!
                      document.getElementById("df-query").innerHTML = response.query;
                      document.getElementById("df-query-name").removeAttribute("hidden");
                  }
                  else { // nope: hide it.
                      document.getElementById("df-query-name").setAttribute("hidden", "");
                  }
              }
         }
     }
 }]

This is just one way of showing the message, and you can do whatever you want with your DOM structure. The point here is that the callback is called each time results are received, and response info is provided to it.

Should you encounter any problems, please contact support@doofinder.com.

Last Updated: August 2021