Automated SEO Text Generation for Product Cards

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Showing 1 of 1All 2062 services
Automated SEO Text Generation for Product Cards
Medium
~3-5 days
Frequently Asked Questions

Our competencies:

Development stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1358
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1250
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    956
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1188
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    929
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Website development for FIXPER company
    947

We automate the generation of SEO descriptions for e-commerce stores where the catalog includes thousands of items. Manual writing of unique texts for each product would take months and millions — our system handles it in hours. But simply calling the neural network API is not enough: a well-thought-out architecture is needed, consisting of data preparation, prompt engineering, batch processing, validation, and a review interface. With over 10 years of experience in developing high-load systems, we guarantee stability and quality of generation.

Why This Works?

Modern language models — such as ChatGPT (GPT-4o) and Claude — generate meaningful texts if you give them structured data: name, category, attributes. According to the OpenAI documentation, contextual learning allows adapting the output to the task. Prompt engineering sets the tone, length, structure, and keyword requirements, so the result is relevant and SEO-optimized. Example for Nike Air Max 270 sneakers:

{
  "id": "SKU-4821",
  "name": "Nike Air Max 270 Sneakers",
  "category": "Men's Shoes / Sneakers",
  "brand": "Nike",
  "attributes": { "material": "mesh + synthetic", "sole": "Air Max unit", "colors": ["black/white", "navy/grey"], "sizes": "40–46", "weight": "310g" },
  "tags": ["running", "casual", "cushioning"],
  "targetKeywords": ["buy nike air max 270", "nike air max 270 sneakers"]
}

How Is Uniqueness Guaranteed?

The model with temperature >0 always produces a different result. Additionally, we check each generation for duplicates via Elasticsearch — if the text matches an existing one, we trigger a new generation with a different seed. This eliminates duplicates in the catalog. This approach preserves uniqueness even during mass generation.

How Do We Design Prompts for Product Texts?

A prompt is not just "write a product description." A good prompt defines structure, tone, length, keyword requirements, and prohibitions. Example in TypeScript:

function buildProductSeoPrompt(product: Product, keywords: string[]): string {
  return `
Write a product description for an e-commerce catalog in [language].

Product: ${product.name}
Category: ${product.category}
Brand: ${product.brand}
Key attributes: ${JSON.stringify(product.attributes)}
Tags: ${product.tags.join(", ")}

Requirements:
- Length: 200–400 words
- Include these keywords naturally: ${keywords.join(", ")}
- Structure: opening benefit statement → key features (3–5 points) → use cases → closing
- Tone: informative, no hype, no superlatives like "best" or "unique"
- Do NOT use: "this product", "we present to you", bullet points
- Do NOT start with the product name
- Write for a person who is comparing options

Output: plain text, no markdown, no headings.
`.trim();
}

Why Is Batch Processing with Queues Important?

Generating texts synchronously is not feasible — an LLM request takes 3–10 seconds, and there may be thousands of items. We use a task queue based on BullMQ with parallelism and retries.

import { Queue, Worker } from "bullmq";
import { openai } from "../lib/openai";
import { db } from "../lib/db";

const seoQueue = new Queue("seo-generation", {
  connection: { host: "localhost", port: 6379 },
});

export async function queueProductsForGeneration(productIds: string[]) {
  const jobs = productIds.map((id) => ({
    name: "generate",
    data: { productId: id },
    opts: { attempts: 3, backoff: { type: "exponential", delay: 5000 }, removeOnComplete: 100 },
  }));
  await seoQueue.addBulk(jobs);
}

const worker = new Worker("seo-generation", async (job) => {
  const product = await db.products.findById(job.data.productId);
  if (!product) return;
  const keywords = await getTargetKeywords(product);
  const prompt = buildProductSeoPrompt(product, keywords);
  const completion = await openai.chat.completions.create({
    model: "gpt-4o-mini",
    messages: [{ role: "user", content: prompt }],
    temperature: 0.7,
    max_tokens: 600,
  });
  const text = completion.choices[0].message.content?.trim();
  if (!text) throw new Error("Empty response");
  await db.productSeoTexts.upsert({
    productId: product.id,
    text,
    status: "draft",
    model: "gpt-4o-mini",
    generatedAt: new Date(),
  });
}, { connection: { host: "localhost", port: 6379 }, concurrency: 5 });

How Are Errors Handled During Generation?

