tech@designanddevelopment.tech +91 9511638160
Build Your Website in 1 Day 100% Money-Back Guarantee
Claim Offer
Free Tools Get A Quote
API Integration Tutorials

Integrating the OpenAI Embeddings API with Laravel for Intelligent Search and Recommendations

Learn step‑by‑step how to connect Laravel to OpenAI’s Embeddings API and build semantic search and personalized recommendation engines for eCommerce and SaaS platforms.

DD D&D TechnologyTech Insights Jun 08, 2026 5 min read
Integrating the OpenAI Embeddings API with Laravel for Intelligent Search and Recommendations
Share:

Integrating the OpenAI Embeddings API with Laravel for Intelligent Search and Recommendations

In today’s digital landscape, delivering fast, relevant results is a key differentiator for eCommerce platforms and SaaS products. Traditional keyword‑based search often falls short when users expect semantic understanding and personalized suggestions. This tutorial shows you how to harness the power of OpenAI Embeddings API inside a Laravel application to create a smart, AI‑driven search and recommendation engine.

Why Use OpenAI Embeddings?

  • Semantic Understanding: Convert text, product titles, or descriptions into high‑dimensional vectors that capture meaning, not just keywords.
  • Scalable Similarity Search: Use vector similarity (cosine, dot‑product) to find the most relevant items in milliseconds.
  • Personalization: Combine user behavior vectors with product embeddings to generate tailored recommendations.
  • AI Automation: Reduce manual tagging and categorisation effort—perfect for startups and enterprises looking for rapid digital transformation.

Prerequisites

Before we dive in, make sure you have the following:

  1. Laravel 9+ installed (we’ll use Laravel 10 in the examples).
  2. Composer and PHP 8.1+.
  3. An OpenAI API key.
  4. MySQL or PostgreSQL database for storing vectors (JSON column works well).
  5. Basic knowledge of Laravel service providers, queues, and Eloquent models.

Step 1 – Set Up the Laravel Project

composer create-project laravel/laravel openai‑search-demo
cd openai‑search-demo
php artisan serve

Open the project in your favorite IDE. Add the OpenAI PHP client library:

composer require openai-php/client

Step 2 – Configure Environment Variables

In .env, add your OpenAI key and a default model for embeddings:

OPENAI_API_KEY=sk-********************
OPENAI_EMBEDDING_MODEL=text-embedding-ada-002

Also, set a dedicated queue connection for background vector generation (Redis is recommended):

QUEUE_CONNECTION=redis

Step 3 – Create a Service Wrapper for the Embeddings API

Generate a service class that abstracts the API call:

php artisan make:service OpenAIEmbeddingService

Replace the generated file app/Services/OpenAIEmbeddingService.php with:

namespace App\Services;

use OpenAI; // Provided by openai-php/client
use Illuminate\Support\Facades\Log;

class OpenAIEmbeddingService
{
    protected $client;
    protected $model;

    public function __construct()
    {
        $this->client = OpenAI::client(config('services.openai.key'));
        $this->model  = config('services.openai.embedding_model');
    }

    /**
     * Generate an embedding vector for a given text.
     */
    public function embed(string $text): array
    {
        try {
            $response = $this->client->embeddings()->create([
                'model' => $this->model,
                'input' => $text,
            ]);
            // OpenAI returns an array of embeddings; we need the first one.
            return $response->data[0]->embedding;
        } catch (\Exception $e) {
            Log::error('OpenAI embedding error: '.$e->getMessage());
            return [];
        }
    }
}

Register the service in config/services.php:

'openai' => [
    'key' => env('OPENAI_API_KEY'),
    'embedding_model' => env('OPENAI_EMBEDDING_MODEL', 'text-embedding-ada-002'),
],

Step 4 – Design the Product Model to Store Vectors

Assume an eCommerce product table with name, description, and a JSON column embedding:

php artisan make:model Product -m

In the migration file:

Schema::create('products', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->text('description');
    $table->json('embedding')->nullable(); // Stores vector as JSON array
    $table->timestamps();
});

Run migrations:

php artisan migrate

Step 5 – Generate Embeddings Asynchronously

Embedding generation can be time‑consuming. Use Laravel queues to process it in the background.

php artisan make:job GenerateProductEmbedding

Job implementation (app/Jobs/GenerateProductEmbedding.php):

namespace App\Jobs;

use App\Models\Product;
use App\Services\OpenAIEmbeddingService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class GenerateProductEmbedding implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $productId;

    public function __construct(int $productId)
    {
        $this->productId = $productId;
    }

    public function handle(OpenAIEmbeddingService $embeddingService)
    {
        $product = Product::find($this->productId);
        if (!$product) return;

        $text = $product->name . ' ' . $product->description;
        $vector = $embeddingService->embed($text);
        if (!empty($vector)) {
            $product->embedding = $vector;
            $product->save();
        }
    }
}

Dispatch the job whenever a product is created or updated:

use App\Jobs\GenerateProductEmbedding;

