E-commerce AI Chatbot: Boost Conversions with RAG

Deploy an AI chatbot on your online store to increase sales, reduce cart abandonment, and improve customer experience.

Author
Ailog Team
Published
Reading time
22 min read
Level
intermediate

E-commerce AI Chatbot: Boost Conversions with RAG

AI chatbots are revolutionizing e-commerce. An assistant that understands your products, guides customers, and responds instantly to questions can transform your conversion rate. This guide shows you how to deploy a high-performance RAG chatbot on your online store.

Why a RAG Chatbot for E-commerce?

Limitations of Traditional Chatbots

Rule-based (if/then) chatbots or static FAQs quickly show their limits: • Rigidity: Only understand anticipated phrasings • Heavy maintenance: Each new question requires a rule • Frustrating experience: "I didn't understand your question" repeated endlessly • No product context: Unable to recommend the right product

The RAG Advantage

A RAG chatbot connected to your product catalog:

| Aspect | Traditional Chatbot | RAG Chatbot | |--------|---------------------|-------------| | Natural language understanding | Limited (keywords) | Excellent (semantic) | | Product knowledge | Static, manual | Dynamic, synchronized | | Personalization | Basic | Contextual | | Scalability | Difficult (rules) | Simple (documents) | | Maintenance | Heavy | Automated |

Proven Business Impact

Stores using AI chatbots report: • +15-30% conversion rate on engaged visitors • -40% support tickets for pre-sale questions • +25% average cart value through recommendations • 24/7 availability at no additional cost

E-commerce RAG Chatbot Architecture

`` ┌─────────────────────────────────────────────────────────────┐ │ DATA SOURCES │ ├─────────────┬─────────────┬─────────────┬──────────────────┤ │ Product │ FAQ │ Return │ Customer │ │ Catalog │ Support │ Policy │ History │ └──────┬──────┴──────┬──────┴──────┬──────┴────────┬─────────┘ │ │ │ │ └─────────────┴──────┬──────┴───────────────┘ ▼ ┌─────────────────┐ │ Indexing │ │ (Embeddings) │ └────────┬────────┘ ▼ ┌─────────────────┐ │ Vector DB │ │ (Qdrant) │ └────────┬────────┘ │ ┌───────────────────────────┴───────────────────────────────┐ │ RUNTIME │ ├─────────────────────────────────────────────────────────────┤ │ ┌─────────┐ ┌───────────┐ ┌──────────┐ ┌────────┐ │ │ │ Chat │───▶│ Retriever │───▶│ LLM │──▶│Response│ │ │ │ Widget │ │ │ │(Generation)│ │ │ │ │ └─────────┘ └───────────┘ └──────────┘ └────────┘ │ └─────────────────────────────────────────────────────────────┘ `

Synchronizing the Product Catalog

Shopify Connector

`python import shopify from datetime import datetime

class ShopifyConnector: def __init__(self, shop_url: str, access_token: str): shopify.ShopifyResource.set_site(shop_url) shopify.ShopifyResource.set_headers({ 'X-Shopify-Access-Token': access_token })

def get_all_products(self) -> list[dict]: """ Retrieve all products with their variants """ products = [] page = shopify.Product.find(limit=250)

while page: for product in page: products.append(self._format_product(product))

Pagination if len(page) < 250: break page = shopify.Product.find(limit=250, since_id=page[-1].id)

return products

def _format_product(self, product) -> dict: """ Format a product for RAG indexing """ Build a rich description for RAG description_parts = [ f"Product: {product.title}", f"Description: {self._clean_html(product.body_html)}", f"Category: {product.product_type}", f"Brand: {product.vendor}", f"Tags: {', '.join(product.tags.split(', '))}", ]

Add variants for variant in product.variants: variant_info = f"Variant: {variant.title}" if variant.price: variant_info += f" - Price: ${variant.price}" if variant.inventory_quantity: variant_info += f" - Stock: {variant.inventory_quantity}" description_parts.append(variant_info)

return { "id": f"product_{product.id}", "title": product.title, "content": "\n".join(description_parts), "metadata": { "type": "product", "product_id": product.id, "price_min": min(v.price for v in product.variants), "price_max": max(v.price for v in product.variants), "category": product.product_type, "in_stock": any(v.inventory_quantity > 0 for v in product.variants), "url": f"/products/{product.handle}", "image": product.images[0].src if product.images else None, "updated_at": product.updated_at } }

def _clean_html(self, html: str) -> str: from bs4 import BeautifulSoup return BeautifulSoup(html or "", "html.parser").get_text() `

WooCommerce Connector

`python from woocommerce import API

class WooCommerceConnector: def __init__(self, url: str, consumer_key: str, consumer_secret: str): self.wcapi = API( url=url, consumer_key=consumer_key, consumer_secret=consumer_secret, version="wc/v3" )

def get_all_products(self) -> list[dict]: """ Retrieve all WooCommerce products """ products = [] page = 1

while True: response = self.wcapi.get("products", params={ "per_page": 100, "page": page, "status": "publish" })

batch = response.json() if not batch: break

for product in batch: products.append(self._format_product(product))