If a request fails or returns an empty response, the task is automatically re-enqueued with exponential backoff. After three failed attempts, the product is marked as failed and sent for manual review. This ensures fault tolerance and minimizes data loss.

Quality Control Through Validation

The generated text is automatically checked: length, presence of all keywords, absence of stop phrases, keyword density. If validation fails, the product is flagged with needs_review and sent for regeneration with an adjusted prompt.

interface ValidationResult { passed: boolean; issues: string[] }
function validateSeoText(text: string, product: Product): ValidationResult {
  const issues: string[] = [];
  if (text.length < 500) issues.push(`Too short: ${text.length} chars`);
  const missingKeywords = product.targetKeywords.filter(kw => !text.toLowerCase().includes(kw.toLowerCase()));
  if (missingKeywords.length > 0) issues.push(`Missing keywords: ${missingKeywords.join(", ")}`);
  const stopPhrases = ["this product", "we present to you", "unique", "best in its class"];
  for (const phrase of stopPhrases) {
    if (text.toLowerCase().includes(phrase)) issues.push(`Contains stop phrase: "${phrase}"`);
  }
  const wordCount = text.split(/\s+/).length;
  for (const kw of product.targetKeywords) {
    const kwCount = (text.toLowerCase().match(new RegExp(kw.toLowerCase(), "g")) || []).length;
    if (kwCount / wordCount > 0.03) issues.push(`Keyword density too high for "${kw}": ${(kwCount / wordCount * 100).toFixed(1)}%`);
  }
  return { passed: issues.length === 0, issues };
}

Review Interface

Editors see a list of drafts with "Publish", "Regenerate", "Edit" buttons. Regeneration takes into account the reason for previous rejection — the worker adds it to the prompt. All drafts are stored in draft status; publication only occurs after confirmation.

Comparison: Manual vs AI Generation

Parameter Manual Copywriting AI Generation
Speed per text 15–30 minutes 5–15 seconds
Cost for 10,000 texts high (depends on authors) significantly lower
Scalability linear with number of authors parallel queue
Quality control depends on executor automatic validation
Timeliness manual updates trigger on data change

Example: for a large client in the clothing segment, we generated 12,000 descriptions in 4 hours. Prompts accounted for seasonality, gender, size chart. After initial generation, 8% of texts fell into needs_review due to high keyword density — after prompt adjustment, the percentage dropped to 2%. The final launch took one day.

Implementation Stages

Stage Description Duration
Analysis Collect data structure, test prompts on a sample 1 week
Development Integrate LLM, queue, validators, review interface 2–3 weeks
Testing Run on 500 products, iterative prompt refinement 1 week
Launch Generate entire catalog, train the team 1 week

What Is Included in the Implementation?

  • Integration with LLM (OpenAI, Claude) via API
  • Queue system on BullMQ with retries and backoff
  • Prompt engineering for your specifics (categories, tone, keywords)
  • Review and moderation interface (React + TypeScript)
  • Validators: length, keywords, stop words, density
  • Documentation and team training
  • Support for one month after launch

Timeline and Cost

Implementation time — from 2 to 6 weeks depending on catalog size and integration complexity. Cost is calculated individually — the more products, the cheaper each individual text. Let's evaluate your project? Contact us — we'll tell you how to reduce the SEO content budget several times over.

Request a consultation — we will analyze your catalog and choose the optimal generation model. Get a prototype on your data and see the effect.

AI Integration: Chatbots, RAG, Semantic Search, Recommendations

In 8 out of 10 projects, an "AI chatbot" turns out to be an expensive wrapper over GPT-4o with a system prompt. Without access to real company data. The user asks "how much does the Premium plan cost?" — the bot hallucinates a price out of thin air. Asks "when will my order arrive?" — gets a polite "contact support." This is not integration — it's imitation. We have implemented RAG solutions in 30+ projects over 5 years: from e-commerce stores to medical portals. We guarantee: useful AI assistance begins where the model reads your documents, not generic answers.

How do we build RAG systems?

Retrieval-Augmented Generation — standard architecture: query → find relevant fragments in a vector DB → insert found context → model response. But the devil is in the implementation details. Let's break down key components that determine quality.

Chunking. Cutting a document into 500-token pieces without regard for structure is a guarantee of losing meaning. If the cut lands in the middle of a paragraph, context breaks. Solution — recursive RecursiveCharacterTextSplitter with 10–15% overlap for documentation. For contracts and instructions, we use a semantic splitter: extract headings, lists, code blocks — each section becomes an independent chunk. Difference in search quality: on a medical project, precision increased from 0.55 to 0.84 just by proper chunking.

