Search by Algolia
How personalization boosts customer engagement
e-commerce

How personalization boosts customer engagement

You land on your favorite retailer’s website, where everything seems to be attractively arranged just for you. Your favorite ...

Jon Silvers

Director, Digital Marketing

What is retail analytics and how can it inform your data-driven ecommerce merchandising strategy?
e-commerce

What is retail analytics and how can it inform your data-driven ecommerce merchandising strategy?

There is such tremendous activity both on and off of retailer websites today that it would be impossible to make ...

Catherine Dee

Search and Discovery writer

8 ways to use merchandising data to boost your online store ROI
e-commerce

8 ways to use merchandising data to boost your online store ROI

New year, new goals. Sounds positive, but looking at your sales data, your revenue and profit aren’t so hot ...

John Stewart

VP, Corporate Communications and Brand

Algolia DocSearch + Astro Starlight
engineering

Algolia DocSearch + Astro Starlight

What is Astro Starlight? If you're building a documentation site, your content needs to be easy to write and ...

Jaden Baptista

Technical Writer

What role does AI play in recommendation systems and engines?
ai

What role does AI play in recommendation systems and engines?

You put that in your cart. How about this cool thing to go with it? You liked that? Here are ...

Catherine Dee

Search and Discovery writer

How AI can help improve your user experience
ux

How AI can help improve your user experience

They say you get one chance to make a great first impression. With visual design on ecommerce web pages, this ...

Jon Silvers

Director, Digital Marketing

Keeping your Algolia search index up to date
product

Keeping your Algolia search index up to date

When creating your initial Algolia index, you may seed the index with an initial set of data. This is convenient ...

Jaden Baptista

Technical Writer

Merchandising in the AI era
e-commerce

Merchandising in the AI era

For merchandisers, every website visit is an opportunity to promote products to potential buyers. In the era of AI, incorporating ...

Tariq Khan

Director of Content Marketing

Debunking the most common AI myths
ai

Debunking the most common AI myths

ARTIFICIAL INTELLIGENCE CAN’T BE TRUSTED, shouts the headline on your social media newsfeed. Is that really true, or is ...

Vincent Caruana

Senior Digital Marketing Manager, SEO

How AI can benefit the retail industry
ai

How AI can benefit the retail industry

Artificial intelligence is on a roll. It’s strengthening healthcare diagnostics, taking on office grunt work, helping banks combat fraud ...

Catherine Dee

Search and Discovery writer

How ecommerce AI is reshaping business
e-commerce

How ecommerce AI is reshaping business

Like other modern phenomena such as social media, artificial intelligence has landed on the ecommerce industry scene with a giant ...

Vincent Caruana

Senior Digital Marketing Manager, SEO

AI-driven smart merchandising: what it is and why your ecommerce store needs it
ai

AI-driven smart merchandising: what it is and why your ecommerce store needs it

Do you dream of having your own personal online shopper? Someone familiar and fun who pops up every time you ...

Catherine Dee

Search and Discovery writer

NRF 2024: A cocktail of inspiration and innovation
e-commerce

NRF 2024: A cocktail of inspiration and innovation

Retail’s big show, NRF 2024, once again brought together a wide spectrum of practitioners focused on innovation and transformation ...

Reshma Iyer

Director of Product Marketing, Ecommerce

How AI-powered personalization is transforming the user and customer experience
ai

How AI-powered personalization is transforming the user and customer experience

In a world of so many overwhelming choices for consumers, how can you best engage with the shoppers who visit ...

Vincent Caruana

Senior Digital Marketing Manager, SEO

Unveiling the future: Algolia’s AI revolution at NRF Retail Big Show
algolia

Unveiling the future: Algolia’s AI revolution at NRF Retail Big Show

Get ready for an exhilarating journey into the future of retail as Algolia takes center stage at the NRF Retail ...

John Stewart

VP Corporate Marketing

How to master personalization with AI
ai

How to master personalization with AI

Picture ecommerce in its early days: businesses were just beginning to discover the power of personalized marketing. They’d divide ...

Ciprian Borodescu

AI Product Manager | On a mission to help people succeed through the use of AI

5 best practices for nailing the ecommerce virtual assistant user experience
ai

5 best practices for nailing the ecommerce virtual assistant user experience

“Hello there, how can I help you today?”, asks the virtual shopping assistant in the lower right-hand corner ...

Vincent Caruana

Senior Digital Marketing Manager, SEO

Add InstantSearch and Autocomplete to your search experience in just 5 minutes
product

Add InstantSearch and Autocomplete to your search experience in just 5 minutes

A good starting point for building a comprehensive search experience is a straightforward app template. When crafting your application’s ...

Imogen Lovera

Senior Product Manager

Looking for something?

facebookfacebooklinkedinlinkedintwittertwittermailmail

Progressive enhancement is an important topic when creating any web site or app. What happens when a user’s browser isn’t able to handle any JavaScript or the specific JavaScript you’re using? If you’re front end fails, you need a fallback to allow basic functionality to keep working.