page += 1

return products

def _format_product(self, product: dict) -> dict: """ Format a WooCommerce product for RAG """ description_parts = [ f"Product: {product['name']}", f"Description: {self._clean_html(product.get('description', ''))}", f"Short description: {self._clean_html(product.get('short_description', ''))}", ]

Categories categories = [cat['name'] for cat in product.get('categories', [])] if categories: description_parts.append(f"Categories: {', '.join(categories)}")

Attributes for attr in product.get('attributes', []): description_parts.append(f"{attr['name']}: {', '.join(attr['options'])}")

Price if product.get('sale_price'): description_parts.append(f"Price: ${product['sale_price']} (was ${product['regular_price']})") else: description_parts.append(f"Price: ${product.get('price', 'N/A')}")

return { "id": f"product_{product['id']}", "title": product['name'], "content": "\n".join(description_parts), "metadata": { "type": "product", "product_id": product['id'], "price": float(product.get('price', 0)), "categories": categories, "in_stock": product.get('stock_status') == 'instock', "url": product.get('permalink', ''), "image": product['images'][0]['src'] if product.get('images') else None } }

def _clean_html(self, html: str) -> str: from bs4 import BeautifulSoup return BeautifulSoup(html or "", "html.parser").get_text() `

Automatic Synchronization

`python import asyncio from datetime import datetime, timedelta

class ProductSyncService: def __init__(self, connector, indexer, sync_interval_hours: int = 6): self.connector = connector self.indexer = indexer self.sync_interval = timedelta(hours=sync_interval_hours) self.last_sync = None

async def start_sync_loop(self): """ Start periodic synchronization """ while True: try: await self.sync() except Exception as e: print(f"Sync error: {e}")

await asyncio.sleep(self.sync_interval.total_seconds())

async def sync(self): """ Synchronize products with vector database """ print(f"[{datetime.now()}] Starting product synchronization...")

Retrieve all products products = self.connector.get_all_products()

Index await self.indexer.index_documents( documents=products, collection="products" )

self.last_sync = datetime.now() print(f"[{datetime.now()}] {len(products)} products synchronized")

async def sync_single_product(self, product_id: str): """ Synchronize a single product (webhook) """ product = self.connector.get_product(product_id) if product: await self.indexer.update_document( document=product, collection="products" ) `

Optimized E-commerce Prompts

Sales Assistant Prompt

`python SALES_ASSISTANT_PROMPT = """You are the AI sales assistant for {store_name}, a store specializing in {category}.

PRIMARY OBJECTIVE: Help visitors find the perfect product and guide them to purchase.

STRICT RULES: Base your recommendations ONLY on products from the provided catalog Never invent products, prices, or features If a product is out of stock, mention it and suggest alternatives Always include the link to the product page

BEHAVIOR: • Ask questions to understand needs • Suggest 2-3 products maximum per response • Highlight current promotions • Reassure about return policy if hesitation detected

RECOMMENDATION FORMAT: For each recommended product, use this format: [Product Name] Price: $XX [Short 1-2 sentence description explaining why this product fits] View product: [URL]

AVAILABLE PRODUCTS: {context}

CONVERSATION: {history}

CUSTOMER QUESTION: {question} """ `

After-Sales Support Prompt

`python SUPPORT_PROMPT = """You are the support assistant for {store_name}.

OBJECTIVE: Help customers with their orders, returns, and after-purchase questions.

RULES: Answer only from the provided policies and FAQ For any question about a specific order, ask for the order number If the issue requires human intervention, direct to the contact form Remain empathetic in the face of frustrations

AVAILABLE INFORMATION: {context}

QUESTION: {question} """ `

Intent Detection and Routing

`python from enum import Enum

class CustomerIntent(Enum): PRODUCT_SEARCH = "product_search" PRODUCT_COMPARISON = "comparison" PRICE_QUESTION = "price_question" STOCK_CHECK = "stock_check" ORDER_STATUS = "order_status" RETURN_REQUEST = "return_request" GENERAL_SUPPORT = "general_support" CHITCHAT = "chitchat"

class IntentDetector: def __init__(self, llm): self.llm = llm

async def detect(self, message: str, history: list = None) -> CustomerIntent: """ Detect customer intent """ prompt = f""" Analyze this customer message and determine their primary intent.

Message: {message}

Possible intents: • product_search: Customer is looking for a product • comparison: Customer is comparing products • price_question: Question about price or promotion • stock_check: Checking availability • order_status: Asking about order status • return_request: Wants to return a product • general_support: Other support question • chitchat: Simple conversation/greeting

Respond only with the intent (single word). """

response = await self.llm.generate(prompt, temperature=0) intent_str = response.strip().lower()

try: return CustomerIntent(intent_str) except ValueError: return CustomerIntent.GENERAL_SUPPORT

class EcommerceRAGRouter: def __init__(self, intent_detector, retrievers: dict, generators: dict): self.intent_detector = intent_detector self.retrievers = retrievers self.generators = generators

async def route(self, message: str, history: list = None) -> dict: """ Route the request to the right retriever and generator """ intent = await self.intent_detector.detect(message, history)