Embedding model. For Russian-language texts, intfloat/multilingual-e5-large gives a noticeable accuracy boost over outdated text-embedding-ada-002. In our measurements, NDCG@10 on a test set of 10,000 query-document pairs is 12% higher. OpenAI text-embedding-3-large is good for English content, but for Russian we recommend BAAI/bge-m3 or the mentioned e5-large.

Vector DB. If you already have PostgreSQL — pgvector saves resources. Install extension CREATE EXTENSION vector, add column vector(1024), create HNSW index. On a project with 80,000 support articles, p95 search time was 12 ms. That's enough. For catalogs with millions of items — Qdrant or Weaviate: native hybrid search and sharding out of the box.

What does hybrid search give?

Vector-only search is blind to exact matches: SKUs like "ABC-123", proper names, abbreviations are lost. Full-text-only search doesn't catch synonyms and paraphrasing. Combining via RRF (Reciprocal Rank Fusion) gives the best of both worlds: BM25 + vector search, results merged. In practice, recall@20 increases from 0.65 to 0.92 — the difference is noticeable to the user.

Reranking — final filter: top-20 candidates from hybrid search are run through a cross-encoder cross-encoder/ms-marco-MiniLM-L-6-v2. It adds 50–100 ms to response time, but relevance improves by another 5–10%. Without reranking, the chatbot may show irrelevant documents.

How to implement semantic search on a site?

A search for "comfortable leather armchairs" should find products described as "soft chairs made of natural leather" — ordinary LIKE search cannot do this. Our architecture: when adding a product/post, automatically generate an embedding via multilingual-e5-large, store it in pgvector. On query, embed it with the same model, search nearest neighbors via cosine distance with HNSW index. For a catalog of 100,000 items, index builds in 3 minutes, memory ~400 MB (1536-dimensional vectors). Average search time: 20 ms.

What about recommendation systems?

Collaborative filtering ("users like you bought X") requires history — at least 2–3 months of data with 1000+ active users. For startups or small projects, we use content-based: embedding of current product → search nearest neighbors by cosine similarity. When enough statistics accumulate (usually 15–20 interactions per user), we switch to a hybrid LightFM model. It combines behavior and product features. In our e-commerce project with 50,000 SKUs, the hybrid model increased conversion in the recommendation block by 18% (A/B test lasted 2 weeks).

How does streaming work?

Users shouldn't wait for the entire text to be generated — it kills UX. Server-Sent Events (SSE) is the protocol for token streaming. OpenAI SDK supports stream: true, returning an AsyncIterator. On frontend — Vercel AI SDK (useChat) or custom EventSource. Typical mistake: using WebSocket for unidirectional streaming — SSE is simpler (less code, built-in reconnect). Stack: Node.js + SSE + React.

How to orchestrate agents?

A simple chatbot answers. An agent performs actions: creates a Jira ticket, checks order status in CRM, books a calendar slot. For orchestration, we use LangGraph: state graph where each node is a model or tool call. Vercel AI SDK useChat + tools for Next.js allows adding integration in 10 lines of code. Main challenge — reliability: the model sometimes calls the wrong tool or passes malformed parameters. Protection — Zod schemas for each tool and structured outputs to guarantee JSON.

What does the work include?

Stage Result Duration
Audit of data and business logic Source map, document format, quality assessment 1–2 days
Prototype of RAG or recommendation system Demo with metrics (recall, precision, latency) 1–2 weeks
Integration into existing web application API endpoints, chatbot/search interface 1–2 weeks
A/B testing and optimization Report on metrics (CTR, conversion, hallucination rate) 1 week
Documentation and team training Operations manual, code review 2–3 days

Additionally: we hand over vectorizer source code, monitoring dashboards (Langfuse), admin panel access for knowledge base updates. Post-production support — 1 month free.

What are the timelines?

Task Estimated Time
RAG chatbot based on existing knowledge base 3–6 weeks
Semantic catalog search 2–4 weeks
Recommendation system with A/B testing 6–10 weeks
Multi-agent system with integrations from 8 weeks

Pricing is calculated individually after project discovery. We'll evaluate your project in 1 day. Contact us — we'll show how to turn AI from a toy into a profit-driving tool.