Why Use AI for Product Recommendations?
Traditional ecommerce websites rely on static menus and basic filtering. However, AI product recommendations analyze user behavior, purchase history, and browsing patterns to suggest relevant products dynamically. This personalization can increase conversion rates by up to 300%.
Benefits of AI Integration:
- Personalized Shopping Experience: Each customer sees products tailored to their preferences
- Increased Sales: Relevant suggestions lead to higher conversion rates
- Improved Customer Retention: Smart recommendations keep users engaged
- Automated Inventory Management: AI predicts trending products
Project Structure Overview
Before we begin implementing ecommerce AI integration, let's set up our project structure. Create the following directory layout:
ecommerce-ai-project/
│
├── index.html
├── css/
│ └── style.css
├── js/
│ ├── ai-engine.js
│ └── recommendations.js
├── php/
│ ├── config.php
│ ├── db-connection.php
│ └── api/
│ ├── get-user-behavior.php
│ ├── get-recommendations.php
│ └── save-interaction.php
└── database/
└── schema.sql
Step 1: Database Setup for AI Training
First, we need to create database tables to store user interactions and product data. This data will train our machine learning ecommerce recommendation system.
Create Database Schema (database/schema.sql)
-- Create products table
CREATE TABLE products (
product_id INT PRIMARY KEY AUTO_INCREMENT,
product_name VARCHAR(255) NOT NULL,
category VARCHAR(100),
price DECIMAL(10, 2),
description TEXT,
stock_quantity INT DEFAULT 0,
image_url VARCHAR(500),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Create user behavior table
CREATE TABLE user_behavior (
behavior_id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
product_id INT,
action_type ENUM('view', 'click', 'cart', 'purchase'),
session_id VARCHAR(100),
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (product_id) REFERENCES products(product_id)
);
-- Create user preferences table
CREATE TABLE user_preferences (
preference_id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
category VARCHAR(100),
preference_score FLOAT DEFAULT 0,
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- Create AI recommendations cache
CREATE TABLE ai_recommendations (
recommendation_id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
product_id INT,
confidence_score FLOAT,
recommendation_type VARCHAR(50),
generated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (product_id) REFERENCES products(product_id)
);
-- Insert sample products
INSERT INTO products (product_name, category, price, description, stock_quantity, image_url) VALUES
('Wireless Headphones', 'Electronics', 79.99, 'High-quality Bluetooth headphones', 50, '/images/headphones.jpg'),
('Smart Watch', 'Electronics', 199.99, 'Fitness tracking smartwatch', 30, '/images/smartwatch.jpg'),
('Laptop Stand', 'Accessories', 34.99, 'Ergonomic aluminum laptop stand', 100, '/images/stand.jpg'),
('USB-C Hub', 'Accessories', 45.99, 'Multi-port USB-C adapter', 75, '/images/hub.jpg'),
('Mechanical Keyboard', 'Electronics', 129.99, 'RGB mechanical gaming keyboard', 40, '/images/keyboard.jpg');
Step 2: PHP Configuration and Database Connection
Configure Database Connection (php/config.php)
<?php
// Database configuration
define('DB_HOST', 'localhost');
define('DB_NAME', 'ecommerce_ai');
define('DB_USER', 'your_username');
define('DB_PASS', 'your_password');
// AI Configuration
define('AI_MIN_CONFIDENCE', 0.6); // Minimum confidence score for recommendations
define('AI_MAX_RECOMMENDATIONS', 10);
define('SESSION_TIMEOUT', 1800); // 30 minutes
// Error reporting (disable in production)
error_reporting(E_ALL);
ini_set('display_errors', 1);
?>
Create Database Connection (php/db-connection.php)
<?php
require_once 'config.php';
class Database {
private static $instance = null;
private $connection;
private function __construct() {
try {
$this->connection = new PDO(
"mysql:host=" . DB_HOST . ";dbname=" . DB_NAME,
DB_USER,
DB_PASS,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
} catch(PDOException $e) {
die("Connection failed: " . $e->getMessage());
}
}
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function getConnection() {
return $this->connection;
}
}
?>
Step 3: Track User Behavior (API Endpoint)
Save User Interactions (php/api/save-interaction.php)
<?php
header('Content-Type: application/json');
require_once '../db-connection.php';
$db = Database::getInstance()->getConnection();
// Get POST data
$data = json_decode(file_get_contents('php://input'), true);
$userId = $data['user_id'] ?? null;
$productId = $data['product_id'] ?? null;
$actionType = $data['action_type'] ?? 'view';
$sessionId = session_id() ?: $data['session_id'];
if (!$productId) {
echo json_encode(['success' => false, 'error' => 'Product ID required']);
exit;
}
try {
// Save user behavior
$stmt = $db->prepare("
INSERT INTO user_behavior (user_id, product_id, action_type, session_id)
VALUES (:user_id, :product_id, :action_type, :session_id)
");
$stmt->execute([
':user_id' => $userId,
':product_id' => $productId,
':action_type' => $actionType,
':session_id' => $sessionId
]);
// Update user preferences
if ($userId) {
$categoryStmt = $db->prepare("
SELECT category FROM products WHERE product_id = :product_id
");
$categoryStmt->execute([':product_id' => $productId]);
$category = $categoryStmt->fetchColumn();
if ($category) {
$prefStmt = $db->prepare("
INSERT INTO user_preferences (user_id, category, preference_score)
VALUES (:user_id, :category, 1)
ON DUPLICATE KEY UPDATE
preference_score = preference_score + 1
");
$prefStmt->execute([
':user_id' => $userId,
':category' => $category
]);
}
}
echo json_encode(['success' => true, 'message' => 'Interaction saved']);
} catch(PDOException $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
?>
Step 4: AI Recommendation Engine
Generate AI Recommendations (php/api/get-recommendations.php)
<?php
header('Content-Type: application/json');
require_once '../db-connection.php';
require_once '../config.php';
$db = Database::getInstance()->getConnection();
$userId = $_GET['user_id'] ?? null;
$sessionId = $_GET['session_id'] ?? session_id();
$limit = $_GET['limit'] ?? AI_MAX_RECOMMENDATIONS;
try {
$recommendations = [];
if ($userId) {
// Collaborative filtering based on user preferences
$stmt = $db->prepare("
SELECT
p.product_id,
p.product_name,
p.category,
p.price,
p.image_url,
up.preference_score,
(up.preference_score / (SELECT MAX(preference_score) FROM user_preferences WHERE user_id = :user_id)) as confidence_score
FROM products p
INNER JOIN user_preferences up ON p.category = up.category
WHERE up.user_id = :user_id
AND p.stock_quantity > 0
AND p.product_id NOT IN (
SELECT product_id FROM user_behavior
WHERE user_id = :user_id AND action_type = 'purchase'
)
ORDER BY up.preference_score DESC
LIMIT :limit
");
$stmt->bindParam(':user_id', $userId, PDO::PARAM_INT);
$stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
$stmt->execute();
$recommendations = $stmt->fetchAll();
} else {
// Session-based recommendations
$stmt = $db->prepare("
SELECT
p.product_id,
p.product_name,
p.category,
p.price,
p.image_url,
COUNT(ub.behavior_id) as interaction_count,
0.7 as confidence_score
FROM products p
INNER JOIN user_behavior ub ON p.category = (
SELECT category FROM products
WHERE product_id IN (
SELECT product_id FROM user_behavior WHERE session_id = :session_id
)
LIMIT 1
)
WHERE p.stock_quantity > 0
AND p.product_id NOT IN (
SELECT product_id FROM user_behavior WHERE session_id = :session_id
)
GROUP BY p.product_id
ORDER BY interaction_count DESC
LIMIT :limit
");
$stmt->bindParam(':session_id', $sessionId, PDO::PARAM_STR);
$stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
$stmt->execute();
$recommendations = $stmt->fetchAll();
}
// If no recommendations found, show popular products
if (empty($recommendations)) {
$stmt = $db->prepare("
SELECT
p.product_id,
p.product_name,
p.category,
p.price,
p.image_url,
COUNT(ub.behavior_id) as popularity,
0.5 as confidence_score
FROM products p
LEFT JOIN user_behavior ub ON p.product_id = ub.product_id
WHERE p.stock_quantity > 0
GROUP BY p.product_id
ORDER BY popularity DESC
LIMIT :limit
");
$stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
$stmt->execute();
$recommendations = $stmt->fetchAll();
}
echo json_encode([
'success' => true,
'recommendations' => $recommendations,
'count' => count($recommendations)
]);
} catch(PDOException $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
?>
Step 5: JavaScript AI Engine
Create AI Processing Logic (js/ai-engine.js)
class AIEngine {
constructor() {
this.userId = this.getUserId();
this.sessionId = this.getSessionId();
this.behaviorQueue = [];
this.recommendationCache = null;
this.cacheExpiry = 300000; // 5 minutes
this.lastCacheTime = null;
}
getUserId() {
return localStorage.getItem('user_id') || null;
}
getSessionId() {
let sessionId = sessionStorage.getItem('session_id');
if (!sessionId) {
sessionId = 'sess_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
sessionStorage.setItem('session_id', sessionId);
}
return sessionId;
}
async trackInteraction(productId, actionType = 'view') {
const data = {
user_id: this.userId,
product_id: productId,
action_type: actionType,
session_id: this.sessionId
};
try {
const response = await fetch('php/api/save-interaction.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
const result = await response.json();
if (result.success) {
console.log('Interaction tracked:', actionType, productId);
// Invalidate cache after new interaction
this.recommendationCache = null;
}
return result;
} catch (error) {
console.error('Error tracking interaction:', error);
return { success: false, error: error.message };
}
}
async getRecommendations(limit = 10) {
// Return cached recommendations if valid
if (this.recommendationCache && this.lastCacheTime) {
const cacheAge = Date.now() - this.lastCacheTime;
if (cacheAge < this.cacheExpiry) {
console.log('Returning cached recommendations');
return this.recommendationCache;
}
}
const params = new URLSearchParams({
user_id: this.userId || '',
session_id: this.sessionId,
limit: limit
});
try {
const response = await fetch(`php/api/get-recommendations.php?${params}`);
const result = await response.json();
if (result.success) {
this.recommendationCache = result.recommendations;
this.lastCacheTime = Date.now();
return result.recommendations;
}
return [];
} catch (error) {
console.error('Error fetching recommendations:', error);
return [];
}
}
calculateSimilarity(product1, product2) {
// Simple similarity calculation based on category and price range
let similarity = 0;
if (product1.category === product2.category) {
similarity += 0.5;
}
const priceDiff = Math.abs(product1.price - product2.price);
const avgPrice = (product1.price + product2.price) / 2;
const priceSimiliarity = 1 - (priceDiff / avgPrice);
similarity += priceSimiliarity * 0.5;
return similarity;
}
async generateSmartMenu(currentProduct) {
const recommendations = await this.getRecommendations(6);
// If on a product page, filter recommendations based on similarity
if (currentProduct) {
recommendations.sort((a, b) => {
const simA = this.calculateSimilarity(currentProduct, a);
const simB = this.calculateSimilarity(currentProduct, b);
return simB - simA;
});
}
return recommendations;
}
}
// Initialize AI Engine
const aiEngine = new AIEngine();
Step 6: Frontend Recommendation Display
Create Recommendation UI (js/recommendations.js)
class RecommendationUI {
constructor(aiEngine) {
this.aiEngine = aiEngine;
this.container = null;
}
async displayRecommendations(containerId, options = {}) {
this.container = document.getElementById(containerId);
if (!this.container) {
console.error('Recommendation container not found');
return;
}
const {
title = 'Recommended For You',
limit = 6,
currentProduct = null
} = options;
// Show loading state
this.container.innerHTML = `
<div class="recommendations-section">
<h2 class="recommendations-title">${title}</h2>
<div class="loading">Loading recommendations...</div>
</div>
`;
const recommendations = await this.aiEngine.getRecommendations(limit);
if (recommendations.length === 0) {
this.container.innerHTML = `
<div class="recommendations-section">
<h2 class="recommendations-title">${title}</h2>
<p>No recommendations available at the moment.</p>
</div>
`;
return;
}
this.renderProducts(recommendations, title);
}
renderProducts(products, title) {
const productsHTML = products.map(product => `
<div class="product-card" data-product-id="${product.product_id}">
<div class="product-image">
<img src="${product.image_url}" alt="${product.product_name}" loading="lazy">
<span class="confidence-badge">
${Math.round(product.confidence_score * 100)}% Match
</span>
</div>
<div class="product-info">
<h3 class="product-name">${product.product_name}</h3>
<p class="product-category">${product.category}</p>
<p class="product-price">$${parseFloat(product.price).toFixed(2)}</p>
<button class="btn-view-product" onclick="viewProduct(${product.product_id})">
View Details
</button>
</div>
</div>
`).join('');
this.container.innerHTML = `
<div class="recommendations-section">
<h2 class="recommendations-title">${title}</h2>
<div class="products-grid">
${productsHTML}
</div>
</div>
`;
this.attachEventListeners();
}
attachEventListeners() {
const productCards = this.container.querySelectorAll('.product-card');
productCards.forEach(card => {
const productId = card.dataset.productId;
card.addEventListener('click', () => {
this.aiEngine.trackInteraction(productId, 'click');
});
const viewBtn = card.querySelector('.btn-view-product');
viewBtn?.addEventListener('click', (e) => {
e.stopPropagation();
this.aiEngine.trackInteraction(productId, 'view');
});
});
}
}
// Helper function for product view
async function viewProduct(productId) {
await aiEngine.trackInteraction(productId, 'view');
window.location.href = `product.html?id=${productId}`;
}
// Helper function for add to cart
async function addToCart(productId) {
await aiEngine.trackInteraction(productId, 'cart');
// Add your cart logic here
alert('Product added to cart!');
}
// Initialize Recommendation UI
const recommendationUI = new RecommendationUI(aiEngine);
Step 7: Main HTML Implementation
Create Homepage (index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI-Powered Ecommerce Store</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<header>
<nav class="navbar">
<div class="container">
<h1 class="logo">AI Store</h1>
<ul class="nav-menu">
<li><a href="index.html">Home</a></li>
<li><a href="#products">Products</a></li>
<li><a href="#recommendations">For You</a></li>
<li><a href="cart.html">Cart</a></li>
</ul>
</div>
</nav>
</header>
<main>
<section class="hero">
<div class="container">
<h2>Smart Shopping with AI Recommendations</h2>
<p>Discover products tailored just for you</p>
</div>
</section>
<!-- AI Recommendations Section -->
<section class="recommendations">
<div class="container">
<div id="ai-recommendations"></div>
</div>
</section>
<!-- All Products Section -->
<section id="products" class="all-products">
<div class="container">
<h2>All Products</h2>
<div id="products-list"></div>
</div>
</section>
</main>
<footer>
<p>© 2025 AI-Powered Ecommerce. All rights reserved.</p>
</footer>
<script src="js/ai-engine.js"></script>
<script src="js/recommendations.js"></script>
<script>
// Initialize AI recommendations on page load
document.addEventListener('DOMContentLoaded', async function() {
await recommendationUI.displayRecommendations('ai-recommendations', {
title: 'Recommended Just For You',
limit: 6
});
});
</script>
</body>
</html>
Step 8: Styling the AI Recommendation Interface
Create Stylesheet (css/style.css)
/* Global Styles */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: #333;
background-color: #f8f9fa;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
/* Navigation */
.navbar {
background: linear-gradient(135deg, #01AEEF 0%, #0088cc 100%);
color: white;
padding: 1rem 0;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.navbar .container {
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
font-size: 1.8rem;
font-weight: bold;
}
.nav-menu {
display: flex;
list-style: none;
gap: 2rem;
}
.nav-menu a {
color: white;
text-decoration: none;
font-weight: 500;
transition: opacity 0.3s;
}
.nav-menu a:hover {
opacity: 0.8;
}
/* Hero Section */
.hero {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 4rem 0;
text-align: center;
}
.hero h2 {
font-size: 2.5rem;
margin-bottom: 1rem;
}
/* Recommendations Section */
.recommendations {
padding: 3rem 0;
background-color: white;
}
.recommendations-section {
width: 100%;
}
.recommendations-title {
font-size: 2rem;
color: #333;
margin-bottom: 2rem;
text-align: center;
position: relative;
}
.recommendations-title::after {
content: '';
display: block;
width: 80px;
height: 4px;
background: #01AEEF;
margin: 10px auto 0;
border-radius: 2px;
}
/* Products Grid */
.products-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 2rem;
margin-top: 2rem;
}
/* Product Card */
.product-card {
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
transition: transform 0.3s, box-shadow 0.3s;
cursor: pointer;
}
.product-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 15px rgba(0,0,0,0.2);
}
.product-image {
position: relative;
width: 100%;
height: 250px;
overflow: hidden;
background: #f0f0f0;
}
.product-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.confidence-badge {
position: absolute;
top: 10px;
right: 10px;
background: rgba(1, 174, 239, 0.95);
color: white;
padding: 5px 12px;
border-radius: 20px;
font-size: 0.85rem;
font-weight: bold;
}
.product-info {
padding: 1.5rem;
}
.product-name {
font-size: 1.2rem;
color: #333;
margin-bottom: 0.5rem;
font-weight: 600;
}
.product-category {
color: #666;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.product-price {
font-size: 1.5rem;
color: #01AEEF;
font-weight: bold;
margin: 1rem 0;
}
.btn-view-product {
width: 100%;
padding: 12px;
background: linear-gradient(135deg, #01AEEF 0%, #0088cc 100%);
color: white;
border: none;
border-radius: 6px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
}
.btn-view-product:hover {
transform: scale(1.02);
box-shadow: 0 4px 12px rgba(1, 174, 239, 0.4);
}
/* Loading State */
.loading {
text-align: center;
padding: 3rem;
font-size: 1.2rem;
color: #666;
}
/* All Products Section */
.all-products {
padding: 3rem 0;
background-color: #f8f9fa;
}
.all-products h2 {
font-size: 2rem;
margin-bottom: 2rem;
text-align: center;
}
/* Footer */
footer {
background: #333;
color: white;
text-align: center;
padding: 2rem 0;
margin-top: 3rem;
}
/* Responsive Design */
@media (max-width: 768px) {
.products-grid {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
}
.hero h2 {
font-size: 1.8rem;
}
.recommendations-title {
font-size: 1.5rem;
}
.nav-menu {
gap: 1rem;
}
}
@media (max-width: 480px) {
.products-grid {
grid-template-columns: 1fr;
}
}
Step 9: Advanced AI Features
Implementing Real-Time AI Menu Suggestions
Now let's add a dynamic AI menu suggestion feature that appears as users browse. Create a new file for the dynamic menu:
Smart Menu Component (js/smart-menu.js)
class SmartMenu {
constructor(aiEngine) {
this.aiEngine = aiEngine;
this.menuVisible = false;
this.currentCategory = null;
this.initializeMenu();
}
initializeMenu() {
// Create floating AI menu
const menuHTML = `
<div id="smart-menu" class="smart-menu hidden">
<div class="smart-menu-header">
<h3>AI Suggestions</h3>
<button class="close-menu" onclick="smartMenu.hideMenu()">×</button>
</div>
<div class="smart-menu-content">
<div id="menu-recommendations"></div>
</div>
</div>
<button id="ai-menu-trigger" class="ai-menu-trigger" onclick="smartMenu.toggleMenu()">
<span>AI Picks</span>
</button>
`;
document.body.insertAdjacentHTML('beforeend', menuHTML);
this.setupEventListeners();
}
setupEventListeners() {
// Track scroll behavior
let scrollTimeout;
window.addEventListener('scroll', () => {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(() => {
this.updateMenuBasedOnScroll();
}, 500);
});
// Track category changes
document.addEventListener('categoryChange', (e) => {
this.currentCategory = e.detail.category;
this.refreshMenu();
});
}
async updateMenuBasedOnScroll() {
const scrollPercent = (window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100;
// Show menu suggestion after 30% scroll
if (scrollPercent > 30 && !this.menuVisible) {
await this.refreshMenu();
}
}
async refreshMenu() {
const recommendations = await this.aiEngine.getRecommendations(4);
this.renderMenuItems(recommendations);
}
renderMenuItems(items) {
const menuContent = document.getElementById('menu-recommendations');
if (!menuContent) return;
const itemsHTML = items.map(item => `
<div class="menu-item" data-product-id="${item.product_id}">
<img src="${item.image_url}" alt="${item.product_name}">
<div class="menu-item-info">
<h4>${item.product_name}</h4>
<p class="price">${parseFloat(item.price).toFixed(2)}</p>
<span class="match-badge">${Math.round(item.confidence_score * 100)}% Match</span>
</div>
</div>
`).join('');
menuContent.innerHTML = itemsHTML;
// Add click handlers
document.querySelectorAll('.menu-item').forEach(item => {
item.addEventListener('click', () => {
const productId = item.dataset.productId;
this.aiEngine.trackInteraction(productId, 'click');
viewProduct(productId);
});
});
}
toggleMenu() {
const menu = document.getElementById('smart-menu');
if (this.menuVisible) {
this.hideMenu();
} else {
this.showMenu();
}
}
async showMenu() {
const menu = document.getElementById('smart-menu');
menu.classList.remove('hidden');
this.menuVisible = true;
await this.refreshMenu();
}
hideMenu() {
const menu = document.getElementById('smart-menu');
menu.classList.add('hidden');
this.menuVisible = false;
}
}
// Initialize Smart Menu
let smartMenu;
document.addEventListener('DOMContentLoaded', () => {
smartMenu = new SmartMenu(aiEngine);
});
Add Smart Menu Styles to CSS (css/style.css)
/* Smart AI Menu */
.smart-menu {
position: fixed;
right: 20px;
top: 50%;
transform: translateY(-50%);
width: 320px;
background: white;
border-radius: 16px;
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
z-index: 1000;
transition: all 0.3s ease;
}
.smart-menu.hidden {
opacity: 0;
pointer-events: none;
transform: translateY(-50%) scale(0.9);
}
.smart-menu-header {
background: linear-gradient(135deg, #01AEEF 0%, #0088cc 100%);
color: white;
padding: 1rem;
border-radius: 16px 16px 0 0;
display: flex;
align-items: center;
gap: 10px;
}
.ai-icon {
font-size: 1.5rem;
}
.smart-menu-header h3 {
flex: 1;
font-size: 1.1rem;
}
.close-menu {
background: none;
border: none;
color: white;
font-size: 2rem;
cursor: pointer;
line-height: 1;
padding: 0;
width: 30px;
height: 30px;
}
.smart-menu-content {
padding: 1rem;
max-height: 400px;
overflow-y: auto;
}
.menu-item {
display: flex;
gap: 12px;
padding: 12px;
border-radius: 8px;
cursor: pointer;
transition: background 0.2s;
margin-bottom: 10px;
}
.menu-item:hover {
background: #f0f9ff;
}
.menu-item img {
width: 60px;
height: 60px;
object-fit: cover;
border-radius: 6px;
}
.menu-item-info {
flex: 1;
}
.menu-item-info h4 {
font-size: 0.95rem;
margin-bottom: 5px;
color: #333;
}
.menu-item-info .price {
color: #01AEEF;
font-weight: bold;
font-size: 1.1rem;
}
.match-badge {
display: inline-block;
background: #e8f8ff;
color: #01AEEF;
padding: 2px 8px;
border-radius: 12px;
font-size: 0.75rem;
font-weight: 600;
margin-top: 5px;
}
/* Floating AI Trigger Button */
.ai-menu-trigger {
position: fixed;
right: 20px;
bottom: 30px;
width: 60px;
height: 60px;
border-radius: 50%;
background: linear-gradient(135deg, #01AEEF 0%, #0088cc 100%);
color: white;
border: none;
box-shadow: 0 4px 20px rgba(1, 174, 239, 0.4);
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: 0.7rem;
font-weight: bold;
z-index: 999;
transition: all 0.3s;
}
.ai-menu-trigger:hover {
transform: scale(1.1);
box-shadow: 0 6px 25px rgba(1, 174, 239, 0.5);
}
.ai-menu-trigger span:first-child {
font-size: 1.5rem;
}
@media (max-width: 768px) {
.smart-menu {
right: 10px;
width: calc(100% - 20px);
max-width: 320px;
}
}
Step 10: Testing and Optimization
Performance Optimization Tips
To ensure your machine learning ecommerce system performs optimally:
- Cache Recommendations: Store AI recommendations in memory for 5 minutes to reduce database queries
- Batch Processing: Process user behavior data in batches rather than individual requests
- Index Database: Add indexes to frequently queried columns (user_id, product_id, category)
- CDN for Images: Use a CDN to serve product images faster
- Lazy Loading: Load recommendations only when the section becomes visible
Add Database Indexes (database/indexes.sql)
-- Optimize query performance with indexes
CREATE INDEX idx_user_behavior_user ON user_behavior(user_id);
CREATE INDEX idx_user_behavior_product ON user_behavior(product_id);
CREATE INDEX idx_user_behavior_session ON user_behavior(session_id);
CREATE INDEX idx_user_behavior_action ON user_behavior(action_type);
CREATE INDEX idx_user_preferences_user ON user_preferences(user_id);
CREATE INDEX idx_user_preferences_category ON user_preferences(category);
CREATE INDEX idx_products_category ON products(category);
CREATE INDEX idx_products_price ON products(price);
CREATE INDEX idx_ai_recommendations_user ON ai_recommendations(user_id);
-- Composite indexes for complex queries
CREATE INDEX idx_behavior_user_action ON user_behavior(user_id, action_type);
CREATE INDEX idx_behavior_session_timestamp ON user_behavior(session_id, timestamp);
Step 11: Advanced AI Algorithms
Implementing Collaborative Filtering
For more sophisticated AI product recommendations, add collaborative filtering:
<?php
// php/api/collaborative-filtering.php
header('Content-Type: application/json');
require_once '../db-connection.php';
$db = Database::getInstance()->getConnection();
$userId = $_GET['user_id'] ?? null;
if (!$userId) {
echo json_encode(['success' => false, 'error' => 'User ID required']);
exit;
}
try {
// Find similar users based on purchase history
$stmt = $db->prepare("
SELECT
ub2.user_id as similar_user_id,
COUNT(DISTINCT ub2.product_id) as common_products,
GROUP_CONCAT(DISTINCT ub2.product_id) as their_products
FROM user_behavior ub1
INNER JOIN user_behavior ub2
ON ub1.product_id = ub2.product_id
AND ub1.user_id != ub2.user_id
WHERE ub1.user_id = :user_id
AND ub1.action_type IN ('purchase', 'cart')
AND ub2.action_type IN ('purchase', 'cart')
GROUP BY ub2.user_id
HAVING common_products >= 2
ORDER BY common_products DESC
LIMIT 10
");
$stmt->execute([':user_id' => $userId]);
$similarUsers = $stmt->fetchAll();
if (empty($similarUsers)) {
echo json_encode(['success' => true, 'recommendations' => []]);
exit;
}
$similarUserIds = array_column($similarUsers, 'similar_user_id');
$placeholders = str_repeat('?,', count($similarUserIds) - 1) . '?';
// Get products that similar users liked but current user hasn't interacted with
$recStmt = $db->prepare("
SELECT
p.product_id,
p.product_name,
p.category,
p.price,
p.image_url,
COUNT(DISTINCT ub.user_id) as popularity,
AVG(CASE WHEN ub.action_type = 'purchase' THEN 1.0
WHEN ub.action_type = 'cart' THEN 0.8
WHEN ub.action_type = 'click' THEN 0.5
ELSE 0.3 END) as confidence_score
FROM user_behavior ub
INNER JOIN products p ON ub.product_id = p.product_id
WHERE ub.user_id IN ($placeholders)
AND p.stock_quantity > 0
AND p.product_id NOT IN (
SELECT product_id FROM user_behavior WHERE user_id = ?
)
GROUP BY p.product_id
ORDER BY popularity DESC, confidence_score DESC
LIMIT 10
");
$params = array_merge($similarUserIds, [$userId]);
$recStmt->execute($params);
$recommendations = $recStmt->fetchAll();
echo json_encode([
'success' => true,
'recommendations' => $recommendations,
'similar_users_count' => count($similarUsers)
]);
} catch(PDOException $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
?>
Conclusion and Best Practices
You've successfully implemented a comprehensive AI in ecommerce system with intelligent product recommendations and smart menu suggestions. Here are key takeaways:
Best Practices for AI Ecommerce Integration:
- Data Privacy: Always anonymize user data and comply with GDPR/privacy regulations
- A/B Testing: Test AI recommendations against traditional methods to measure improvement
- Continuous Learning: Regularly retrain your AI model with new user behavior data
- Fallback Mechanisms: Always have default recommendations when AI can't generate personalized ones
- Performance Monitoring: Track recommendation click-through rates and conversion metrics
- Mobile Optimization: Ensure AI features work seamlessly on mobile devices
- User Control: Allow users to customize or disable AI recommendations if they prefer
Next Steps:
- Integrate with actual payment gateways
- Add user authentication system
- Implement more advanced ML algorithms (neural networks, deep learning)
- Add real-time chat support with AI chatbots
- Create admin dashboard to monitor AI performance
- Implement A/B testing framework
By following this guide, you now have a fully functional AI-powered ecommerce website with intelligent product recommendations and dynamic menu suggestions. The system learns from user behavior and continuously improves its suggestions over time, leading to better customer experiences and higher conversion rates.
Additional Resources:
- TensorFlow.js for client-side machine learning
- scikit-learn for Python-based ML models
- Google Analytics for tracking AI recommendation performance
- Redis for caching recommendation data
Remember: The key to successful ecommerce AI integration is continuous optimization and testing. Monitor your AI system's performance regularly and adjust algorithms based on real user data.
Step 12: Implementing AI-Powered Search
Intelligent Search with Auto-Suggestions
Enhance your AI in ecommerce platform with smart search functionality that learns from user queries and provides relevant suggestions.
Create Search API (php/api/ai-search.php)
<?php
header('Content-Type: application/json');
require_once '../db-connection.php';
$db = Database::getInstance()->getConnection();
$query = $_GET['q'] ?? '';
$userId = $_GET['user_id'] ?? null;
$limit = $_GET['limit'] ?? 10;
if (strlen($query) < 2) {
echo json_encode(['success' => false, 'error' => 'Query too short']);
exit;
}
try {
// Log search query for AI learning
if ($userId) {
$logStmt = $db->prepare("
INSERT INTO search_queries (user_id, query, timestamp)
VALUES (:user_id, :query, NOW())
");
$logStmt->execute([
':user_id' => $userId,
':query' => $query
]);
}
// Search with AI relevance scoring
$searchStmt = $db->prepare("
SELECT
p.product_id,
p.product_name,
p.category,
p.price,
p.image_url,
p.description,
(
MATCH(p.product_name, p.description) AGAINST(:query IN NATURAL LANGUAGE MODE) * 2 +
(CASE WHEN p.category LIKE :query_like THEN 1 ELSE 0 END) +
(SELECT COUNT(*) FROM user_behavior ub WHERE ub.product_id = p.product_id) * 0.01
) as relevance_score,
(SELECT AVG(preference_score)
FROM user_preferences
WHERE user_id = :user_id AND category = p.category) as personalization_score
FROM products p
WHERE (
MATCH(p.product_name, p.description) AGAINST(:query IN NATURAL LANGUAGE MODE)
OR p.product_name LIKE :query_like
OR p.category LIKE :query_like
)
AND p.stock_quantity > 0
ORDER BY
COALESCE(personalization_score, 0) DESC,
relevance_score DESC
LIMIT :limit
");
$queryLike = '%' . $query . '%';
$searchStmt->bindParam(':query', $query, PDO::PARAM_STR);
$searchStmt->bindParam(':query_like', $queryLike, PDO::PARAM_STR);
$searchStmt->bindParam(':user_id', $userId, PDO::PARAM_INT);
$searchStmt->bindParam(':limit', $limit, PDO::PARAM_INT);
$searchStmt->execute();
$results = $searchStmt->fetchAll();
// Get search suggestions
$suggestionStmt = $db->prepare("
SELECT DISTINCT query, COUNT(*) as frequency
FROM search_queries
WHERE query LIKE :query_like
GROUP BY query
ORDER BY frequency DESC
LIMIT 5
");
$suggestionStmt->execute([':query_like' => $query . '%']);
$suggestions = $suggestionStmt->fetchAll();
echo json_encode([
'success' => true,
'results' => $results,
'suggestions' => $suggestions,
'count' => count($results)
]);
} catch(PDOException $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
?>
Add Search Queries Table (database/search-schema.sql)
-- Create search queries table for AI learning
CREATE TABLE search_queries (
query_id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
query VARCHAR(255) NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_query (query),
INDEX idx_user_query (user_id, query)
);
-- Add full-text indexes for better search performance
ALTER TABLE products ADD FULLTEXT INDEX idx_fulltext_search (product_name, description);
-- Create search analytics table
CREATE TABLE search_analytics (
analytics_id INT PRIMARY KEY AUTO_INCREMENT,
query VARCHAR(255),
results_count INT,
click_through_rate DECIMAL(5,2),
conversion_rate DECIMAL(5,2),
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY unique_query (query)
);
Frontend Search Implementation (js/ai-search.js)
class AISearch {
constructor(aiEngine) {
this.aiEngine = aiEngine;
this.searchInput = null;
this.searchResults = null;
this.suggestionBox = null;
this.debounceTimer = null;
this.minQueryLength = 2;
}
initialize(inputId, resultsId) {
this.searchInput = document.getElementById(inputId);
this.searchResults = document.getElementById(resultsId);
if (!this.searchInput || !this.searchResults) {
console.error('Search elements not found');
return;
}
this.createSuggestionBox();
this.attachEventListeners();
}
createSuggestionBox() {
const suggestionBox = document.createElement('div');
suggestionBox.id = 'search-suggestions';
suggestionBox.className = 'search-suggestions hidden';
this.searchInput.parentElement.appendChild(suggestionBox);
this.suggestionBox = suggestionBox;
}
attachEventListeners() {
this.searchInput.addEventListener('input', (e) => {
clearTimeout(this.debounceTimer);
const query = e.target.value.trim();
if (query.length < this.minQueryLength) {
this.hideSuggestions();
return;
}
this.debounceTimer = setTimeout(() => {
this.performSearch(query);
}, 300);
});
this.searchInput.addEventListener('focus', () => {
if (this.suggestionBox.children.length > 0) {
this.suggestionBox.classList.remove('hidden');
}
});
document.addEventListener('click', (e) => {
if (!this.searchInput.contains(e.target) && !this.suggestionBox.contains(e.target)) {
this.hideSuggestions();
}
});
}
async performSearch(query) {
const params = new URLSearchParams({
q: query,
user_id: this.aiEngine.userId || '',
limit: 20
});
try {
const response = await fetch(`php/api/ai-search.php?${params}`);
const data = await response.json();
if (data.success) {
this.displayResults(data.results);
this.displaySuggestions(data.suggestions, query);
}
} catch (error) {
console.error('Search error:', error);
}
}
displayResults(results) {
if (results.length === 0) {
this.searchResults.innerHTML = `
<div class="no-results">
<p>No products found. Try different keywords.</p>
</div>
`;
return;
}
const resultsHTML = results.map(product => `
<div class="search-result-item" data-product-id="${product.product_id}">
<img src="${product.image_url}" alt="${product.product_name}" class="result-image">
<div class="result-info">
<h3 class="result-title">${product.product_name}</h3>
<p class="result-category">${product.category}</p>
<p class="result-price">${parseFloat(product.price).toFixed(2)}</p>
${product.relevance_score ? `<span class="relevance-badge">${Math.round(product.relevance_score * 10)}% Match</span>` : ''}
</div>
<button class="btn-add-to-cart" onclick="addToCart(${product.product_id})">Add to Cart</button>
</div>
`).join('');
this.searchResults.innerHTML = `
<div class="search-results-container">
<h2>Search Results (${results.length})</h2>
<div class="results-grid">
${resultsHTML}
</div>
</div>
`;
// Track clicks
document.querySelectorAll('.search-result-item').forEach(item => {
item.addEventListener('click', () => {
const productId = item.dataset.productId;
this.aiEngine.trackInteraction(productId, 'click');
});
});
}
displaySuggestions(suggestions, currentQuery) {
if (suggestions.length === 0) {
this.hideSuggestions();
return;
}
const suggestionsHTML = suggestions
.filter(s => s.query.toLowerCase() !== currentQuery.toLowerCase())
.map(suggestion => `
<div class="suggestion-item" data-query="${suggestion.query}">
<span class="suggestion-icon">?</span>
<span class="suggestion-text">${suggestion.query}</span>
<span class="suggestion-count">${suggestion.frequency} searches</span>
</div>
`).join('');
this.suggestionBox.innerHTML = suggestionsHTML;
this.suggestionBox.classList.remove('hidden');
// Add click handlers
document.querySelectorAll('.suggestion-item').forEach(item => {
item.addEventListener('click', () => {
const query = item.dataset.query;
this.searchInput.value = query;
this.performSearch(query);
this.hideSuggestions();
});
});
}
hideSuggestions() {
this.suggestionBox.classList.add('hidden');
}
}
// Initialize AI Search
let aiSearch;
document.addEventListener('DOMContentLoaded', () => {
aiSearch = new AISearch(aiEngine);
aiSearch.initialize('search-input', 'search-results');
});
Search Styles (Add to css/style.css)
/* AI Search Styles */
.search-container {
position: relative;
max-width: 600px;
margin: 2rem auto;
}
#search-input {
width: 100%;
padding: 15px 50px 15px 20px;
font-size: 1rem;
border: 2px solid #e0e0e0;
border-radius: 30px;
outline: none;
transition: all 0.3s;
}
#search-input:focus {
border-color: #01AEEF;
box-shadow: 0 0 0 3px rgba(1, 174, 239, 0.1);
}
.search-suggestions {
position: absolute;
top: 100%;
left: 0;
right: 0;
background: white;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
margin-top: 8px;
z-index: 100;
overflow: hidden;
}
.search-suggestions.hidden {
display: none;
}
.suggestion-item {
padding: 12px 20px;
display: flex;
align-items: center;
gap: 12px;
cursor: pointer;
transition: background 0.2s;
}
.suggestion-item:hover {
background: #f0f9ff;
}
.suggestion-icon {
font-size: 1.2rem;
}
.suggestion-text {
flex: 1;
color: #333;
font-weight: 500;
}
.suggestion-count {
font-size: 0.85rem;
color: #999;
}
/* Search Results */
.search-results-container {
margin-top: 2rem;
}
.search-results-container h2 {
font-size: 1.5rem;
margin-bottom: 1.5rem;
color: #333;
}
.results-grid {
display: grid;
gap: 1.5rem;
}
.search-result-item {
display: grid;
grid-template-columns: 100px 1fr auto;
gap: 1.5rem;
padding: 1.5rem;
background: white;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
transition: all 0.3s;
cursor: pointer;
align-items: center;
}
.search-result-item:hover {
box-shadow: 0 4px 15px rgba(0,0,0,0.15);
transform: translateY(-2px);
}
.result-image {
width: 100px;
height: 100px;
object-fit: cover;
border-radius: 8px;
}
.result-info {
display: flex;
flex-direction: column;
gap: 8px;
}
.result-title {
font-size: 1.2rem;
color: #333;
margin: 0;
}
.result-category {
color: #666;
font-size: 0.9rem;
}
.result-price {
font-size: 1.3rem;
color: #01AEEF;
font-weight: bold;
}
.relevance-badge {
display: inline-block;
background: #e8f8ff;
color: #01AEEF;
padding: 4px 10px;
border-radius: 12px;
font-size: 0.85rem;
font-weight: 600;
}
.btn-add-to-cart {
padding: 12px 24px;
background: linear-gradient(135deg, #01AEEF 0%, #0088cc 100%);
color: white;
border: none;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
white-space: nowrap;
}
.btn-add-to-cart:hover {
transform: scale(1.05);
box-shadow: 0 4px 12px rgba(1, 174, 239, 0.3);
}
.no-results {
text-align: center;
padding: 3rem;
color: #666;
}
@media (max-width: 768px) {
.search-result-item {
grid-template-columns: 80px 1fr;
gap: 1rem;
}
.btn-add-to-cart {
grid-column: 1 / -1;
width: 100%;
}
.result-image {
width: 80px;
height: 80px;
}
}
Step 13: Real-Time Analytics Dashboard
Monitor AI Performance
Create an admin dashboard to track how well your AI product recommendations are performing.
Analytics API (php/api/get-analytics.php)
<?php
header('Content-Type: application/json');
require_once '../db-connection.php';
$db = Database::getInstance()->getConnection();
$dateFrom = $_GET['date_from'] ?? date('Y-m-d', strtotime('-30 days'));
$dateTo = $_GET['date_to'] ?? date('Y-m-d');
try {
// Recommendation performance
$perfStmt = $db->prepare("
SELECT
DATE(ar.generated_at) as date,
COUNT(DISTINCT ar.recommendation_id) as recommendations_shown,
COUNT(DISTINCT CASE WHEN ub.action_type = 'click' THEN ub.behavior_id END) as clicks,
COUNT(DISTINCT CASE WHEN ub.action_type = 'cart' THEN ub.behavior_id END) as add_to_cart,
COUNT(DISTINCT CASE WHEN ub.action_type = 'purchase' THEN ub.behavior_id END) as purchases,
ROUND(
COUNT(DISTINCT CASE WHEN ub.action_type = 'click' THEN ub.behavior_id END) * 100.0 /
COUNT(DISTINCT ar.recommendation_id), 2
) as click_through_rate,
ROUND(
COUNT(DISTINCT CASE WHEN ub.action_type = 'purchase' THEN ub.behavior_id END) * 100.0 /
COUNT(DISTINCT ar.recommendation_id), 2
) as conversion_rate
FROM ai_recommendations ar
LEFT JOIN user_behavior ub ON ar.product_id = ub.product_id
AND ar.user_id = ub.user_id
AND ub.timestamp >= ar.generated_at
WHERE DATE(ar.generated_at) BETWEEN :date_from AND :date_to
GROUP BY DATE(ar.generated_at)
ORDER BY date DESC
");
$perfStmt->execute([
':date_from' => $dateFrom,
':date_to' => $dateTo
]);
$performance = $perfStmt->fetchAll();
// Top recommended products
$topProductsStmt = $db->prepare("
SELECT
p.product_id,
p.product_name,
p.category,
COUNT(ar.recommendation_id) as times_recommended,
COUNT(CASE WHEN ub.action_type = 'purchase' THEN 1 END) as conversions,
AVG(ar.confidence_score) as avg_confidence
FROM ai_recommendations ar
INNER JOIN products p ON ar.product_id = p.product_id
LEFT JOIN user_behavior ub ON ar.product_id = ub.product_id
AND ar.user_id = ub.user_id
AND ub.action_type = 'purchase'
WHERE DATE(ar.generated_at) BETWEEN :date_from AND :date_to
GROUP BY p.product_id
ORDER BY times_recommended DESC
LIMIT 10
");
$topProductsStmt->execute([
':date_from' => $dateFrom,
':date_to' => $dateTo
]);
$topProducts = $topProductsStmt->fetchAll();
// User engagement metrics
$engagementStmt = $db->prepare("
SELECT
COUNT(DISTINCT user_id) as unique_users,
COUNT(DISTINCT session_id) as total_sessions,
COUNT(behavior_id) as total_interactions,
ROUND(COUNT(behavior_id) * 1.0 / COUNT(DISTINCT session_id), 2) as avg_interactions_per_session
FROM user_behavior
WHERE DATE(timestamp) BETWEEN :date_from AND :date_to
");
$engagementStmt->execute([
':date_from' => $dateFrom,
':date_to' => $dateTo
]);
$engagement = $engagementStmt->fetch();
// Category preferences
$categoryStmt = $db->prepare("
SELECT
category,
SUM(preference_score) as total_score,
COUNT(DISTINCT user_id) as interested_users
FROM user_preferences
GROUP BY category
ORDER BY total_score DESC
LIMIT 10
");
$categoryStmt->execute();
$categories = $categoryStmt->fetchAll();
echo json_encode([
'success' => true,
'performance' => $performance,
'top_products' => $topProducts,
'engagement' => $engagement,
'categories' => $categories
]);
} catch(PDOException $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
?>
Analytics Dashboard (admin-dashboard.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Analytics Dashboard</title>
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/dashboard.css">
</head>
<body>
<div class="dashboard-container">
<header class="dashboard-header">
<h1>AI Ecommerce Analytics</h1>
<div class="date-filter">
<input type="date" id="date-from" value="">
<span>to</span>
<input type="date" id="date-to" value="">
<button onclick="loadAnalytics()" class="btn-refresh">Refresh</button>
</div>
</header>
<div class="metrics-grid">
<div class="metric-card">
<div class="metric-info">
<h3 id="unique-users">0</h3>
<p>Unique Users</p>
</div>
</div>
<div class="metric-card">
<div class="metric-info">
<h3 id="ctr">0%</h3>
<p>Click-Through Rate</p>
</div>
</div>
<div class="metric-card">
<div class="metric-info">
<h3 id="conversion-rate">0%</h3>
<p>Conversion Rate</p>
</div>
</div>
<div class="metric-card">
<div class="metric-info">
<h3 id="avg-interactions">0</h3>
<p>Avg Interactions/Session</p>
</div>
</div>
</div>
<div class="charts-container">
<div class="chart-card">
<h2>Performance Over Time</h2>
<canvas id="performance-chart"></canvas>
</div>
<div class="chart-card">
<h2>Top Recommended Products</h2>
<div id="top-products-list"></div>
</div>
</div>
<div class="chart-card">
<h2>Category Preferences</h2>
<canvas id="category-chart"></canvas>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
<script src="js/dashboard.js"></script>
</body>
</html>
Dashboard JavaScript (js/dashboard.js)
let performanceChart = null;
let categoryChart = null;
async function loadAnalytics() {
const dateFrom = document.getElementById('date-from').value;
const dateTo = document.getElementById('date-to').value;
const params = new URLSearchParams({
date_from: dateFrom,
date_to: dateTo
});
try {
const response = await fetch(`php/api/get-analytics.php?${params}`);
const data = await response.json();
if (data.success) {
updateMetrics(data.engagement, data.performance);
updatePerformanceChart(data.performance);
updateTopProducts(data.top_products);
updateCategoryChart(data.categories);
}
} catch (error) {
console.error('Error loading analytics:', error);
}
}
function updateMetrics(engagement, performance) {
document.getElementById('unique-users').textContent =
engagement.unique_users.toLocaleString();
document.getElementById('avg-interactions').textContent =
engagement.avg_interactions_per_session;
if (performance.length > 0) {
const avgCTR = performance.reduce((sum, day) =>
sum + parseFloat(day.click_through_rate || 0), 0) / performance.length;
const avgConversion = performance.reduce((sum, day) =>
sum + parseFloat(day.conversion_rate || 0), 0) / performance.length;
document.getElementById('ctr').textContent = avgCTR.toFixed(2) + '%';
document.getElementById('conversion-rate').textContent = avgConversion.toFixed(2) + '%';
}
}
function updatePerformanceChart(performance) {
const ctx = document.getElementById('performance-chart').getContext('2d');
if (performanceChart) {
performanceChart.destroy();
}
const dates = performance.map(p => p.date).reverse();
const clicks = performance.map(p => parseInt(p.clicks || 0)).reverse();
const conversions = performance.map(p => parseInt(p.purchases || 0)).reverse();
performanceChart = new Chart(ctx, {
type: 'line',
data: {
labels: dates,
datasets: [
{
label: 'Clicks',
data: clicks,
borderColor: '#01AEEF',
backgroundColor: 'rgba(1, 174, 239, 0.1)',
tension: 0.4
},
{
label: 'Conversions',
data: conversions,
borderColor: '#6BCB77',
backgroundColor: 'rgba(107, 203, 119, 0.1)',
tension: 0.4
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'top',
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
}
function updateTopProducts(products) {
const container = document.getElementById('top-products-list');
const html = products.map((product, index) => `
<div class="product-rank-item">
<span class="rank-number">${index + 1}</span>
<div class="product-rank-info">
<h4>${product.product_name}</h4>
<p>${product.category}</p>
</div>
<div class="product-rank-stats">
<span class="stat-badge">${product.times_recommended} recommendations</span>
<span class="stat-badge success">${product.conversions} conversions</span>
</div>
</div>
`).join('');
container.innerHTML = html;
}
function updateCategoryChart(categories) {
const ctx = document.getElementById('category-chart').getContext('2d');
if (categoryChart) {
categoryChart.destroy();
}
const labels = categories.map(c => c.category);
const scores = categories.map(c => parseFloat(c.total_score));
categoryChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: 'Preference Score',
data: scores,
backgroundColor: [
'rgba(1, 174, 239, 0.8)',
'rgba(107, 203, 119, 0.8)',
'rgba(255, 107, 157, 0.8)',
'rgba(255, 217, 61, 0.8)',
'rgba(155, 89, 182, 0.8)',
'rgba(52, 152, 219, 0.8)',
'rgba(46, 204, 113, 0.8)',
'rgba(241, 196, 15, 0.8)',
'rgba(230, 126, 34, 0.8)',
'rgba(231, 76, 60, 0.8)'
],
borderWidth: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
}
// Initialize dashboard
document.addEventListener('DOMContentLoaded', () => {
// Set default dates
const today = new Date();
const thirtyDaysAgo = new Date(today.getTime() - (30 * 24 * 60 * 60 * 1000));
document.getElementById('date-to').valueAsDate = today;
document.getElementById('date-from').valueAsDate = thirtyDaysAgo;
loadAnalytics();
// Auto-refresh every 5 minutes
setInterval(loadAnalytics, 300000);
});
Dashboard Styles (css/dashboard.css)
/* Dashboard Styles */
.dashboard-container {
max-width: 1400px;
margin: 0 auto;
padding: 2rem;
background: #f8f9fa;
min-height: 100vh;
}
.dashboard-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
background: white;
padding: 1.5rem;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.dashboard-header h1 {
color: #333;
font-size: 2rem;
}
.date-filter {
display: flex;
align-items: center;
gap: 1rem;
}
.date-filter input[type="date"] {
padding: 8px 12px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 0.9rem;
}
.btn-refresh {
padding: 10px 20px;
background: linear-gradient(135deg, #01AEEF 0%, #0088cc 100%);
color: white;
border: none;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
}
.btn-refresh:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(1, 174, 239, 0.3);
}
/* Metrics Grid */
.metrics-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.metric-card {
background: white;
padding: 1.5rem;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
display: flex;
align-items: center;
gap: 1.5rem;
transition: transform 0.3s;
}
.metric-card:hover {
transform: translateY(-5px);
box-shadow: 0 4px 15px rgba(0,0,0,0.15);
}
.metric-icon {
font-size: 3rem;
width: 70px;
height: 70px;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #01AEEF 0%, #0088cc 100%);
border-radius: 50%;
}
.metric-info h3 {
font-size: 2rem;
color: #333;
margin: 0;
}
.metric-info p {
color: #666;
margin: 5px 0 0 0;
font-size: 0.9rem;
}
/* Charts Container */
.charts-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.chart-card {
background: white;
padding: 1.5rem;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.chart-card h2 {
font-size: 1.3rem;
color: #333;
margin-bottom: 1.5rem;
}
.chart-card canvas {
max-height: 300px;
}
/* Top Products List */
#top-products-list {
display: flex;
flex-direction: column;
gap: 1rem;
}
.product-rank-item {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem;
background: #f8f9fa;
border-radius: 8px;
transition: all 0.3s;
}
.product-rank-item:hover {
background: #e8f8ff;
}
.rank-number {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #01AEEF 0%, #0088cc 100%);
color: white;
font-weight: bold;
font-size: 1.2rem;
border-radius: 50%;
}
.product-rank-info {
flex: 1;
}
.product-rank-info h4 {
margin: 0 0 5px 0;
color: #333;
font-size: 1rem;
}
.product-rank-info p {
margin: 0;
color: #666;
font-size: 0.85rem;
}
.product-rank-stats {
display: flex;
gap: 8px;
}
.stat-badge {
padding: 5px 12px;
background: #e0e0e0;
color: #333;
border-radius: 12px;
font-size: 0.85rem;
font-weight: 600;
}
.stat-badge.success {
background: #d4edda;
color: #155724;
}
@media (max-width: 768px) {
.dashboard-header {
flex-direction: column;
gap: 1rem;
}
.metrics-grid {
grid-template-columns: 1fr;
}
.charts-container {
grid-template-columns: 1fr;
}
.product-rank-item {
flex-direction: column;
text-align: center;
}
.product-rank-stats {
flex-direction: column;
width: 100%;
}
}
Step 14: Mobile App Integration
API for Mobile Apps
Create a RESTful API that mobile applications can use to access your AI in ecommerce features.
Mobile API Endpoint (php/api/mobile/recommendations.php)
<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
require_once '../../db-connection.php';
// Handle preflight requests
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit;
}
$db = Database::getInstance()->getConnection();
// API Authentication (simplified - use proper JWT in production)
$apiKey = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
if (empty($apiKey)) {
echo json_encode(['success' => false, 'error' => 'API key required']);
http_response_code(401);
exit;
}
// Get request parameters
$userId = $_GET['user_id'] ?? null;
$deviceId = $_GET['device_id'] ?? null;
$limit = min($_GET['limit'] ?? 10, 50); // Max 50 items
$platform = $_GET['platform'] ?? 'unknown'; // ios, android, web
try {
// Log API request
$logStmt = $db->prepare("
INSERT INTO api_logs (user_id, device_id, platform, endpoint, timestamp)
VALUES (:user_id, :device_id, :platform, 'recommendations', NOW())
");
$logStmt->execute([
':user_id' => $userId,
':device_id' => $deviceId,
':platform' => $platform
]);
// Get recommendations
if ($userId) {
$stmt = $db->prepare("
SELECT
p.product_id,
p.product_name,
p.category,
p.price,
p.image_url,
p.description,
up.preference_score,
ROUND(up.preference_score / (SELECT MAX(preference_score) FROM user_preferences WHERE user_id = :user_id), 2) as confidence_score
FROM products p
INNER JOIN user_preferences up ON p.category = up.category
WHERE up.user_id = :user_id
AND p.stock_quantity > 0
ORDER BY up.preference_score DESC
LIMIT :limit
");
$stmt->bindParam(':user_id', $userId, PDO::PARAM_INT);
$stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
$stmt->execute();
$recommendations = $stmt->fetchAll();
} else {
// Device-based recommendations
$stmt = $db->prepare("
SELECT
p.product_id,
p.product_name,
p.category,
p.price,
p.image_url,
p.description,
COUNT(ub.behavior_id) as popularity,
0.6 as confidence_score
FROM products p
LEFT JOIN user_behavior ub ON p.product_id = ub.product_id
WHERE p.stock_quantity > 0
GROUP BY p.product_id
ORDER BY popularity DESC
LIMIT :limit
");
$stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
$stmt->execute();
$recommendations = $stmt->fetchAll();
}
// Format response for mobile
$formattedRecommendations = array_map(function($item) {
return [
'id' => (int)$item['product_id'],
'name' => $item['product_name'],
'category' => $item['category'],
'price' => (float)$item['price'],
'image' => $item['image_url'],
'description' => $item['description'] ?? '',
'confidence' => (float)($item['confidence_score'] ?? 0),
'match_percentage' => round((float)($item['confidence_score'] ?? 0) * 100)
];
}, $recommendations);
echo json_encode([
'success' => true,
'data' => [
'recommendations' => $formattedRecommendations,
'count' => count($formattedRecommendations),
'timestamp' => time()
],
'meta' => [
'version' => '1.0',
'platform' => $platform
]
]);
} catch(PDOException $e) {
echo json_encode([
'success' => false,
'error' => 'Database error occurred',
'message' => $e->getMessage()
]);
http_response_code(500);
}
?>
API Logs Table (database/api-schema.sql)
-- Create API logs table
CREATE TABLE api_logs (
log_id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
device_id VARCHAR(255),
platform VARCHAR(50),
endpoint VARCHAR(100),
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_device (device_id),
INDEX idx_platform (platform),
INDEX idx_timestamp (timestamp)
);
-- Create API keys table
CREATE TABLE api_keys (
key_id INT PRIMARY KEY AUTO_INCREMENT,
api_key VARCHAR(64) UNIQUE NOT NULL,
user_id INT,
key_name VARCHAR(100),
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_used TIMESTAMP NULL,
INDEX idx_api_key (api_key)
);
Step 15: Security and Privacy Features
Data Privacy Compliance
Implement GDPR-compliant features for your AI product recommendations system.
Privacy Controls (php/api/privacy/export-data.php)
<?php
header('Content-Type: application/json');
require_once '../../db-connection.php';
$db = Database::getInstance()->getConnection();
$userId = $_GET['user_id'] ?? null;
if (!$userId) {
echo json_encode(['success' => false, 'error' => 'User ID required']);
exit;
}
try {
// Get all user data
$data = [];
// User behavior
$behaviorStmt = $db->prepare("
SELECT * FROM user_behavior WHERE user_id = :user_id
");
$behaviorStmt->execute([':user_id' => $userId]);
$data['behavior'] = $behaviorStmt->fetchAll();
// User preferences
$prefStmt = $db->prepare("
SELECT * FROM user_preferences WHERE user_id = :user_id
");
$prefStmt->execute([':user_id' => $userId]);
$data['preferences'] = $prefStmt->fetchAll();
// Recommendations history
$recStmt = $db->prepare("
SELECT * FROM ai_recommendations WHERE user_id = :user_id
");
$recStmt->execute([':user_id' => $userId]);
$data['recommendations_history'] = $recStmt->fetchAll();
// Search history
$searchStmt = $db->prepare("
SELECT * FROM search_queries WHERE user_id = :user_id
");
$searchStmt->execute([':user_id' => $userId]);
$data['search_history'] = $searchStmt->fetchAll();
echo json_encode([
'success' => true,
'user_id' => $userId,
'data' => $data,
'exported_at' => date('Y-m-d H:i:s')
], JSON_PRETTY_PRINT);
} catch(PDOException $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
?>
Delete User Data (php/api/privacy/delete-data.php)
<?php
header('Content-Type: application/json');
require_once '../../db-connection.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo json_encode(['success' => false, 'error' => 'POST method required']);
exit;
}
$db = Database::getInstance()->getConnection();
$data = json_decode(file_get_contents('php://input'), true);
$userId = $data['user_id'] ?? null;
$confirmToken = $data['confirm_token'] ?? null;
if (!$userId || !$confirmToken) {
echo json_encode(['success' => false, 'error' => 'User ID and confirmation token required']);
exit;
}
try {
$db->beginTransaction();
// Delete user behavior
$stmt1 = $db->prepare("DELETE FROM user_behavior WHERE user_id = :user_id");
$stmt1->execute([':user_id' => $userId]);
// Delete user preferences
$stmt2 = $db->prepare("DELETE FROM user_preferences WHERE user_id = :user_id");
$stmt2->execute([':user_id' => $userId]);
// Delete recommendations
$stmt3 = $db->prepare("DELETE FROM ai_recommendations WHERE user_id = :user_id");
$stmt3->execute([':user_id' => $userId]);
// Delete search history
$stmt4 = $db->prepare("DELETE FROM search_queries WHERE user_id = :user_id");
$stmt4->execute([':user_id' => $userId]);
// Log deletion
$logStmt = $db->prepare("
INSERT INTO privacy_logs (user_id, action, timestamp)
VALUES (:user_id, 'data_deletion', NOW())
");
$logStmt->execute([':user_id' => $userId]);
$db->commit();
echo json_encode([
'success' => true,
'message' => 'All user data has been deleted',
'user_id' => $userId,
'deleted_at' => date('Y-m-d H:i:s')
]);
} catch(PDOException $e) {
$db->rollBack();
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
?>
Privacy Logs Table (database/privacy-schema.sql)
-- Create privacy logs table
CREATE TABLE privacy_logs (
log_id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
action ENUM('data_export', 'data_deletion', 'consent_given', 'consent_withdrawn'),
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_user_id (user_id),
INDEX idx_action (action)
);
Step 16: Performance Optimization
Caching Strategy
Implement Redis caching to improve machine learning ecommerce performance.
Redis Cache Implementation (php/cache/redis-cache.php)
<?php
class RedisCache {
private static $instance = null;
private $redis;
private $enabled;
private function __construct() {
$this->enabled = extension_loaded('redis');
if ($this->enabled) {
try {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
$this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_JSON);
} catch (Exception $e) {
$this->enabled = false;
error_log('Redis connection failed: ' . $e->getMessage());
}
}
}
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function get($key) {
if (!$this->enabled) return null;
try {
$value = $this->redis->get($key);
return $value !== false ? $value : null;
} catch (Exception $e) {
error_log('Redis get failed: ' . $e->getMessage());
return null;
}
}
public function set($key, $value, $ttl = 3600) {
if (!$this->enabled) return false;
try {
return $this->redis->setex($key, $ttl, $value);
} catch (Exception $e) {
error_log('Redis set failed: ' . $e->getMessage());
return false;
}
}
public function delete($key) {
if (!$this->enabled) return false;
try {
return $this->redis->del($key) > 0;
} catch (Exception $e) {
error_log('Redis delete failed: ' . $e->getMessage());
return false;
}
}
public function invalidateUserCache($userId) {
if (!$this->enabled) return false;
$pattern = "recommendations:user:{$userId}:*";
try {
$keys = $this->redis->keys($pattern);
if (!empty($keys)) {
return $this->redis->del($keys) > 0;
}
return true;
} catch (Exception $e) {
error_log('Cache invalidation failed: ' . $e->getMessage());
return false;
}
}
}
?>
Updated Recommendations with Cache (php/api/get-recommendations-cached.php)
<?php
header('Content-Type: application/json');
require_once '../db-connection.php';
require_once '../cache/redis-cache.php';
require_once '../config.php';
$db = Database::getInstance()->getConnection();
$cache = RedisCache::getInstance();
$userId = $_GET['user_id'] ?? null;
$sessionId = $_GET['session_id'] ?? session_id();
$limit = $_GET['limit'] ?? AI_MAX_RECOMMENDATIONS;
$forceRefresh = isset($_GET['refresh']);
try {
$cacheKey = "recommendations:user:{$userId}:limit:{$limit}";
// Try to get from cache
if (!$forceRefresh) {
$cachedData = $cache->get($cacheKey);
if ($cachedData !== null) {
echo json_encode([
'success' => true,
'recommendations' => $cachedData,
'count' => count($cachedData),
'cached' => true
]);
exit;
}
}
// Generate recommendations (same logic as before)
$recommendations = [];
if ($userId) {
$stmt = $db->prepare("
SELECT
p.product_id,
p.product_name,
p.category,
p.price,
p.image_url,
up.preference_score,
(up.preference_score / (SELECT MAX(preference_score) FROM user_preferences WHERE user_id = :user_id)) as confidence_score
FROM products p
INNER JOIN user_preferences up ON p.category = up.category
WHERE up.user_id = :user_id
AND p.stock_quantity > 0
ORDER BY up.preference_score DESC
LIMIT :limit
");
$stmt->bindParam(':user_id', $userId, PDO::PARAM_INT);
$stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
$stmt->execute();
$recommendations = $stmt->fetchAll();
}
// Cache the results for 5 minutes
if (!empty($recommendations)) {
$cache->set($cacheKey, $recommendations, 300);
}
echo json_encode([
'success' => true,
'recommendations' => $recommendations,
'count' => count($recommendations),
'cached' => false
]);
} catch(PDOException $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
?>
Step 17: A/B Testing Framework
Test AI Recommendations vs Traditional Methods
Implement A/B testing to measure the effectiveness of your AI in ecommerce features.
A/B Testing Logic (js/ab-testing.js)
class ABTesting {
constructor() {
this.variant = this.getVariant();
this.testId = 'ai_recommendations_test_' + Date.now();
}
getVariant() {
// Check if user already has a variant assigned
let variant = localStorage.getItem('ab_variant');
if (!variant) {
// Randomly assign variant (50/50 split)
variant = Math.random() < 0.5 ? 'control' : 'treatment';
localStorage.setItem('ab_variant', variant);
}
return variant;
}
async getRecommendations(userId, limit = 10) {
if (this.variant === 'treatment') {
// Use AI recommendations
return await this.getAIRecommendations(userId, limit);
} else {
// Use traditional recommendations (popular products)
return await this.getTraditionalRecommendations(limit);
}
}
async getAIRecommendations(userId, limit) {
const params = new URLSearchParams({
user_id: userId || '',
limit: limit
});
const response = await fetch(`php/api/get-recommendations.php?${params}`);
const data = await response.json();
this.trackEvent('recommendations_shown', {
variant: 'treatment',
count: data.recommendations.length
});
return data.recommendations;
}
async getTraditionalRecommendations(limit) {
const response = await fetch(`php/api/get-popular-products.php?limit=${limit}`);
const data = await response.json();
this.trackEvent('recommendations_shown', {
variant: 'control',
count: data.products.length
});
return data.products;
}
trackEvent(eventName, data) {
const eventData = {
test_id: this.testId,
variant: this.variant,
event: eventName,
data: data,
timestamp: new Date().toISOString()
};
// Send to analytics API
fetch('php/api/analytics/track-event.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(eventData)
}).catch(error => {
console.error('Failed to track event:', error);
});
}
trackConversion(productId, revenue) {
this.trackEvent('conversion', {
product_id: productId,
revenue: revenue
});
}
}
// Initialize A/B Testing
const abTest = new ABTesting();