Chat on WhatsApp
AI for Magento 13 min read

AI Product Recommendations in Magento — Adobe Sensei vs Custom OpenAI Embeddings

Adobe Sensei Product Recommendations ships only with Adobe Commerce — Magento Open Source merchants do not get it. The alternative is rolling your own with OpenAI's text-embedding-3-small, a vector store (pgvector or OpenSearch k-NN), and a 60-line PDP block. This is the honest comparison: Sensei's real CTR uplift of 3–7% on PDPs and AOV +5–10% versus a custom embedding stack that costs $0.02 per 1,000 products to embed, $5/month for a Redis cache, and gives you full ranking transparency. Includes the cold-start playbook (category-centroid embeddings until behavioural signals arrive), the pgvector schema, the OpenAI batch call, and the break-even math — at 100,000 monthly sessions, Sensei needs 0.4% incremental revenue to pay for itself; the custom stack needs 0.04%.

AI Product Recommendations in Magento — Adobe Sensei vs Custom OpenAI Embeddings

AI product recommendations in Magento is the architecture decision every Adobe Commerce and Magento Open Source 2.4.4 — 2.4.9 merchant hits once the catalog passes 1,000 SKUs and rule-based related products stops producing relevant results. The two real options in 2026: Adobe Sensei Product Recommendations (Adobe Commerce only, fully managed, black-box) and a custom OpenAI embeddings stack (open-source-compatible, transparent, ~50x cheaper at break-even). This is the honest side-by-side, with the embedding code, the pgvector schema, the cold-start playbook, and the break-even math we use at kishansavaliya.com.

Adobe Sensei is only available on Adobe Commerce and the open-source alternative is now mature enough to ship in production.

Adobe Sensei Product Recommendations[1] is a managed service inside Adobe Experience Platform that ingests catalog + behavioural data from an Adobe Commerce store, trains six recommendation types, and serves them via Storefront API or a drop-in JS widget. The catch is unambiguous on the Adobe product page[1]: Sensei is Adobe Commerce only. Magento Open Source merchants cannot install, license, or extend it — no community port, no Marketplace alternative wraps the same service.

If you are on Magento Open Source 2.4.4 — 2.4.9 and someone is selling you "Sensei-compatible" recommendations, ask which Adobe IO Runtime project ID you are connecting to. There isn't one.

The realistic alternative for Open Source merchants: build a custom engine with OpenAI's text-embedding-3-small[2], store vectors in pgvector or OpenSearch k-NN, and query cosine-similar SKUs at PDP load. The pieces are mature — text-embedding-3-small ships at $0.020 per 1M input tokens[2], OpenSearch 2.x has native k-NN with HNSW, and Magento 2.4.4 — 2.4.9 already runs OpenSearch as the catalog search backend so the infrastructure is paid for.

Section 1 — What Adobe Sensei actually does (and what it costs)

Sensei exposes six recommendation types[1]: Recommended for You (personalised), More Like This (attribute similarity), Customers Also Viewed (co-view filter), Customers Also Bought (co-purchase filter), Popular (30-day view + add-to-cart), Trending (7-day velocity). Reported impact across Adobe Commerce case studies and a 200+ merchant cohort:

MetricReported uplift (Sensei)Notes
PDP click-through on recommendations+3–7%vs rule-based related products[1]
Average order value+5–10%concentrated in cross-sell slots[1]
Conversion rate+2–4%strongest on Recommended for You
Time-to-first-recommendation~14 dayswarm-up window after install

Those are real numbers. The catches are equally real:

  • Adobe Commerce license required. Adobe Commerce on-prem starts at ~$22,000/year (2026 list, varies by GMV tier). Sensei is included — but only if you bought the license. Open Source merchants face a ~$22K floor before the first recommendation renders.
  • Black-box ranking. Sensei does not expose feature weights, embedding vectors, or ranking logic. The only lever is admin-side "boost" rules.
  • No model customization. The six recommendation types are fixed. There is no API to define a seventh.
  • Data egress. Catalog + behavioural data leaves Magento for Adobe Experience Platform — a data-residency conversation for EU merchants, not a checkbox.
  • Vendor lock-in. Storefront API and recommendation IDs are Adobe-specific. Switching off means rebuilding the PDP block.

Section 2 — Sensei limits that push merchants to custom embeddings

The four scenarios where the Adobe Sensei approach actively breaks down — observed across the recommendation projects we have scoped in the last 24 months:

Limit 1 — Open Source merchants are excluded entirely

Adobe's product page is explicit[1]: Sensei Product Recommendations is Adobe Commerce only. No community module bridges the gap. Open Source merchants are roughly 65% of the Magento install base in 2026 — none of them can run Sensei.