What’s so hard about that?

When you’re working on the Jamstack, that can be much harder than in traditional stacks. Since the Jamstack is dedicated to serving HTML from a CDN, we don’t have a traditional server – only static files and serverless functions. Because of that, we might find ourselves rewriting our rendering code for both the frontend and the server. Three years and a redesign go by and suddenly you’re in a time machine looking at search results in last year’s design.

With 11ty’s new Serverless package and Netlify functions, we can quickly start from the server. From there, we can progressively enhance the experience using libraries like InstantSearch.js.

What is 11ty Serverless?

11ty is a static site generator written in Node.js. It offers multiple template languages and multiple methods for ingesting data. It’s built with flexibility in mind.

Historically, it does all of its work during the build process and generates HTML that can be stored on a CDN. This creates speedy websites that work incredibly well on the Jamstack.

For any dynamic content, it has relied on front-end JavaScript to fetch data. This works in many situations, but provides no clear path toward progressive enhancement.

If your front-end code fails, the dynamic aspects of your site will fail with it. With the upcoming 1.0 release of 11ty, that won’t be a concern any more. 11ty will come bundled with the optional 11ty Serverless plugin. This will allow a developer to specify routes that can handle user input. That input can come from query parameters or from the URL structure itself.

What we’re building

Screenshot showcasing the final serverless search page

In this demo, we’ll take a very simple 11ty site and add a dynamic search route. That search route will use 11ty and a template filter to create HTML in a serverless function – all from within the 11ty code we’re used to. This will be used for the “fallback” in our progressive enhancement. While we won’t go into building out a JavaScript-based search in this demo, creating a real-time search with InstantSearch.js is a great basis for a solid user experience.

How we’ll build this:

1. Install the plugin and configure the serverless function
2. Create the search page
3. Create a getResults template filter to query our Algolia Index

Setup

We’ll start from a basic 11ty template with just a little HTML to get us going.

To get started, clone this repository and install the dependencies (11ty 1.0 and dotenv).

Want to see the finished product? Check out the final branch of the repository or see this demo site.

npm install && npm start

The structure of our project follows the basic structure of an 11ty site. The individual pages are in the root of the project – currently, only the index.html file. The templates are in the _includes directory. The configuration file is .eleventy.js in the root. The site templates are also relatively simplistic: a base template that includes a header and footer.

Once the install is done, we’ll have a working 11ty site running locally. It’s not very interesting yet, just an index page with a little HTML. Let’s add a search page to bring in some content.

Install and configure the 11ty Serverless plugin

In its latest 1.0 “canary” versions, 11ty ships with the plugin 11ty Serverless. This helps generate the serverless function we’ll need to run 11ty on demand.

To install it in our project, we need to update the .eleventy.js configuration file.

require("dotenv").config();  
const { EleventyServerlessBundlerPlugin } = require("@11ty/eleventy");  

module.exports = function(eleventyConfig) {  
    // Configuration rules  
    eleventyConfig.addPlugin(EleventyServerlessBundlerPlugin, {  
       name: "search", // The serverless function name for the permalink object 
       functionsDir: "./netlify/functions/",  
     });  
};

Since 11ty is creating files in our project that we don’t want to track in version control, update your .gitignore with the following items:

netlify/functions/search/**  
!netlify/functions/search/index.js

When we rerun npm start, 11ty will now create a serverless function – and all necessary bundle files – in the directory specified by functionsDir with a name specified by the name property.

For most uses, you won’t modify these files. The plugin generates the index.js file, which can be edited for more advanced use cases. 11ty will override the other files in this directory on each run.

Create a page to use the serverless function

Now that 11ty has created the function, we can add a page to use it.

Start by creating a new file in the root of the project named search.html. In the file, we can configure the page’s data with frontmatter.

---  
layout: "base.html"  
title: Search Page  
permalink:  
 search: /search/  
---

The layout variable will indicate which template in _includes to use for display. The title variable will display in the HTML’s

The permalink object is where we specify what the final URL for this page should be.

If you’re familiar with 11ty, you may remember the permalink variable being a string. You can still use a string for simple use cases, but for Serverless, it will be an object. The object’s keys will be the name we specified in the configuration for our serverless function.

You can also specify different serverless functions to run based on the URL in this way. If you want the page generated at build time AND request time, you can specify a build key for the permalink, as well.

Once added, the page will render at /search/. It doesn’t have any content yet other than the header and footer. Let’s grab some dynamic content from query parameters.

---
layout: "base.html"
title: Search Page
permalink:
  search: /search/
---

<h2 class="is-size-3 mb-3">This list is built at request from the query "{{ eleventy.serverless.query.query }}"</h2>

This will create a headline that will look at the query parameters of our route and insert whatever value the query parameter contains.

If you visit the page with ?query=11ty at the end of the URL, the string 11ty will appear in the headline.

So, how do we take that query and get results from Algolia?

Create a getResults template filter

To get the data we need to render our template, we need to create a template filter. The filter will accept the query string from the serverless page, run a query against an Algolia Index, and return an array of articles to our search page.

Before we dive into the code, you’ll need to have an Algolia app and a few environment variables. If you already have an Algolia Index, feel free to use that. We’ll be using an Index that has blog posts with titles, descriptions, and URLs. If you don’t have an Algolia Index, create an account and app, and use this data to manually create your first Index.

[
    {
        "title": "Creating an omnibar with Autocomplete",
        "description": "In this tutorial, we’ll walk through setting up Autocomplete to fire interactions with JavaScript. Specifically, we’ll build an omnibar to toggle light and dark mode for our website. An omnibar is a search field that has both search and actions that can be taken. A strong example of this is the Chrome or Firefox search and URL bar.",
        "url": "https://www.algolia.com/blog/engineering/creating-an-omnibar-with-autocomplete/"
    },
    {
        "title": "Building a Store Locator in React using Algolia, Mapbox, and Twilio – Part 1",
        "description": "These days, ecommerce shoppers expect convenience and want the physical and online worlds to mesh allowing them to conduct their business on whichever channel they want. For example, users may choose to:",
        "url": "https://www.algolia.com/blog/engineering/building-a-store-locator-in-react-using-algolia-mapbox-and-twilio-part-1/"
    },
    {
        "title": "Introducing Algolia Recommend: The next best way for developers to increase revenue",
        "description": "Now, with the introduction of Algolia Recommend, Algolia further enables developers to unleash the component of the experience that drives the remaining part of the product discovery experience: product recommendations. ",
        "url": "https://www.algolia.com/blog/product/introducing-algolia-recommend-the-next-best-way-for-developers-to-increase-revenue/"
    }
]

Once you have an Index, create a .env file and add the following variables:

# The app id
ALGOLIA_APP = ""
# The search-only API key
ALGOLIA_SEARCH_KEY = ""
# The index name
ALGOLIA_INDEX = ""

Once those are in place, we can submit queries via the Algolia JavaScript client to get results. Since our query is accessible in our template, we’ll create a new template filter to use the query and return the results.

To create a new filter, we need to extend 11ty in the .eleventy.js configuration file.

First, we’ll install the algoliasearch NPM package.

npm install algoliasearch
require("dotenv").config();
const { EleventyServerlessBundlerPlugin } = require("@11ty/eleventy");
const algoliasearch = require("algoliasearch");

const client = algoliasearch(process.env.ALGOLIA_APP, process.env.ALGOLIA_SEARCH_KEY);
const index = client.initIndex(process.env.ALGOLIA_INDEX);

module.exports = function (eleventyConfig) {
  eleventyConfig.addPlugin(EleventyServerlessBundlerPlugin, {
    name: "search", // The serverless function name from your permalink object
    functionsDir: "./netlify/functions/",
  });

  eleventyConfig.addFilter("getResults", function (query) {
    return index.search(query, {
      attributesToRetrieve: ["title", "url", "date", "description"],

    }).then(res => {
      return res.hits;
    })
  });

};

At the top of the file, we’ll set up the Algolia search client with the API keys, app name, and index name. After that, inside of the exported function, we’ll use 11ty’s addFilter() method to add a filter.

This method accepts two arguments: a string to use as the filter, and a function to execute when used. The function will receive the data passed from the page file. In this case, it will be the user-entered query.

In this simple example, we pass the query into the index.search() method and request back only the attributes we need to keep our response small. When that returns, we can return the results back to our page for use in a template loop.

---
layout: "base.html"
title: Search Page
permalink:
  search: /search/
---

<h2 class="is-size-3 mb-3">This list is built at request from the query "{{ eleventy.serverless.query.query }}"</h2>

{% assign results = eleventy.serverless.query.query | getResults %}
<div class="card-grid">
  {% for result in results %}
    {% include "article.html" %}
  {% endfor %}
</div>

In the page, we use the built-in assign tag in Liquid to assign the data to a variable. Then, we can loop through the returned array and pass that information into an include. This include can be used for these results as well as ANY article display on the site. The article.html file should be created in the _includes directory.

<article class="card column">
    <h2 class="title"><a href="{{ result.url }}">{{ result.title }}</a></h2>
    <p class="content">{{ result.description }}</p>
</article>

We now have a working server-rendered search in a statically-generated site thanks to 11ty Serverless. What are some other patterns in static sites that 11ty Serverless can help us overcome? Check out related solutions on our open source code exchange platform.

About the author
Bryan Robinson

Senior Developer Relations Specialist

githubtwitter

Recommended Articles

Powered byAlgolia Algolia Recommend

Keeping your Algolia search index up to date
product

Jaden Baptista

Technical Writer

Building a Store Locator in React using Algolia, Mapbox, and Twilio – Part 3
engineering

Clément Sauvage

Software Engineer, Freelance

How to personalize search results and recommendations
engineering

Ashley Huynh