Intent -> configuration mapping config = { CustomerIntent.PRODUCT_SEARCH: { "retriever": "products", "generator": "sales", "filters": {"in_stock": True} }, CustomerIntent.PRODUCT_COMPARISON: { "retriever": "products", "generator": "sales", "top_k": 10 }, CustomerIntent.PRICE_QUESTION: { "retriever": "products", "generator": "sales" }, CustomerIntent.STOCK_CHECK: { "retriever": "products", "generator": "sales" }, CustomerIntent.ORDER_STATUS: { "retriever": "support", "generator": "support", "require_order_number": True }, CustomerIntent.RETURN_REQUEST: { "retriever": "policies", "generator": "support" }, CustomerIntent.GENERAL_SUPPORT: { "retriever": "support", "generator": "support" }, CustomerIntent.CHITCHAT: { "retriever": None, "generator": "chitchat" } }

return { "intent": intent, "config": config.get(intent, config[CustomerIntent.GENERAL_SUPPORT]) } `

Intelligent Product Recommendations

Similarity-Based Recommendations

`python class ProductRecommender: def __init__(self, retriever): self.retriever = retriever

async def similar_products( self, product_id: str, exclude_ids: list[str] = None, limit: int = 4 ) -> list[dict]: """ Find similar products """ Retrieve source product source_product = await self.retriever.get_by_id(product_id) if not source_product: return []

Search by similarity results = await self.retriever.search( query=source_product["content"], top_k=limit + len(exclude_ids or []) + 1, filters={"type": "product", "in_stock": True} )

Filter exclude = set(exclude_ids or []) | {product_id} recommendations = [ r for r in results if r["metadata"]["product_id"] not in exclude ][:limit]

return recommendations

async def complementary_products( self, cart_items: list[str], limit: int = 3 ) -> list[dict]: """ Suggest complementary products (cross-sell) """ Build query based on cart cart_products = [] for product_id in cart_items: product = await self.retriever.get_by_id(product_id) if product: cart_products.append(product["title"])

if not cart_products: return []

Search for complements query = f"Products that go well with: {', '.join(cart_products)}"

results = await self.retriever.search( query=query, top_k=limit + len(cart_items), filters={"type": "product", "in_stock": True} )

Exclude products already in cart return [r for r in results if r["metadata"]["product_id"] not in cart_items][:limit] `

Contextual LLM-Based Recommendations

`python async def generate_recommendation( self, customer_query: str, customer_context: dict, retrieved_products: list[dict] ) -> str: """ Generate a personalized recommendation """ prompt = f""" You need to recommend products to a customer.

CUSTOMER CONTEXT: • Query: {customer_query} • Indicated budget: {customer_context.get('budget', 'Not specified')} • Purchase history: {customer_context.get('purchase_history', 'New customer')}

AVAILABLE PRODUCTS: {self._format_products(retrieved_products)}

INSTRUCTIONS: Choose 2-3 products maximum Explain why each product fits Adapt your pitch to budget if indicated Suggest a cheaper alternative if budget is limited

RECOMMENDATION: """

return await self.llm.generate(prompt, temperature=0.3) `

Cart Management and Upsell

Cart Abandonment Detection

`python class CartAbandonmentDetector: def __init__(self, session_timeout_minutes: int = 30): self.timeout = timedelta(minutes=session_timeout_minutes) self.active_carts = {}

def track_activity(self, session_id: str, cart_items: list): """ Track cart activity """ self.active_carts[session_id] = { "items": cart_items, "last_activity": datetime.now(), "notified": False }

def get_abandoned_carts(self) -> list[dict]: """ Identify abandoned carts """ abandoned = [] now = datetime.now()

for session_id, cart in self.active_carts.items(): if (now - cart["last_activity"] > self.timeout and not cart["notified"] and len(cart["items"]) > 0): abandoned.append({ "session_id": session_id, "items": cart["items"], "abandoned_at": cart["last_activity"] })

return abandoned

class CartRecoveryBot: def __init__(self, recommender, llm): self.recommender = recommender self.llm = llm

async def generate_recovery_message( self, cart_items: list[dict], customer_name: str = None ) -> str: """ Generate a cart recovery message """ items_text = "\n".join([ f"- {item['title']} (${item['price']})" for item in cart_items ])

prompt = f""" A customer has abandoned their cart. Generate a friendly message to encourage them to complete their purchase.

Items in cart: {items_text}

The message should: • Be warm but not pushy • Remind them of the items • Mention we can help with questions • Offer to help them choose

{"Start with 'Hi " + customer_name + "'" if customer_name else ""} """

return await self.llm.generate(prompt, temperature=0.7) `

Optimized Chat Widget

Widget Configuration

`javascript // E-commerce widget configuration const chatConfig = { // Appearance theme: { primaryColor: '#2563eb', position: 'bottom-right', bubbleText: 'Need help?' },

// Proactive behavior proactive: { enabled: true, triggers: [ { event: 'time_on_page', value: 60, // seconds message: 'Looking for something specific? I can help!' }, { event: 'page_type', value: 'product', delay: 30, message: 'Questions about this product? I\'m here to help.' }, { event: 'cart_value', value: 100, message: 'Did you know shipping is free on orders over $150?' } ] },