Limit 2 — Catalogs under 500 SKUs never warm up

Sensei's behavioural recommendations need traffic signal. Under 500 SKUs at under 10K monthly sessions, the co-view and co-purchase matrices stay sparse for months. The fall-back is "Popular" which collapses to the same 20 SKUs site-wide.

Limit 3 — No feature-aware ranking

A B2B parts catalog wants "same voltage rating". A fashion catalog wants "same colour family, different category". Sensei's six types do not expose attribute weights in the ranking layer — attributes apply as hard filters that often return zero results.

Limit 4 — Multi-store-view merchants share one model

US + DE + JP store views typically want region-specific bestsellers and cross-sells. Sensei treats all store views as one model per Commerce instance. Splitting means separate Commerce instances — separate ~$22K licenses.

Section 3 — The custom OpenAI embeddings approach

Four pieces: embedding job, vector store, recommendation block, behavioural feedback loop. Each is a weekend's worth of code.

3a — The embedding job

A CLI command iterates the catalog, builds an embedding input per SKU, calls OpenAI's embedding endpoint[2], and writes the 1,536-dim vector to a custom table.

#!/usr/bin/env python3
# bin/embed_catalog.py — run via cron or magento CLI wrapper
import os
import json
import psycopg2
from openai import OpenAI

client = OpenAI(api_key=os.environ['OPENAI_API_KEY'])
MODEL = 'text-embedding-3-small'  # 1,536 dims, $0.020 per 1M tokens
BATCH = 100

def build_input(product):
    parts = [
        product['name'],
        product['short_description'] or '',
        ' > '.join(product['category_breadcrumbs']),
        ' '.join(f"{k}:{v}" for k, v in product['attributes'].items()),
    ]
    return ' | '.join(p for p in parts if p)[:8000]

def embed_batch(products):
    inputs = [build_input(p) for p in products]
    response = client.embeddings.create(model=MODEL, input=inputs)
    return [(p['sku'], r.embedding) for p, r in zip(products, response.data)]

def main():
    conn = psycopg2.connect(os.environ['PG_DSN'])
    cur = conn.cursor()
    cur.execute("SELECT sku, name, short_description, category_breadcrumbs, attributes "
                "FROM product_catalog_view WHERE updated_at > NOW() - INTERVAL '24 hours'")
    products = [dict(zip(['sku', 'name', 'short_description',
                          'category_breadcrumbs', 'attributes'], row)) for row in cur.fetchall()]
    for i in range(0, len(products), BATCH):
        for sku, vector in embed_batch(products[i:i + BATCH]):
            cur.execute(
                "INSERT INTO product_embeddings (sku, vector, model, updated_at) "
                "VALUES (%s, %s, %s, NOW()) "
                "ON CONFLICT (sku) DO UPDATE SET vector = EXCLUDED.vector, updated_at = NOW()",
                (sku, vector, MODEL))
        conn.commit()
        print(f"Embedded {i + BATCH}/{len(products)}")

if __name__ == '__main__':
    main()

Token math: a typical product input runs ~600–1,200 tokens. At $0.020 per 1M input tokens[2], 1,000 products costs ~$0.02; a 50,000-SKU catalog ~$1.00. Re-embedding only changed SKUs nightly keeps the steady-state bill at pennies per month.

3b — Vector store: pgvector or OpenSearch k-NN

Two production-grade options, both Magento-compatible:

-- pgvector schema (PostgreSQL 15+ with the pgvector extension)
CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE product_embeddings (
  sku          VARCHAR(64) PRIMARY KEY,
  vector       vector(1536) NOT NULL,
  model        VARCHAR(64)  NOT NULL,
  updated_at   TIMESTAMPTZ  NOT NULL DEFAULT NOW()
);

-- HNSW index for sub-10ms cosine search at 100K vectors
CREATE INDEX product_embeddings_hnsw
  ON product_embeddings
  USING hnsw (vector vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);

-- The recommendation query: top-10 similar SKUs excluding self
SELECT sku, 1 - (vector <=> $1) AS similarity
FROM product_embeddings
WHERE sku != $2
ORDER BY vector <=> $1
LIMIT 10;

If you already run OpenSearch as the Magento catalog backend (which you do on Magento 2.4.4 — 2.4.9), the k-NN equivalent is a single index mapping:

{
  "settings": { "index.knn": true },
  "mappings": {
    "properties": {
      "sku":    { "type": "keyword" },
      "vector": {
        "type": "knn_vector",
        "dimension": 1536,
        "method": {
          "name": "hnsw",
          "space_type": "cosinesimil",
          "engine": "lucene",
          "parameters": { "m": 16, "ef_construction": 64 }
        }
      }
    }
  }
}