public function store(Request $request)
{
    $product = Product::create($request->only(['name','description']));
    GenerateProductEmbedding::dispatch($product->id);
    return response()->json($product, 201);
}

Step 6 – Implement Semantic Search

When a user searches, we embed the query and find the nearest product vectors.

php artisan make:controller SearchController

Controller logic (app/Http/Controllers/SearchController.php):

namespace App\Http\Controllers;

use App\Models\Product;
use App\Services\OpenAIEmbeddingService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class SearchController extends Controller
{
    public function search(Request $request, OpenAIEmbeddingService $embeddingService)
    {
        $query = $request->input('q');
        $queryVector = $embeddingService->embed($query);
        if (empty($queryVector)) {
            return response()->json(['error' => 'Embedding failed'], 500);
        }

        // PostgreSQL example using <-> operator for cosine similarity
        $results = Product::select('*')
            ->whereNotNull('embedding')
            ->orderByRaw('embedding <-> ?', [json_encode($queryVector)])
            ->limit(10)
            ->get();

        return response()->json($results);
    }
}

For MySQL 8.0+, you can store vectors as JSON and compute similarity in PHP after fetching a limited set, or use the VECTOR data type via external extensions. The key idea remains: compare the query embedding with stored embeddings.

Step 7 – Build a Recommendation Engine

Recommendations can be built by blending user interaction vectors (e.g., recent clicks) with product embeddings. A simple approach:

  1. Collect user‑item interaction data (views, purchases).
  2. Create a user profile vector by averaging embeddings of interacted products.
  3. Find nearest product vectors that the user hasn’t interacted with.

Example service:

php artisan make:service RecommendationService
namespace App\Services;

use App\Models\Product;
use App\Models\User; // Assume a pivot table user_product_interaction
use Illuminate\Support\Facades\DB;

class RecommendationService
{
    public function recommendForUser(int $userId, int $limit = 5): array
    {
        $interacted = DB::table('user_product_interaction')
            ->where('user_id', $userId)
            ->pluck('product_id')
            ->toArray();

        $vectors = Product::whereIn('id', $interacted)
            ->pluck('embedding')
            ->map(fn($e) => json_decode($e, true))
            ->toArray();

        if (empty($vectors)) return [];

        // Simple average
        $userVector = array_fill(0, count($vectors[0]), 0);
        foreach ($vectors as $vec) {
            foreach ($vec as $i => $val) {
                $userVector[$i] += $val;
            }
        }
        $userVector = array_map(fn($v) => $v / count($vectors), $userVector);

        // Find nearest products not yet interacted with
        $candidates = Product::whereNotIn('id', $interacted)
            ->whereNotNull('embedding')
            ->get();

        $scored = $candidates->map(function ($product) use ($userVector) {
            $embedding = json_decode($product->embedding, true);
            $score = $this->cosineSimilarity($userVector, $embedding);
            $product->score = $score;
            return $product;
        })->sortByDesc('score')->take($limit);

        return $scored->values()->all();
    }

    private function cosineSimilarity(array $a                
Was this article helpful? 4.8 (128 votes)
DD
D&D Technology
We help businesses grow with modern websites, web apps, and digital
solutions powered by the latest technologies.
View All Posts

Join the Conversation

0 Comments
AI

Ready to Add AI in Your Ecommerce Platform?

Launch automation, chatbot, recommendation engine and smart dashboards.

Transparent Process
Clear steps, no hidden charges
Fast Project Kickoff
Start your project immediately
Dedicated Expert Team
Experienced, reliable, innovative
24/7 Support
We're here whenever you need us

Build Your Website in 1 Day

From design to launch — fast turnaround without compromising quality.

Get Started

Launch Your SaaS in 1 Day

Production-ready SaaS platform with auth, payments, and admin — done in 24 hours.

See SaaS Products

100% Money-Back Guarantee

Not satisfied? Get a full refund — no questions asked. Your trust is our priority.

Talk to Us
Flexible Start Plans

Start Your Project with a Small First Step

Pay the essential setup cost or your first EMI, and our team starts building right away.

WEBSITE LAUNCH

Pay Your Domain +
1 Month EMI

Secure your domain, pay your first EMI, and we begin your website design and development immediately.

Domain Setup 1st EMI Website Work Starts
Start Website Project
Perfect for business websites, portfolios & eCommerce
APP LAUNCH

Pay Play Store Fee +
1 Month EMI

Cover your Play Store setup and first EMI, and we start your Android/iOS app design and development.

Play Store Setup 1st EMI App Work Starts
Start App Project
Ideal for startup apps, booking apps & business apps
SOFTWARE LAUNCH

Pay 1 Month EMI &
Start Your Software

Begin your custom software journey with the first EMI and our team starts planning, UI/UX, and development.

1st EMI Project Kickoff Software Development
Start Software Project
Best for ERP, CRM, HRMS, SaaS & custom systems
Transparent EMI ProcessClear pricing, no hidden charges.
Fast Project KickoffStart within 24–48 hours.
Dedicated Expert TeamExperienced, reliable & responsive.