Skip to main content

Insert the Shopify Search Box on Your Jekyll Site Using Lunr.js

Last updated: November 28 2024

Written and researched by experts at Avada Learn more about our methodology

If your site is built on Jekyll and you’re using Shopify as your e-commerce platform, adding a powerful and efficient search box is a smart move, as it makes it easier for visitors to find the content they want. With Lunr.js, you can create an on-site search feature that operates directly in the browser without relying on external services. 

In this guide, we’ll show you how to insert a search box using Shopify and Lunr.js, allowing you to streamline your site’s search functionality and provide a seamless experience for your audience.

How to insert the search box on your Jekyll site using lunr.js

What is Lunr.js?

Lunr.js could be an excellent choice for you if you want to build the search. However, first, what is Lunr.js?

Lunr.js is known as a small, full-text library for use in the browser. It indexes JSON documents and brings along a simple search interface for retrieving documents that can match text queries the most. The search usually works in the following steps:

  • Get the search term sent as a GET parameter to search.html.
  • search.html then reads the GET parameter and searches through JSON containing the searchable content.
  • search.html shows a search result list.

To get started, we will generate /js/search.js to hold our search JavaScript and get junr.js installed to /js/lunr.min.js.

How to insert the Shopify search box on your Jekyll site using lunr.js?

Step 1: Create search.html

In the first step, we need to generate /search.html. This file contains a search box, a placeholder for showing results, a JSON output of all the content we want to search on. All JavaScript libraries are also included:

---
layout: search
---
<form action="/search.html" method="get">
  <label for="search-box">Search</label>
  <input type="text" id="search-box" name="query">
  <input type="submit" value="search">
</form>

<ul id="search-results"></ul>

<script>
  window.store = {
    {% for post in site.posts %}
      "{{ post.url | slugify }}": {
        "title": "{{ post.title | xml_escape }}",
        "author": "{{ post.author | xml_escape }}",
        "category": "{{ post.category | xml_escape }}",
        "content": {{ post.content | strip_html | strip_newlines | jsonify }},
        "url": "{{ post.url | xml_escape }}"
      }
      {% unless forloop.last %},{% endunless %}
    {% endfor %}
  };
</script>
<script src="/js/lunr.min.js"></script>
<script src="/js/search.js"></script>

Step 2: Write JavaScript

Move to the next step, to have /js/search.js perform 3 tasks, we need to write the JavaScript. Those three tasks include:

  • Get the search term
  • Perform the search
  • Display the results

We are going over the sections of code. Then, we will see the whole file at the end.

Step 3: Get the search term

It is not really easy for JavaScript to instantly read GET parameters so we need to add a getParameterByName function to get things done. Please do not be worried if you don’t get how this function works, it is merely manipulating the query string to divide it into variables.

Now you are able to employ getParameterByName to get the search term:

...
function getQueryVariable(variable) {
  var query = window.location.search.substring(1);
  var vars = query.split('&');

  for (var i = 0; i < vars.length; i++) {
    var pair = vars[i].split('=');

    if (pair[0] === variable) {
      return decodeURIComponent(pair[1].replace(/\+/g, '%20'));
    }
  }
}

var searchTerm = getQueryVariable('query');
...

Just in case there is a search term, we need to set up and adjust lunr.js. This job involves telling Lunr about the fields that interest you and adding the search data from the JSON. You can perform the search once this is already set up:

...
if (searchTerm) {
  document.getElementById('search-box').setAttribute("value", searchTerm);

  // Initalize lunr with the fields it will be searching on. I've given title
  // a boost of 10 to indicate matches on this field are more important.
  var idx = lunr(function () {
    this.field('id');
    this.field('title', { boost: 10 });
    this.field('author');
    this.field('category');
    this.field('content');
  });

  for (var key in window.store) { // Add the data to lunr
    idx.add({
      'id': key,
      'title': window.store[key].title,
      'author': window.store[key].author,
      'category': window.store[key].category,
      'content': window.store[key].content
    });

    var results = idx.search(searchTerm); // Get lunr to perform a search
    displaySearchResults(results, window.store); // We'll write this in the next section
  }
}
...

Step 5: Display the result

Now you are allowed to show the results in your list when already having them.

...
function displaySearchResults(results, store) {
  var searchResults = document.getElementById('search-results');

  if (results.length) { // Are there any results?
    var appendString = '';

    for (var i = 0; i < results.length; i++) {  // Iterate over the results
      var item = store[results[i].ref];
      appendString += '<li><a href="' + item.url + '"><h3>' + item.title + '</h3></a>';
      appendString += '<p>' + item.content.substring(0, 150) + '...</p></li>';
    }

    searchResults.innerHTML = appendString;
  } else {
    searchResults.innerHTML = '<li>No results found</li>';
  }
}
...

When putting it all together, you will have a working search:

(function() {
  function displaySearchResults(results, store) {
    var searchResults = document.getElementById('search-results');

    if (results.length) { // Are there any results?
      var appendString = '';

      for (var i = 0; i < results.length; i++) {  // Iterate over the results
        var item = store[results[i].ref];
        appendString += '<li><a href="' + item.url + '"><h3>' + item.title + '</h3></a>';
        appendString += '<p>' + item.content.substring(0, 150) + '...</p></li>';
      }

      searchResults.innerHTML = appendString;
    } else {
      searchResults.innerHTML = '<li>No results found</li>';
    }
  }

  function getQueryVariable(variable) {
    var query = window.location.search.substring(1);
    var vars = query.split('&');

    for (var i = 0; i < vars.length; i++) {
      var pair = vars[i].split('=');

      if (pair[0] === variable) {
        return decodeURIComponent(pair[1].replace(/\+/g, '%20'));
      }
    }
  }

  var searchTerm = getQueryVariable('query');

  if (searchTerm) {
    document.getElementById('search-box').setAttribute("value", searchTerm);

    // Initalize lunr with the fields it will be searching on. I've given title
    // a boost of 10 to indicate matches on this field are more important.
    var idx = lunr(function () {
      this.field('id');
      this.field('title', { boost: 10 });
      this.field('author');
      this.field('category');
      this.field('content');
    });

    for (var key in window.store) { // Add the data to lunr
      idx.add({
        'id': key,
        'title': window.store[key].title,
        'author': window.store[key].author,
        'category': window.store[key].category,
        'content': window.store[key].content
      });

      var results = idx.search(searchTerm); // Get lunr to perform a search
      displaySearchResults(results, window.store); // We'll write this in the next section
    }
  }
})();

Step 6: Search field

Now only by adding a form that submits to /search.html can you be able to insert a search box any places on your store site. You will need to prefix the action with `` when you are using a base url on GitHub pages.

...
<form action="/search.html" method="get">
  <label for="search-box">Search</label>
  <input type="text" id="search-box" name="query">
  <input type="submit" value="search">
</form>
...

Bottom Line

By incorporating Lunr.js into your Shopify Jekyll site, you can greatly enhance your website's usability by offering a fast, responsive search experience. This step-by-step guide ensures that adding a search box is straightforward so you can help visitors easily navigate through your content, whether it's blog posts or product pages.

Sam
linkedin
Sam Nguyen is the CEO and founder of Avada Commerce, an e-commerce solution provider headquartered in Singapore. He is an expert on the Shopify e-commerce platform for online stores and retail point-of-sale systems. Sam loves talking about e-commerce and he aims to help over a million online businesses grow and thrive.