3c — PDP block

A Magento block reads the current SKU, fetches its embedding, runs the cosine query, and renders top-N as a Hyvä product card grid. Sub-10ms on pgvector with HNSW at the 100K-vector mark.

<?php
// app/code/Panth/AiRecommendations/Block/Pdp/Similar.php
namespace Panth\AiRecommendations\Block\Pdp;

use Magento\Catalog\Model\ProductRepository;
use Magento\Framework\View\Element\Template;
use Panth\AiRecommendations\Service\VectorSearch;

class Similar extends Template
{
    public function __construct(
        Template\Context $context,
        private VectorSearch $search,
        private ProductRepository $productRepository,
        array $data = []
    ) {
        parent::__construct($context, $data);
    }

    public function getRecommendations(string $sku, int $limit = 10): array
    {
        $cacheKey = 'pdp_reco_v1_' . md5($sku);
        $cached = $this->_cache->load($cacheKey);
        if ($cached) {
            return json_decode($cached, true);
        }
        $skus = $this->search->findSimilar($sku, $limit);
        $products = array_map(
            fn($s) => $this->productRepository->get($s),
            $skus
        );
        $payload = array_map(fn($p) => [
            'sku'   => $p->getSku(),
            'name'  => $p->getName(),
            'url'   => $p->getProductUrl(),
            'price' => $p->getFinalPrice(),
        ], $products);
        $this->_cache->save(json_encode($payload), $cacheKey, ['catalog_product'], 3600);
        return $payload;
    }
}

Section 4 — Cold-start: what to do with new SKUs

Sensei's documented warm-up window is ~14 days because the collaborative filter needs co-view + co-purchase signal[1]. The custom stack has no warm-up penalty — a new SKU has a usable embedding the moment its title and description are written. The behavioural reranker (second-pass scoring by historical CTR and conversion) still needs signal.

The playbook we ship on every recommendation project:

  • Day 0 — content embedding. The new SKU has a 1,536-dim vector from title + description + breadcrumbs. Cosine search returns a relevant candidate set immediately.
  • Day 0–14 — category centroid fallback. Under 50 PDP views or 5 add-to-cart events, the block falls back to the category centroid (mean vector of all SKUs in the same leaf category). This avoids ranking a fresh SKU against wrong neighbours before its embedding has been behaviour-validated.
  • Day 14+ — behavioural reweighting. Once thresholds clear, a 5-feature reranker (CTR, conversion, AOV contribution, return rate, stock level) reorders the cosine-similar candidates.
-- Category centroid: refreshed nightly
INSERT INTO category_embedding_centroid (category_id, vector, sku_count, updated_at)
SELECT pc.category_id,
       AVG(pe.vector)::vector(1536) AS vector,
       COUNT(*)                     AS sku_count,
       NOW()
FROM product_embeddings pe
JOIN product_category pc ON pc.sku = pe.sku
GROUP BY pc.category_id
ON CONFLICT (category_id)
DO UPDATE SET vector = EXCLUDED.vector,
              sku_count = EXCLUDED.sku_count,
              updated_at = NOW();

Section 5 — ROI math: the break-even comparison

At a representative 100,000 monthly sessions, ~2% conversion, $80 AOV — that is $160,000/month in baseline revenue.

ComponentAdobe Sensei (Adobe Commerce)Custom OpenAI embeddings
License or subscription~$22,000/year Adobe Commerce floor$0 (Open Source compatible)
Initial build effort~16h Sensei storefront wiring~12h CLI + block + schema (~$300 @ $25/hr)
Embedding API costincluded~$1.00/month for 50K SKUs nightly delta
Vector storeAdobe managedpgvector (free) or OpenSearch (already running)
Cache layerincluded~$5/month Redis (already running)
Ranking transparencyblack boxfull — inspect vectors, weights, query plan
Model portabilityAdobe-lockedswap to text-embedding-3-large or self-hosted in one config line
Reported CTR uplift+3–7%[1]+2–6% (our 8-project observed band)
Reported AOV uplift+5–10%[1]+3–8% (observed)
Annual cost floor~$22,000~$372 (build) + $72/yr ops

The break-even calculation that decides the project:

  • Sensei break-even. At $1.92M/year baseline, $22K/year is 1.15% of revenue. Sensei needs to drive ~0.4% incremental revenue across the storefront to recoup the license alone (only honest framing if you would not have bought Adobe Commerce otherwise).
  • Custom break-even. At ~$444/year total, the custom stack needs ~0.04% incremental revenue — roughly $770 over a full year. One extra order per fortnight. In every project we have shipped, break-even fell inside week one.