// Contextual quick replies quickReplies: { homepage: [ 'What are your best sellers?', 'Any promotions going on?', 'How does shipping work?' ], product: [ 'Is this product available?', 'What are the delivery times?', 'Can I return this product?' ], cart: [ 'How do I use a promo code?', 'What are shipping costs?', 'Can I modify my order?' ] } }; `

Conversion Tracking

`python class ChatAnalytics: def __init__(self, analytics_client): self.client = analytics_client

def track_conversation( self, session_id: str, messages: list, outcome: str, metadata: dict = None ): """ Track a conversation for analysis """ self.client.track({ "event": "chat_conversation", "session_id": session_id, "message_count": len(messages), "outcome": outcome, "purchase", "support_ticket", "abandoned" "duration_seconds": self._calculate_duration(messages), "products_discussed": metadata.get("products", []), "intent_detected": metadata.get("intent"), "timestamp": datetime.now().isoformat() })

def track_chat_to_purchase( self, session_id: str, order_value: float, products: list ): """ Track a chat -> purchase conversion """ self.client.track({ "event": "chat_conversion", "session_id": session_id, "order_value": order_value, "products": products, "attribution": "chat_assisted" })

def get_chat_roi_metrics(self, period_days: int = 30) -> dict: """ Calculate chat ROI """ data = self.client.query(f""" SELECT COUNT(DISTINCT session_id) as conversations, COUNT(DISTINCT CASE WHEN outcome = 'purchase' THEN session_id END) as conversions, SUM(CASE WHEN outcome = 'purchase' THEN order_value ELSE 0 END) as revenue, AVG(message_count) as avg_messages FROM chat_events WHERE timestamp > NOW() - INTERVAL '{period_days} days' """)

return { "total_conversations": data["conversations"], "conversions": data["conversions"], "conversion_rate": data["conversions"] / data["conversations"] * 100, "revenue_attributed": data["revenue"], "avg_messages_per_conversation": data["avg_messages"] } `

E-commerce Best Practices Rich Responses with Products

Always format product recommendations visually:

`python def format_product_card(product: dict) -> str: """ Format a product as a visual card (Markdown) """ price_text = f"${product['price']}" if product.get('original_price'): price_text = f"~~${product['original_price']}~~ ${product['price']}"

stock_badge = "In stock" if product['in_stock'] else "Out of stock"

return f""" {product['title']} {price_text} | {stock_badge}

{product['short_description']}

View product """ ` Out-of-Stock Handling

`python async def handle_out_of_stock(self, product: dict, query: str) -> str: """ Intelligently handle out-of-stock situations """ Find alternatives alternatives = await self.recommender.similar_products( product_id=product["id"], filters={"in_stock": True}, limit=3 )

if alternatives: alt_text = "\n".join([format_product_card(p) for p in alternatives]) return f""" Unfortunately, {product['title']} is currently unavailable.

Here are similar alternatives you might like:

{alt_text}

Would you like to be notified when the product is back in stock? """ else: return f""" Unfortunately, {product['title']} is currently unavailable and we don't have a similar alternative.

Would you like to be notified when the product is back in stock? """ ` Human Support Escalation

