Recommend products on e-commerce sites using Workers AI and Stripe
E-commerce and media sites often work on increasing the average transaction value to boost profitability. One of the strategies to increase the average transaction value is "cross-selling," which involves recommending related products. Cloudflare offers a range of products designed to build mechanisms for retrieving data related to the products users are viewing or requesting. In this tutorial, you will experience developing functionalities necessary for cross-selling by creating APIs for related product searches and product recommendations.
In this workshop, you will develop three REST APIs.
- An API to search for information highly related to a specific product.
- An API to suggest products in response to user inquiries.
- A Webhook API to synchronize product information with external e-commerce applications.
By developing these APIs, you will learn about the resources needed to build cross-selling and recommendation features for e-commerce sites.
You will also learn how to use the following Cloudflare products:
- Cloudflare Workers: Execution environment for API applications
- Cloudflare Vectorize: Vector DB used for related product searches
- Cloudflare Workers AI: Used for vectorizing data and generating recommendation texts
All of the tutorials assume you have already completed the Get started guide, which gets you set up with a Cloudflare Workers account, C3 ↗, and Wrangler.
- Sign up for a Cloudflare account ↗.
- Install
Node.js
↗.
Node.js version manager
Use a Node version manager like Volta ↗ or nvm ↗ to avoid permission issues and change Node.js versions. Wrangler, discussed later in this guide, requires a Node version of 16.17.0
or later.
This tutorial involves the use of several Cloudflare products. Some of these products have free tiers, while others may incur minimal charges. Please review the following billing information carefully.
First, let's create a Cloudflare Workers project.
C3 (create-cloudflare-cli) ↗ is a command-line tool designed to help you set up and deploy new applications to Cloudflare. In addition to speed, it leverages officially developed templates for Workers and framework-specific setup guides to ensure each new application that you set up follows Cloudflare and any third-party best practices for deployment on the Cloudflare network.
To efficiently create and manage multiple APIs, let's use Hono
↗. Hono is an open-source application framework released by a Cloudflare Developer Advocate. It is lightweight and allows for the creation of multiple API paths, as well as efficient request and response handling.
Open your command line interface (CLI) and run the following command:
If this is your first time running the C3
command, you will be asked whether you want to install it. Confirm that the package name for installation is create-cloudflare
and answer y
.
During the setup, you will be asked if you want to manage your project source code with Git
. It is recommended to answer Yes
as it helps in recording your work and rolling back changes. You can also choose No
, which will not affect the tutorial progress.
Finally, you will be asked if you want to deploy the application to your Cloudflare account. For now, select No
and start development locally.
If you see a message like the one below, the project setup is complete. You can open the cross-sell-api
directory in your preferred IDE to start development.
Cloudflare Workers applications can be developed and tested in a local environment. On your CLI, change directory into your newly created Workers and run npx wrangler dev
to start the application. Using Wrangler
, the application will start, and you'll see a URL beginning with localhost
.
You can send a request to the API using the curl
command. If you see the text Hello Hono!
, the API is running correctly.
So far, we've covered how to create a Cloudflare Worker project and introduced tools and open-source projects like the C3
command and the Hono
framework that streamline development with Cloudflare. Leveraging these features will help you develop applications on Cloudflare Workers more smoothly.
Now, we will start developing the three APIs that will be used in our cross-sell system. First, let's create an API to synchronize product information with an existing e-commerce application. In this example, we will set up a system where product registrations in Stripe ↗ are synchronized with the cross-sell system.
This API will receive product information sent from an external service like Stripe as a Webhook event. It will then extract the necessary information for search purposes and store it in a database for related product searches. Since vector search will be used, we also need to implement a process that converts strings to vector data using an Embedding model provided by Cloudflare Workers AI.
The process flow is illustrated as follows:
sequenceDiagram participant Stripe box Cloudflare participant CF_Workers participant CF_Workers_AI participant CF_Vectorize end Stripe->>CF_Workers: Send product registration event CF_Workers->>CF_Workers_AI: Request product information vectorization CF_Workers_AI->>CF_Workers: Send back vector data result CF_Workers->>CF_Vectorize: Save vector data
Let's start implementing step-by-step.
This API requires the use of Workers AI and Vectorize. To use these resources from a Worker, you will need to first create the resources then bind them to a Worker. First, let's create a Vectorize index with Wrangler using the command wrangler vectorize create {index_name} --dimensions={number_of_dimensions} --metric={similarity_metric}
. The values for dimensions
and metric
depend on the type of Text Embedding Model you are using for data vectorization (Embedding). For example, if you are using the bge-large-en-v1.5
model, the command is:
When this command executes successfully, you will see a message like the following. It provides the items you need to add to wrangler.toml
to bind the Vectorize index with your Worker application. Copy the three lines starting with [[vectorize]]
.
To use the created Vectorize index from your Worker, let's add the binding. Open wrangler.toml
and add the copied lines.
Additionally, let's add the configuration to use Workers AI in wrangler.toml
.
When handling bound resources from your application, you can generate TypeScript type definitions to develop more safely. Run the npm run cf-typegen
command. This command updates the worker-configuration.d.ts
file, allowing you to use both Vectorize and Workers AI in a type-safe manner.
Once you save these changes, the respective resources and APIs will be available for use in the Workers application. You can access these properties from env
. In this example, you can use them as follows:
Finally, rerun the npx wrangler dev
command with the --remote
option. This is necessary because Vectorize indexes are not supported in local mode. If you see the message, Vectorize bindings are not currently supported in local mode. Please use --remote if you are working with them.
, rerun the command with the --remote
option added.
You can receive notifications about product registration and information via POST requests using webhooks. Let's create an API that accepts POST requests. Open your src/index.ts
file and add the following code:
This code implements an API that processes POST requests to the /webhook
endpoint. The data sent by Stripe's Webhook events is included in the request body in JSON format. Therefore, we use c.req.json()
to extract the data. There are multiple types of Webhook events that Stripe can send, so we added a conditional to only process events when a product is newly added, as indicated by the type
.
When developing a webhook API, you need to ensure that requests from unauthorized sources are rejected. To prevent unauthorized API requests from causing unintended behavior or operational confusion, you need a mechanism to verify the source of API requests. When integrating with Stripe, you can protect the API by generating a signing secret used for webhook verification.
- Refer to the Stripe documentation ↗ to get a secret API key for the test environment ↗.
- Save the obtained API key in a
.dev.vars
file.
- Follow the guide ↗ to install Stripe CLI.
- Use the following Stripe CLI command to forward Webhook events from Stripe to your local application.
- Copy the signing secret that starts with
whsec_
from the Stripe CLI command output.
- Save the obtained signing secret in the
.dev.vars
file.
- Run
npm run cf-typegen
to update the type definitions inworker-configuration.d.ts
. - Run
npm install stripe
to add the Stripe SDK to your application. - Restart the
npm run dev -- --remote
command to import the API key into your application.
Finally, modify the source code of src/index.ts
as follows to ensure that the webhook API cannot be used from sources other than your Stripe account.
This ensures that an HTTP 400 error is returned if the Webhook API is called directly by unauthorized sources.
Use the Stripe CLI command to test sending events from Stripe.
The product information added on the Stripe side is recorded as a log on the terminal screen where npm run dev
is executed.
We've prepared to ingest product information, so let's start implementing the preprocessing needed to create an index for search. In vector search using Cloudflare Vectorize, text data must be converted to numerical data before indexing. By storing data as numerical sequences, we can search based on the similarity of these vectors, allowing us to retrieve highly similar data.
In this step, we'll first implement the process of converting externally sent data into text data. This is necessary because the information to be converted into vector data is in text form. If you want to include product names, descriptions, and metadata as search targets, add the following processing.
By adding this processing, you convert product information in JSON format into a simple Markdown format product introduction text.
Now that we've converted the data to text, let's convert it to vector data. By using the Text Embedding model of Workers AI, we can convert text into vector data of any desired dimension.
When using Workers AI, execute the c.env.AI.run()
function. Specify the model you want to use as the first argument. In the second argument, input text data about the text you want to convert using the Text Embedding model or the instructions for the generated images or text. If you want to save the converted vector data using Vectorize, make sure to select a model that matches the number of dimensions
specified in the npx wrangler vectorize create
command. If the numbers do not match, there is a possibility that the converted vector data cannot be saved.
Finally, let's save the created data to Vectorize. Edit src/index.ts
to implement the indexing process using the VECTORIZE_INDEX
binding. Since the data to be saved will be vector data, save the pre-conversion text data as metadata.
With this, we have established a mechanism to synchronize the product data with the database for recommendations. Use Stripe CLI commands to save some product data.
If the save is successful, you will see logs like [200] POST
in the screen where you are running the stripe listen
command.
If you confirm one log entry for each piece of registered data, the save process is complete. Next, we will implement the API for related product searches.
Now that we have prepared the index for searching, the next step is to implement an API to search for related products. By utilizing a vector index, we can perform searches based on how similar the data is. Let's implement an API that searches for product data similar to the specified product ID using this method.
In this API, the product ID is received as a part of the API path. Using the received ID, vector data is retrieved from Vectorize using c.env.VECTORIZE_INDEX.getByIds()
. The return value of this process includes vector data, which is then passed to c.env.VECTORIZE_INDEX.query()
to conduct a similarity search. To quickly check which products are recommended, we set returnMetadata
to true
to obtain the stored metadata information as well. The topK
parameter specifies the number of data items to retrieve. Change this value if you want to obtain less than 2 or more than 4 data items.
Let's run this API. Use a product ID that starts with prod_
, which can be obtained from the result of running the stripe products crate
command or the stripe products list
command.
If you send a request using a product ID that exists in the Vectorize index, the data for that product and two related products will be returned as follows.
Looking at the score
in similarProducts
, you can see that there is data with a score
of 1
. This means it is exactly the same as the query used to search. By looking at the metadata, it is evident that the data is the same as the product ID sent in the request. Since we want to search for related products, let's add a filter
to prevent the same product from being included in the search results. Here, a filter is added to exclude data with the same product name using the metadata
name.
After adding this process, if you run the API, you will see that there is no data with a score
of 1
.
In this way, you can implement a system to search for related product information using Vectorize.
Recommendations can be more than just displaying related products; they can also address user questions and concerns. The final API will implement a process to answer user questions using Vectorize and Workers AI.
This API will implement the following processes:
- Vectorize the user's question using the Text Embedding Model from Workers AI.
- Use Vectorize to search and retrieve highly relevant products.
- Convert the search results into a string in Markdown format.
- Utilize the Text Generation Model from Workers AI to generate a response based on the search results.
This method realizes a text generation mechanism called Retrieval Augmented Generation (RAG) using Cloudflare. The bindings and other preparations are already completed, so let's add the API.
Let's use the created API to consult on a product. You can send your question in the body of a POST request. For example, if you want to ask about getting a new PC, you can execute the following command:
When the question is sent, a recommendation text will be generated as introduced earlier. In this example, the Ultra Notebook
product was recommended. This is because it has a notebook compucoter
description, which means it received a relatively high score in the Vectorize search.
The text generation model generates new text each time based on the input prompt (questions or product search results). Therefore, even if you send the same request to this API, the response text may differ slightly. When developing for production, use features like logging or caching in the AI Gateway to set up proper control and debugging.
Before deploying the application, we need to make sure your Worker project has access to the Stripe API keys we created earlier. Since the API keys of external services are defined in .dev.vars
, this information also needs to be set in your Worker project. To save API keys and secrets, run the npx wrangler secret put <KEY>
command. In this tutorial, you'll execute the command twice, referring to the values set in .dev.vars
.
Then, run npx wrangler deploy
. This will deploy the application on Cloudflare, making it publicly accessible.
As you can see, using Cloudflare Workers, Workers AI, and Vectorize allows you to easily implement related product or product recommendation APIs. Even if product data is managed on external services like Stripe, you can incorporate them by adding a webhook API. Additionally, though not introduced in this tutorial, you can save information such as user preferences and interested categories in Workers KV or D1. By using this stored information as text generation prompts, you can provide more accurate recommendation functions.
Use the experience from this tutorial to enhance your e-commerce site with new ideas.