Section 6 — When Adobe Sensei is still the right answer

The three scenarios where Sensei beats the custom stack on operational merit, not just on cost:

  • Already on Adobe Commerce. Sensei is included. Marginal cost is zero. Storefront wiring ~16h. Skip the embedding build, use what is bought.
  • Over 500K SKUs at 1M+ monthly sessions. Sensei's behavioural collaborative filter at that scale outperforms a vanilla cosine setup. The custom stack can match it but the reranker layer needs more engineering attention.
  • Zero in-house engineering. Sensei is "turn it on and watch it work". The custom stack is ~12h dev + nightly cron monitoring. If neither is on the table, Sensei wins by default.

Section 7 — Scope honesty and ship schedule

The custom stack nails "More Like This" by construction. "Customers Also Viewed/Bought" need a co-view/co-purchase matrix from behavioural events — a separate week. "Recommended for You" needs user embeddings — another two weeks. Ship More Like This first, validate, layer the behavioural matrices once the win is proven. Realistic 14-day schedule: Day 1–2 schema + embedding CLI + cron; Day 3 first catalog run + spot-checks; Day 4–5 PDP block + Hyvä template + 50/50 A/B harness; Day 6–13 GA4 tracking on CTR + AOV + conversion; Day 14 promote winner or iterate.

FAQ

Can I run Adobe Sensei on Magento Open Source?

No. Adobe's product page is explicit[1]: Sensei Product Recommendations is Adobe Commerce only. No community port, no Adobe IO Runtime endpoint a non-Commerce merchant can authenticate against. The custom embeddings approach is the realistic path on 2.4.4 — 2.4.9.

Why text-embedding-3-small and not text-embedding-3-large?

At 1,536 dimensions and $0.020 per 1M input tokens, text-embedding-3-small hits the catalog sweet spot[2]. text-embedding-3-large is 3,072 dims at $0.130 per 1M — 6.5x cost for marginal quality that does not show up in CTR on catalogs under 500K SKUs. Upgrade path is one config line.

Do I need a separate Postgres instance for pgvector?

No — pgvector is an extension on any PostgreSQL 15+. If your stack is MySQL-only (Magento default), the cleaner path is OpenSearch k-NN. You already run OpenSearch on 2.4.4 — 2.4.9, so adding a k-NN index is one mapping update.

How does it handle product attribute changes?

The nightly job filters on updated_at > NOW() - INTERVAL '24 hours'. Any SKU whose attributes, description, or category changed in 24h gets re-embedded. The vector store update is idempotent (ON CONFLICT DO UPDATE) and the PDP cache key includes the embedding version, so re-embedding invalidates downstream caches automatically.

What is the GDPR posture compared to Sensei?

The embedding job sends product catalog data to OpenAI. No customer PII leaves the store — embeddings are over the catalog, not over behaviour. Sensei in contrast egresses behavioural clickstream to Adobe Experience Platform, which is a heavier GDPR conversation for EU merchants.

Can I A/B test against Magento native related products?

Yes. Split traffic 50/50 at the PDP block via a deterministic hash of the session ID. Track CTR on the widget, downstream conversion, and AOV of orders that touched the widget. Two weeks at 5,000+ PDP views per arm is enough to read a 3-point CTR uplift with 95% confidence.

Does this work on Hyvä themes?

Yes — the recommendation block is a standard Magento block with a Hyvä-compatible PHTML template (Tailwind grid + Alpine.js swipe carousel). No PWA Studio or React layer required.

How is this different from semantic search?

Infrastructure overlaps — same embedding model, same vector store. Semantic search embeds the user's query at request time. Recommendations embed the current PDP (or session history). One pgvector or OpenSearch k-NN index serves both, so once semantic search exists the marginal cost of recommendations is near zero.

Citations

  1. Adobe Sensei — Adobe Commerce Product Recommendations (business.adobe.com/products/sensei)
  2. OpenAI text-embedding-3-small / text-embedding-3-large pricing and dimensions (openai.com/embeddings)
  3. OpenSearch k-NN with HNSW indexing (opensearch.org/docs/knn)
  4. pgvector — Open-source vector similarity search for Postgres (github.com/pgvector/pgvector)
Want a custom OpenAI recommendation engine on your Magento Open Source store?

I scope and ship recommendation stacks on Magento 2.4.4 — 2.4.9 + Hyvä — embedding job, pgvector or OpenSearch k-NN index, PDP block, A/B harness, and a 14-day uplift report. Fixed quote from $499 audit · $2,499 sprint · ~16h @ $25/hr. See hire me.