`python def should_escalate(self, conversation: list, last_response: dict) -> bool: """ Determine if escalation to human is needed """ escalation_triggers = [ Repeated negative sentiment len([m for m in conversation[-3:] if m.get("sentiment") == "negative"]) >= 2,

Explicit request any(kw in conversation[-1]["text"].lower() for kw in [ "talk to someone", "human", "agent", "phone", "representative" ]),

Low model confidence last_response.get("confidence", 1) < 0.5,

Conversation too long without resolution len(conversation) > 10 and not last_response.get("resolved") ]

return any(escalation_triggers) ``

Measuring Success

KPIs to Track

| Metric | Target | How to Measure | |--------|--------|----------------| | Engagement rate | > 15% visitors | Visitors who opened chat | | Resolution rate | > 80% | Conversations without escalation | | Assisted conversion | > 5% | Purchases after chat interaction | | Chat CSAT | > 4/5 | End-of-conversation rating | | Response time | < 3s | First response latency | | Cost per conversation | < $0.10 | LLM cost / number of conversations |

Learn More • Retrieval Fundamentals - Optimize product search • AI Customer Support - Reduce support tickets • Introduction to RAG - Understand the basics

---

Launch Your E-commerce Chatbot with Ailog

Deploying a high-performance RAG chatbot on your store can take months of development. With Ailog, get started in hours: • Native connectors: Shopify, WooCommerce, PrestaShop, Magento • Automatic synchronization of product catalog • Customizable widget that matches your branding • Conversational analytics to measure ROI • European hosting GDPR compliant

Try Ailog for free and boost your conversions today.

Tags

  • RAG
  • e-commerce
  • chatbot
  • conversion
  • Shopify
  • WooCommerce
GuideIntermédiaire

E-commerce AI Chatbot: Boost Conversions with RAG

19 janvier 2026
22 min read
Ailog Team

Deploy an AI chatbot on your online store to increase sales, reduce cart abandonment, and improve customer experience.

E-commerce AI Chatbot: Boost Conversions with RAG

AI chatbots are revolutionizing e-commerce. An assistant that understands your products, guides customers, and responds instantly to questions can transform your conversion rate. This guide shows you how to deploy a high-performance RAG chatbot on your online store.

Why a RAG Chatbot for E-commerce?

Limitations of Traditional Chatbots

Rule-based (if/then) chatbots or static FAQs quickly show their limits:

  • Rigidity: Only understand anticipated phrasings
  • Heavy maintenance: Each new question requires a rule
  • Frustrating experience: "I didn't understand your question" repeated endlessly
  • No product context: Unable to recommend the right product

The RAG Advantage

A RAG chatbot connected to your product catalog:

AspectTraditional ChatbotRAG Chatbot
Natural language understandingLimited (keywords)Excellent (semantic)
Product knowledgeStatic, manualDynamic, synchronized
PersonalizationBasicContextual
ScalabilityDifficult (rules)Simple (documents)
MaintenanceHeavyAutomated

Proven Business Impact

Stores using AI chatbots report:

  • +15-30% conversion rate on engaged visitors
  • -40% support tickets for pre-sale questions
  • +25% average cart value through recommendations
  • 24/7 availability at no additional cost

E-commerce RAG Chatbot Architecture

┌─────────────────────────────────────────────────────────────┐
│                       DATA SOURCES                           │
├─────────────┬─────────────┬─────────────┬──────────────────┤
│   Product   │    FAQ      │   Return    │    Customer      │
│   Catalog   │   Support   │   Policy    │    History       │
└──────┬──────┴──────┬──────┴──────┬──────┴────────┬─────────┘
       │             │             │               │
       └─────────────┴──────┬──────┴───────────────┘
                            ▼
                   ┌─────────────────┐
                   │    Indexing     │
                   │  (Embeddings)   │
                   └────────┬────────┘
                            ▼
                   ┌─────────────────┐
                   │  Vector DB      │
                   │   (Qdrant)      │
                   └────────┬────────┘
                            │
┌───────────────────────────┴───────────────────────────────┐
│                        RUNTIME                              │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────┐    ┌───────────┐    ┌──────────┐   ┌────────┐ │
│  │  Chat   │───▶│ Retriever │───▶│   LLM    │──▶│Response│ │
│  │ Widget  │    │           │    │(Generation)│  │        │ │
│  └─────────┘    └───────────┘    └──────────┘   └────────┘ │
└─────────────────────────────────────────────────────────────┘

Synchronizing the Product Catalog

Shopify Connector

DEVELOPERpython
import shopify from datetime import datetime class ShopifyConnector: def __init__(self, shop_url: str, access_token: str): shopify.ShopifyResource.set_site(shop_url) shopify.ShopifyResource.set_headers({ 'X-Shopify-Access-Token': access_token }) def get_all_products(self) -> list[dict]: """ Retrieve all products with their variants """ products = [] page = shopify.Product.find(limit=250) while page: for product in page: products.append(self._format_product(product)) # Pagination if len(page) < 250: break page = shopify.Product.find(limit=250, since_id=page[-1].id) return products def _format_product(self, product) -> dict: """ Format a product for RAG indexing """ # Build a rich description for RAG description_parts = [ f"Product: {product.title}", f"Description: {self._clean_html(product.body_html)}", f"Category: {product.product_type}", f"Brand: {product.vendor}", f"Tags: {', '.join(product.tags.split(', '))}", ] # Add variants for variant in product.variants: variant_info = f"Variant: {variant.title}" if variant.price: variant_info += f" - Price: ${variant.price}" if variant.inventory_quantity: variant_info += f" - Stock: {variant.inventory_quantity}" description_parts.append(variant_info) return { "id": f"product_{product.id}", "title": product.title, "content": "\n".join(description_parts), "metadata": { "type": "product", "product_id": product.id, "price_min": min(v.price for v in product.variants), "price_max": max(v.price for v in product.variants), "category": product.product_type, "in_stock": any(v.inventory_quantity > 0 for v in product.variants), "url": f"/products/{product.handle}", "image": product.images[0].src if product.images else None, "updated_at": product.updated_at } } def _clean_html(self, html: str) -> str: from bs4 import BeautifulSoup return BeautifulSoup(html or "", "html.parser").get_text()

WooCommerce Connector

DEVELOPERpython
from woocommerce import API class WooCommerceConnector: def __init__(self, url: str, consumer_key: str, consumer_secret: str): self.wcapi = API( url=url, consumer_key=consumer_key, consumer_secret=consumer_secret, version="wc/v3" ) def get_all_products(self) -> list[dict]: """ Retrieve all WooCommerce products """ products = [] page = 1 while True: response = self.wcapi.get("products", params={ "per_page": 100, "page": page, "status": "publish" }) batch = response.json() if not batch: break for product in batch: products.append(self._format_product(product)) page += 1 return products def _format_product(self, product: dict) -> dict: """ Format a WooCommerce product for RAG """ description_parts = [ f"Product: {product['name']}", f"Description: {self._clean_html(product.get('description', ''))}", f"Short description: {self._clean_html(product.get('short_description', ''))}", ] # Categories categories = [cat['name'] for cat in product.get('categories', [])] if categories: description_parts.append(f"Categories: {', '.join(categories)}") # Attributes for attr in product.get('attributes', []): description_parts.append(f"{attr['name']}: {', '.join(attr['options'])}") # Price if product.get('sale_price'): description_parts.append(f"Price: ${product['sale_price']} (was ${product['regular_price']})") else: description_parts.append(f"Price: ${product.get('price', 'N/A')}") return { "id": f"product_{product['id']}", "title": product['name'], "content": "\n".join(description_parts), "metadata": { "type": "product", "product_id": product['id'], "price": float(product.get('price', 0)), "categories": categories, "in_stock": product.get('stock_status') == 'instock', "url": product.get('permalink', ''), "image": product['images'][0]['src'] if product.get('images') else None } } def _clean_html(self, html: str) -> str: from bs4 import BeautifulSoup return BeautifulSoup(html or "", "html.parser").get_text()

Automatic Synchronization

DEVELOPERpython
import asyncio from datetime import datetime, timedelta class ProductSyncService: def __init__(self, connector, indexer, sync_interval_hours: int = 6): self.connector = connector self.indexer = indexer self.sync_interval = timedelta(hours=sync_interval_hours) self.last_sync = None async def start_sync_loop(self): """ Start periodic synchronization """ while True: try: await self.sync() except Exception as e: print(f"Sync error: {e}") await asyncio.sleep(self.sync_interval.total_seconds()) async def sync(self): """ Synchronize products with vector database """ print(f"[{datetime.now()}] Starting product synchronization...") # Retrieve all products products = self.connector.get_all_products() # Index await self.indexer.index_documents( documents=products, collection="products" ) self.last_sync = datetime.now() print(f"[{datetime.now()}] {len(products)} products synchronized") async def sync_single_product(self, product_id: str): """ Synchronize a single product (webhook) """ product = self.connector.get_product(product_id) if product: await self.indexer.update_document( document=product, collection="products" )

Optimized E-commerce Prompts

Sales Assistant Prompt

DEVELOPERpython
SALES_ASSISTANT_PROMPT = """You are the AI sales assistant for {store_name}, a store specializing in {category}. PRIMARY OBJECTIVE: Help visitors find the perfect product and guide them to purchase. STRICT RULES: 1. Base your recommendations ONLY on products from the provided catalog 2. Never invent products, prices, or features 3. If a product is out of stock, mention it and suggest alternatives 4. Always include the link to the product page BEHAVIOR: - Ask questions to understand needs - Suggest 2-3 products maximum per response - Highlight current promotions - Reassure about return policy if hesitation detected RECOMMENDATION FORMAT: For each recommended product, use this format: **[Product Name]** Price: $XX [Short 1-2 sentence description explaining why this product fits] View product: [URL] AVAILABLE PRODUCTS: {context} CONVERSATION: {history} CUSTOMER QUESTION: {question} """

After-Sales Support Prompt

DEVELOPERpython
SUPPORT_PROMPT = """You are the support assistant for {store_name}. OBJECTIVE: Help customers with their orders, returns, and after-purchase questions. RULES: 1. Answer only from the provided policies and FAQ 2. For any question about a specific order, ask for the order number 3. If the issue requires human intervention, direct to the contact form 4. Remain empathetic in the face of frustrations AVAILABLE INFORMATION: {context} QUESTION: {question} """

Intent Detection and Routing

DEVELOPERpython
from enum import Enum class CustomerIntent(Enum): PRODUCT_SEARCH = "product_search" PRODUCT_COMPARISON = "comparison" PRICE_QUESTION = "price_question" STOCK_CHECK = "stock_check" ORDER_STATUS = "order_status" RETURN_REQUEST = "return_request" GENERAL_SUPPORT = "general_support" CHITCHAT = "chitchat" class IntentDetector: def __init__(self, llm): self.llm = llm async def detect(self, message: str, history: list = None) -> CustomerIntent: """ Detect customer intent """ prompt = f""" Analyze this customer message and determine their primary intent. Message: {message} Possible intents: - product_search: Customer is looking for a product - comparison: Customer is comparing products - price_question: Question about price or promotion - stock_check: Checking availability - order_status: Asking about order status - return_request: Wants to return a product - general_support: Other support question - chitchat: Simple conversation/greeting Respond only with the intent (single word). """ response = await self.llm.generate(prompt, temperature=0) intent_str = response.strip().lower() try: return CustomerIntent(intent_str) except ValueError: return CustomerIntent.GENERAL_SUPPORT class EcommerceRAGRouter: def __init__(self, intent_detector, retrievers: dict, generators: dict): self.intent_detector = intent_detector self.retrievers = retrievers self.generators = generators async def route(self, message: str, history: list = None) -> dict: """ Route the request to the right retriever and generator """ intent = await self.intent_detector.detect(message, history) # Intent -> configuration mapping config = { CustomerIntent.PRODUCT_SEARCH: { "retriever": "products", "generator": "sales", "filters": {"in_stock": True} }, CustomerIntent.PRODUCT_COMPARISON: { "retriever": "products", "generator": "sales", "top_k": 10 }, CustomerIntent.PRICE_QUESTION: { "retriever": "products", "generator": "sales" }, CustomerIntent.STOCK_CHECK: { "retriever": "products", "generator": "sales" }, CustomerIntent.ORDER_STATUS: { "retriever": "support", "generator": "support", "require_order_number": True }, CustomerIntent.RETURN_REQUEST: { "retriever": "policies", "generator": "support" }, CustomerIntent.GENERAL_SUPPORT: { "retriever": "support", "generator": "support" }, CustomerIntent.CHITCHAT: { "retriever": None, "generator": "chitchat" } } return { "intent": intent, "config": config.get(intent, config[CustomerIntent.GENERAL_SUPPORT]) }

Intelligent Product Recommendations

Similarity-Based Recommendations

DEVELOPERpython
class ProductRecommender: def __init__(self, retriever): self.retriever = retriever async def similar_products( self, product_id: str, exclude_ids: list[str] = None, limit: int = 4 ) -> list[dict]: """ Find similar products """ # Retrieve source product source_product = await self.retriever.get_by_id(product_id) if not source_product: return [] # Search by similarity results = await self.retriever.search( query=source_product["content"], top_k=limit + len(exclude_ids or []) + 1, filters={"type": "product", "in_stock": True} ) # Filter exclude = set(exclude_ids or []) | {product_id} recommendations = [ r for r in results if r["metadata"]["product_id"] not in exclude ][:limit] return recommendations async def complementary_products( self, cart_items: list[str], limit: int = 3 ) -> list[dict]: """ Suggest complementary products (cross-sell) """ # Build query based on cart cart_products = [] for product_id in cart_items: product = await self.retriever.get_by_id(product_id) if product: cart_products.append(product["title"]) if not cart_products: return [] # Search for complements query = f"Products that go well with: {', '.join(cart_products)}" results = await self.retriever.search( query=query, top_k=limit + len(cart_items), filters={"type": "product", "in_stock": True} ) # Exclude products already in cart return [r for r in results if r["metadata"]["product_id"] not in cart_items][:limit]

Contextual LLM-Based Recommendations

DEVELOPERpython
async def generate_recommendation( self, customer_query: str, customer_context: dict, retrieved_products: list[dict] ) -> str: """ Generate a personalized recommendation """ prompt = f""" You need to recommend products to a customer. CUSTOMER CONTEXT: - Query: {customer_query} - Indicated budget: {customer_context.get('budget', 'Not specified')} - Purchase history: {customer_context.get('purchase_history', 'New customer')} AVAILABLE PRODUCTS: {self._format_products(retrieved_products)} INSTRUCTIONS: 1. Choose 2-3 products maximum 2. Explain why each product fits 3. Adapt your pitch to budget if indicated 4. Suggest a cheaper alternative if budget is limited RECOMMENDATION: """ return await self.llm.generate(prompt, temperature=0.3)

Cart Management and Upsell

Cart Abandonment Detection

DEVELOPERpython
class CartAbandonmentDetector: def __init__(self, session_timeout_minutes: int = 30): self.timeout = timedelta(minutes=session_timeout_minutes) self.active_carts = {} def track_activity(self, session_id: str, cart_items: list): """ Track cart activity """ self.active_carts[session_id] = { "items": cart_items, "last_activity": datetime.now(), "notified": False } def get_abandoned_carts(self) -> list[dict]: """ Identify abandoned carts """ abandoned = [] now = datetime.now() for session_id, cart in self.active_carts.items(): if (now - cart["last_activity"] > self.timeout and not cart["notified"] and len(cart["items"]) > 0): abandoned.append({ "session_id": session_id, "items": cart["items"], "abandoned_at": cart["last_activity"] }) return abandoned class CartRecoveryBot: def __init__(self, recommender, llm): self.recommender = recommender self.llm = llm async def generate_recovery_message( self, cart_items: list[dict], customer_name: str = None ) -> str: """ Generate a cart recovery message """ items_text = "\n".join([ f"- {item['title']} (${item['price']})" for item in cart_items ]) prompt = f""" A customer has abandoned their cart. Generate a friendly message to encourage them to complete their purchase. Items in cart: {items_text} The message should: - Be warm but not pushy - Remind them of the items - Mention we can help with questions - Offer to help them choose {"Start with 'Hi " + customer_name + "'" if customer_name else ""} """ return await self.llm.generate(prompt, temperature=0.7)

Optimized Chat Widget

Widget Configuration

DEVELOPERjavascript
// E-commerce widget configuration const chatConfig = { // Appearance theme: { primaryColor: '#2563eb', position: 'bottom-right', bubbleText: 'Need help?' }, // Proactive behavior proactive: { enabled: true, triggers: [ { event: 'time_on_page', value: 60, // seconds message: 'Looking for something specific? I can help!' }, { event: 'page_type', value: 'product', delay: 30, message: 'Questions about this product? I\'m here to help.' }, { event: 'cart_value', value: 100, message: 'Did you know shipping is free on orders over $150?' } ] }, // Contextual quick replies quickReplies: { homepage: [ 'What are your best sellers?', 'Any promotions going on?', 'How does shipping work?' ], product: [ 'Is this product available?', 'What are the delivery times?', 'Can I return this product?' ], cart: [ 'How do I use a promo code?', 'What are shipping costs?', 'Can I modify my order?' ] } };

Conversion Tracking

DEVELOPERpython
class ChatAnalytics: def __init__(self, analytics_client): self.client = analytics_client def track_conversation( self, session_id: str, messages: list, outcome: str, metadata: dict = None ): """ Track a conversation for analysis """ self.client.track({ "event": "chat_conversation", "session_id": session_id, "message_count": len(messages), "outcome": outcome, # "purchase", "support_ticket", "abandoned" "duration_seconds": self._calculate_duration(messages), "products_discussed": metadata.get("products", []), "intent_detected": metadata.get("intent"), "timestamp": datetime.now().isoformat() }) def track_chat_to_purchase( self, session_id: str, order_value: float, products: list ): """ Track a chat -> purchase conversion """ self.client.track({ "event": "chat_conversion", "session_id": session_id, "order_value": order_value, "products": products, "attribution": "chat_assisted" }) def get_chat_roi_metrics(self, period_days: int = 30) -> dict: """ Calculate chat ROI """ data = self.client.query(f""" SELECT COUNT(DISTINCT session_id) as conversations, COUNT(DISTINCT CASE WHEN outcome = 'purchase' THEN session_id END) as conversions, SUM(CASE WHEN outcome = 'purchase' THEN order_value ELSE 0 END) as revenue, AVG(message_count) as avg_messages FROM chat_events WHERE timestamp > NOW() - INTERVAL '{period_days} days' """) return { "total_conversations": data["conversations"], "conversions": data["conversions"], "conversion_rate": data["conversions"] / data["conversations"] * 100, "revenue_attributed": data["revenue"], "avg_messages_per_conversation": data["avg_messages"] }

E-commerce Best Practices

1. Rich Responses with Products

Always format product recommendations visually:

DEVELOPERpython
def format_product_card(product: dict) -> str: """ Format a product as a visual card (Markdown) """ price_text = f"${product['price']}" if product.get('original_price'): price_text = f"~~${product['original_price']}~~ **${product['price']}**" stock_badge = "In stock" if product['in_stock'] else "Out of stock" return f""" **{product['title']}** {price_text} | {stock_badge} {product['short_description']} [View product]({product['url']}) """

2. Out-of-Stock Handling

DEVELOPERpython
async def handle_out_of_stock(self, product: dict, query: str) -> str: """ Intelligently handle out-of-stock situations """ # Find alternatives alternatives = await self.recommender.similar_products( product_id=product["id"], filters={"in_stock": True}, limit=3 ) if alternatives: alt_text = "\n".join([format_product_card(p) for p in alternatives]) return f""" Unfortunately, **{product['title']}** is currently unavailable. Here are similar alternatives you might like: {alt_text} Would you like to be notified when the product is back in stock? """ else: return f""" Unfortunately, **{product['title']}** is currently unavailable and we don't have a similar alternative. Would you like to be notified when the product is back in stock? """

3. Human Support Escalation

DEVELOPERpython
def should_escalate(self, conversation: list, last_response: dict) -> bool: """ Determine if escalation to human is needed """ escalation_triggers = [ # Repeated negative sentiment len([m for m in conversation[-3:] if m.get("sentiment") == "negative"]) >= 2, # Explicit request any(kw in conversation[-1]["text"].lower() for kw in [ "talk to someone", "human", "agent", "phone", "representative" ]), # Low model confidence last_response.get("confidence", 1) < 0.5, # Conversation too long without resolution len(conversation) > 10 and not last_response.get("resolved") ] return any(escalation_triggers)

Measuring Success

KPIs to Track

MetricTargetHow to Measure
Engagement rate> 15% visitorsVisitors who opened chat
Resolution rate> 80%Conversations without escalation
Assisted conversion> 5%Purchases after chat interaction
Chat CSAT> 4/5End-of-conversation rating
Response time< 3sFirst response latency
Cost per conversation< $0.10LLM cost / number of conversations

Learn More


Launch Your E-commerce Chatbot with Ailog

Deploying a high-performance RAG chatbot on your store can take months of development. With Ailog, get started in hours:

  • Native connectors: Shopify, WooCommerce, PrestaShop, Magento
  • Automatic synchronization of product catalog
  • Customizable widget that matches your branding
  • Conversational analytics to measure ROI
  • European hosting GDPR compliant

Try Ailog for free and boost your conversions today.

Tags

RAGe-commercechatbotconversionShopifyWooCommerce

Articles connexes

Ailog Assistant

Ici pour vous aider

Salut ! Pose-moi des questions sur Ailog et comment intégrer votre RAG dans vos projets !