Have any questions? +1 646.844.5712 (US)

SEMANTIC PRODUCT SEARCH FOR SHOPIFY WITH OPENAI EMBEDDINGS

Pre–words

This is a small, deliberately simple experiment — a first-pass look at how well low-cost semantic search performs on a real product catalogue, not a comprehensive benchmark. The catalogue belonged to a Shopify apparel store; we used only publicly available product-page information, with no access keys, passwords, or private data.

We share it because the approach is inexpensive, easy to reproduce, and increasingly relevant for e-commerce. Note: if you’d like something like this for your store, or you have any questions, please feel free to ask us.

Introduction

Most online-store search is still built around keywords. Type the exact word that appears in a product title or description and you’ll find the item — but phrase your need the way a real shopper thinks (“comfortable clothes for home and office”, “a gift for my husband who loves the outdoors”) and keyword search often returns weak matches, or nothing at all.

Semantic search closes that gap by matching on meaning rather than exact words. This case study measures how effective, accurate, and fast a simple semantic-search setup can be — and what it costs.

A quick primer: embeddings and vector search

An embedding model turns a piece of text into a list of numbers (a vector) that captures its meaning. Texts with similar meaning end up close together in this vector space. To search, you embed the user’s query the same way and look for the product vectors nearest to it — here, using cosine distance as the measure of closeness. The smaller the distance, the more semantically relevant the product.

This retrieval step is the core of Retrieval-Augmented Generation (RAG), and on its own it already powers “search by intent”.

What we tested

We used OpenAI’s text-embedding-3-small model to embed every product description in the catalogue. We chose it deliberately: it is inexpensive — about 2¢ per 1M tokens, or 1¢ per 1M tokens with batch requests — and more than capable for product-scale text. Test scripts were written in Python. We issued single requests to emulate a live shopper’s search, and cheaper batch requests to build the initial database of embeddings.

Where the vectors live

We stored the embeddings in PostgreSQL with the pgvector extension and ran the search directly in the database. That keeps the stack simple and is a perfectly good starting point.

In larger or higher-traffic systems you would often reach for a dedicated vector database — Qdrant, Pinecone, Milvus, or Weaviate — which add horizontal scaling, metadata filtering, and faster approximate nearest-neighbour search. Which one fits depends on catalogue volume, latency targets, and how much infrastructure you want to run.

Speed

For live, single queries — the path a real shopper hits — responses from the embedding service averaged about 0.8 seconds, with occasional peaks to 1.6 and even 2.8 seconds.

Building the database with batch requests averaged about 3.5 seconds per batch of 100 products, occasionally rising to 5.5–10 seconds. That batch time is a one-off cost: the embeddings database is built once and then simply kept up to date as the catalogue changes. In short — fast enough for interactive search, provided you design for the occasional latency spike.

Accuracy — worked examples

We tested with broad, natural-language queries rather than exact keywords. In every case the top results were sensible and on-intent. A few examples (top results described; product names omitted):

Query Top results returned
“Minimum set of clothes for a boy.” Kids’ apparel starter bundles (hat + polo + tee) and youth polos
“A gift for my husband, who loves outdoor activities and traveling.” Carry-on and weekender travel backpacks, a travel toiletry bag, a travel cigar case
“Cute clothes for my teenage daughter for the summer.” A women’s sleeveless summer polo, a lavender pullover, patterned youth polos
“Comfortable clothes for home and office.” Joggers, waffle-knit pullovers and hoodies, everyday shorts, an active tee
“Something for a bachelor party.” A hat-and-polo combo pack, a novelty “Vegas” hat, a travel cigar case, a weekender backpack

The most telling result

As a control, we ran the same natural-language queries against the stores’ own built-in search. The results were consistently worse — and often empty. This is exactly the gap semantic search is built to close: shoppers rarely type the precise keywords a catalogue was written with, and matching on meaning captures the intent that keyword search misses.

What we did not test

This was intentionally a simple experiment. We did not combine search types (for example, hybrid keyword-plus-vector search or a re-ranking step), tune the model, or add the synonyms, filters, and business rules a production system needs. We also did not stress-test at high concurrency. Any of these would refine the results further — none were necessary to see that the core approach works.

Conclusions

Even a simple, inexpensive setup — one embedding model, PostgreSQL with pgvector, and cosine-distance search — delivered fast, relevant, intent-aware product search that outperformed native store search on natural-language queries. For most catalogues it is an affordable, reproducible foundation you can extend with hybrid search, filtering, and re-ranking as needs grow.

If you’d like to explore semantic search or RAG for your own store or product, we’d be glad to help — get in touch.