How to increase your ecommerce conversion rate in 2024
2%. That’s the average conversion rate for an online store. Unless you’re performing at Amazon’s promoted products ...
Senior Digital Marketing Manager, SEO
2%. That’s the average conversion rate for an online store. Unless you’re performing at Amazon’s promoted products ...
Senior Digital Marketing Manager, SEO
What’s a vector database? And how different is it than a regular-old traditional relational database? If you’re ...
Search and Discovery writer
How do you measure the success of a new feature? How do you test the impact? There are different ways ...
Senior Software Engineer
Algolia's advanced search capabilities pair seamlessly with iOS or Android Apps when using FlutterFlow. App development and search design ...
Sr. Developer Relations Engineer
In the midst of the Black Friday shopping frenzy, Algolia soared to new heights, setting new records and delivering an ...
Chief Executive Officer and Board Member at Algolia
When was your last online shopping trip, and how did it go? For consumers, it’s becoming arguably tougher to ...
Senior Digital Marketing Manager, SEO
Have you put your blood, sweat, and tears into perfecting your online store, only to see your conversion rates stuck ...
Senior Digital Marketing Manager, SEO
“Hello, how can I help you today?” This has to be the most tired, but nevertheless tried-and-true ...
Search and Discovery writer
We are proud to announce that Algolia was named a leader in the IDC Marketscape in the Worldwide General-Purpose ...
VP Corporate Marketing
Twice a year, B2B Online brings together America’s leading manufacturers and distributors to uncover learnings and industry trends. This ...
Director, Sales Enablement & B2B Practice Leader
Generative AI and large language models (LLMs). These two cutting-edge AI technologies sound like totally different, incomparable things. One ...
Search and Discovery writer
ChatGPT, Bing, Bard, YouChat, DALL-E, Jasper…chances are good you’re leveraging some version of generative artificial intelligence on ...
Search and Discovery writer
Your users are spoiled. They’re used to Google’s refined and convenient search interface, so they have high expectations ...
Technical Writer
Imagine if, as your final exam for a computer science class, you had to create a real-world large language ...
Sr. SEO Web Digital Marketing Manager
What do you think of the OpenAI ChatGPT app and AI language models? There’s lots going on: GPT-3 ...
Search and Discovery writer
In the fast-paced and dynamic realm of digital merchandising, being reactive to customer trends has been the norm. In ...
Staff User Researcher
You’re at a dinner party when the conversation takes a computer-science-y turn. Have you tried ChatGPT? What ...
Sr. SEO Web Digital Marketing Manager
It’s the era of Big Data, and super-sized language models are the latest stars. When it comes to ...
Search and Discovery writer
If you’re going to send an email to your customer, it better be relevant. Product recommendations are a great way to create engaging emails for your customers to invite them back to your site. Algolia Recommend builds personalized product recommendations by training AI models on customer site analytics. In this blog you’ll see how to build a back-end service that crafts tailored recommendation emails and sends them to your customers using Twilio SendGrid.
For this demo, we’ll be building an engagement email service for an e-commerce site. We’ll explore recommendation strategies that become more tailored as we layer in more features and analytics based on customer interactions with our site.
The four customer scenarios are as follows:
We’ll rely on the following technologies:
We’ll build the service in four steps:
We’ll build our service as an express app using node. You can clone the solution repository to follow along.
git clone https://github.com/algolia-samples/email-recommendations
Our service follows the typical structure of an express application written in Node.js. The server code lives in server/node
:
├── README.md ├── emails │ ├── 1 │ │ ├── README.md │ │ └── email.js │ ├── 2 │ │ ├── README.md │ │ └── email.js │ ├── 3 │ │ ├── README.md │ │ └── email.js │ └── 4 │ ├── README.md │ └── email.js ├── package-lock.json ├── package.json ├── sendgrid.js ├── server.js └── templates ├── base.html ├── partials │ ├── products_3_columns.html │ └── products_full_width.html ├── post_order.html ├── pre_order.html └── re-engagement.html
The server.js
file has our routing, API initialization, and page rendering. The templates/
directory is for our Cerberus email templates. The actual contents of our four engagement emails live in the emails/
directory. We manage sending emails in sendgrid.js
.
Before we can continue, we need to install our dependencies from our package.json
.
cd server/node npm install
Now we’re ready to start configuring the various APIs our service relies on. We copy the file .env.example
from the root of this project to the directory of the server we want to use and rename it to .env
. For example, to use the Node implementation:
cp .env.example server/node/.env
Our .env
file has some keys that need we need to assign:
# Algolia credentials # https://www.algolia.com/doc/guides/security/api-keys/#access-control-list-acl ALGOLIA_APP_ID= ALGOLIA_API_KEY= ALGOLIA_INDEX_NAME= ALGOLIA_RECOMMENDATION_API_KEY= # SendGrid credentials SENDGRID_API_KEY= SENDGRID_FROM_EMAIL= # Envs
STATIC_DIR=../../client
Let’s start with our data and Algolia credentials.
To follow along, you’ll need an index under your existing Algolia account or you can sign up for a free account and set up an application. For the examples in this blog, we’ll be using an existing demo site.
This demo assumes you have a pre-existing index with enough event data to use Algolia Recommend. If you don’t have an index yet or don’t have enough events for recommendations, you can still use the strategies that don’t require trained machine learning models. Just follow these steps to create and populate an index.
Once we have our index we can set the ALGOLIA_INDEX_NAME
and ALGOLIA_APP_ID
environment variables in our .env
file. We’ll also set ALGOLIA_API_KEY
to our search-only API key. We can find this info on API Keys page of our Algolia dashboard.
ALGOLIA_APP_ID= ALGOLIA_API_KEY= ALGOLIA_INDEX_NAME=
While we’re on the API Key page, we should create another key to use for recommendations. From the API Keys page, we navigate over to the All API Keys tab and click New API Key, choose our index, and add recommendation
to our ACL. Now we can add this key to our .env
file.
ALGOLIA_RECOMMENDATION_API_KEY=
Once all the Algolia pieces are in place, let’s make sure our Recommend models are trained and ready. We click on the Recommend light bulb icon on the Algolia dashboard and look at the “Where is Recommend active?” section. If the models are not already trained, we’ll need to train the models.
It’s ok if we don’t have enough events to train our models. We can still use the templates that don’t need Algolia Recommend.
We use Twilio SendGrid as the email provider to send our rendered previews. You’ll need to sign up with SendGrid if you don’t have an account already, then create and store a SendGrid API key with permissions to send emails. You’ll also need to validate you email domain or single sender email before you’ll be able to send outbound mail.
Add your SENDGRID_API_KEY
and validated SENDGRID_FROM_EMAIL
in the .env
file:
SENDGRID_API_KEY= SENDGRID_FROM_EMAIL=
With all our APIs configured, we’re ready to dig into the server code starting with server.js
. Here we set up our express server and initialize all our API clients:
// Setup Express, markdown renderer and Algolia clients. const app = express(); const converter = new showdown.Converter(); const algoliaClient = algoliaearch(process.env.ALGOLIA_APP_ID, process.env.ALGOLIA_API_KEY) const recommendClient = algoliarecommend(process.env.ALGOLIA_APP_ID, process.env.ALGOLIA_API_KEY); const algoliaIndex = algoliaClient.initIndex(process.env.ALGOLIA_INDEX_NAME); // Setup email delivery sendgrid.setApiKey(process.env.SENDGRID_API_KEY);
In this demo we generate and send emails interactively, so we want to serve up our client application.
// Home page app.get("/", (req, res) => { const indexPath = path.resolve(process.env.STATIC_DIR + "/index.html"); res.sendFile(indexPath); });
Each of our engagement scenarios has an email template and a README.md
describing the scenario. The client loads the four templates out of the emails/
directory and puts them in a list to display in the client application.
app.use(express.static(process.env.STATIC_DIR)); app.use(express.json()); const loadEmails = async () => { const EmailBaseDir = "./emails"; const emailDirs = await fs.promises.readdir(EmailBaseDir); const emails = []; for(const emailDir of emailDirs) { const emailDirPath = path.join(EmailBaseDir, emailDir); const explanationFile = await fs.promises.readFile(path.join(emailDirPath, "README.md"), "utf8"); const explanation = converter.makeHtml(explanationFile); const { email } = await import(`./${path.join(emailDirPath, "email.js")}`); emails.push({ ...email, explanation, }); }; return emails; };
After selecting a scenario from the drop down, the client renders the selected email using nunjucks, the appropriate Cerberus email template from the templates/
directory, and the underlying API calls needed to generate the recommendations for that scenario.
If we like the look of the rendered email, we can send it to ourselves using SendGrid. We type our email address into the Send this email field and click Send. Our service will pass the rendered email to the SendGrid API and mail it to us!
Now that we understand the general pattern, let’s dive into how we construct the recommendations for each of our four scenarios.
In this scenario, a customer browses a category on your site but doesn’t buy anything. We don’t know much about the customer or the specific item they are looking for. We use Algolia’s Faceting to recommend the best rated products from that category.
If the customer browses for men’s t-shirts, we call the Algolia Search API and request the first six items for this category using the index’s ranking criteria.
async (algoliaIndex, _) => { // The customer browsed the Men / Tee-shirt category const facetFilters = ["category:Men - T-Shirts"]; // Get the top-rated products from the category const { hits } = await algoliaIndex.search("", { facetFilters, hitsPerPage: 6 });
We use SendGrind to email these suggestions to the customer with links back to our site to continue browsing.
This is a great fallback strategy when we do not have enough information about the customer or the particular product they are looking for. It doesn’t require event data and relies only on category information within the index itself.
In this scenario, the customer has purchased a product from our site. We’ll suggest products other customers have often bought along with it. We’ll use Algolia Recommend to train a machine-learning algorithm based on event data of customer purchases.
With our models already trained, we’ll only need a few lines of code to get from the current product to a list of recommended products based on the purchase history of other customers on our site.
const orderContent = ["D07940-6931-990"]; // Get the similar items for this item. const { results: [ { hits }, ]} = await recommendClient.getRecommendations([{ indexName: process.env.ALGOLIA_INDEX_NAME, objectID: orderContent[0], model: "bought-together", maxRecommendations: 3, }]);
Again, we use SendGrind to email these suggestions to the customer with links back to our site to continue browsing.
This is similar to scenario two. The customer has just purchased a product from our site. This time we’ll use this information to suggest products related to the one they purchased. We’ll use the Algolia Recommend related-products
model this time.
As with the previous scenario, since our models are already trained, we’ll only need a few lines of code to get from the current product to a list of recommended products based on the purchase history of other customers on our site.
const orderContent = ["D07940-6931-990"]; // Get the related product for the bought product. const { results: [ { hits }, ]} = await recommendClient.getRecommendations([{ indexName: process.env.ALGOLIA_INDEX_NAME, objectID: orderContent[0], model: "related-products", maxRecommendations: 3, fallbackParameters: {facetFilters:["category:Women - Jeans"]} }]);
Notice here we include a fallback parameter. We can fill in our recommendation list with top items from this category if there aren’t enough recommendations from the model.
Now we can email the recommendations to the customer using SendGrind.
In this final scenario, a customer has visited the site before. As they navigated our site, we captured their click and conversion actions using Algolia Insights. Algolia takes these events and builds a Personalization profile for the customer. We will use this profile along with the Recommend API to find related products that match the customer’s affinities.
First, we use the unique token our site uses for this customer to retrieve their personalization profile from the Algolia Personalization endpoint. (Note that we use the Recommendation API credentials to retrieve this profile.)
async (algoliaIndex, recommendClient) => { // Get the customer's affinities profile // https://www.algolia.com/doc/rest-api/personalization/#get-a-usertoken-profile const userToken = 'user-1'; const res = await fetch( `https://recommendation.eu.algolia.com/1/profiles/personalization/${userToken}`, { headers: { "X-Algolia-API-Key": process.env.ALGOLIA_RECOMMENDATION_API_KEY, "X-Algolia-Application-Id": process.env.ALGOLIA_APP_ID } } ); const { scores } = await res.json();
The response is the customer’s profile in JSON format. It will look something like this:
{ "userToken": "user_1", "lastEventAt": "2019-07-12T10:03:37Z", "scores": { "category": { "Women - Jeans": 1, "Men - T-Shirts": 10 }, "location": { "US": 6 } } }
This profile includes a list of categories from our site ranked by affinity score. We’ll take the top-ranked categories and turn them into facets that the user can use to search for products.
// Transform the top customer affinities into a list of `facetFilters` let facetFilters = []; for (const key in scores) { const score = scores[key]; let values = []; for (const valueKey in score) { values.push([ valueKey, score[valueKey] ]); }; values.sort((kv1, kv2) => kv2[1] - kv1[1]); facetFilters.push(`${[key]}:${values[0][0]}`); };
Algolia Recommend provides recommendations based on individual products, not categories. We’ll retrieve the top products from each of the facets we know our customer likes, then send them to Algolia Recommend to find similar products.
// Get the top-rated products matching the top-scoring customer profile facets const { hits: [topHit,] } = await algoliaIndex.search("", { facetFilters, hitsPerPage: 6 }); // Get the related items matching the top-rated product const { results: [ { hits }, ]} = await recommendClient.getRecommendations([{ indexName: process.env.ALGOLIA_INDEX_NAME, objectID: topHit.objectID, model: "related-products", maxRecommendations: 3 }]);
Now we have engaging results by combining our knowledge of the customer’s habits with the buying behaviors of other customers on our site.
Once again, we add links back to our site and send the email out using SendGrid.
You can generate engaging customer recommendation emails based on knowledge of your products and your users’ behavior. Machine learning models like those in Algolia Recommend can bring even more relevance into your emails. Now you have the tools to go build a recommendation email service of your own!
Want to do more with recommendations? Take a look at our code blocks using Twilio or, more broadly, our code blocks using Algolia Recommend. Check out related solutions on our open source code exchange platform.
Powered by Algolia Recommend