Реализация автоматической генерации SEO-текстов для карточек товаров (AI)

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация автоматической генерации SEO-текстов для карточек товаров (AI)
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Реализация автоматической генерации SEO-текстов для карточек товаров (AI)

Карточка товара без уникального текста — это либо дублированный контент из прайса поставщика, либо шаблонная фраза из 30 слов. Ни то ни другое не ранжируется. При каталоге от нескольких тысяч позиций писать тексты вручную нецелесообразно — это задача для автоматизации.

Генерация SEO-текстов через языковую модель закрывает эту задачу при правильной архитектуре: подготовленные промпты, контроль качества на выходе, кэширование и ревью перед публикацией.

Что на входе, что на выходе

Вход — структурированные данные товара: название, категория, характеристики, бренд, теги. Выход — SEO-описание длиной 150–600 слов с целевыми ключевыми словами, естественно вписанными в текст.

Пример входных данных:

{
  "id": "SKU-4821",
  "name": "Кроссовки Nike Air Max 270",
  "category": "Мужская обувь / Кроссовки",
  "brand": "Nike",
  "attributes": {
    "material": "mesh + synthetic",
    "sole": "Air Max unit",
    "colors": ["black/white", "navy/grey"],
    "sizes": "40–46",
    "weight": "310g"
  },
  "tags": ["беговые", "повседневные", "амортизация"],
  "targetKeywords": ["nike air max 270 купить", "кроссовки найк аир макс 270"]
}

Промпт-инжиниринг для товарных текстов

Промпт — это не «напиши описание товара». Хороший промпт задаёт структуру, тон, длину, требования к ключевым словам и запреты:

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

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 (not forced): ${keywords.join(", ")}
- Structure: opening benefit statement → key features (3–5 points) → use cases → closing
- Tone: informative, no hype, no superlatives like "лучший" or "уникальный"
- Do NOT use: "данный товар", "представляем вашему вниманию", bullet points
- Do NOT start with the product name
- Write for a person who is comparing options, not for someone who already decided

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

Пакетная обработка с очередями

Генерировать тексты синхронно нельзя — запрос к GPT занимает 3–10 секунд, а позиций могут быть тысячи. Правильная схема — очередь задач:

// jobs/generate-seo-text.ts
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, // 5 параллельных запросов к API
  }
);

Контроль качества

Автоматически сгенерированный текст нужно валидировать до сохранения. Минимальный набор проверок:

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 = [
    "данный товар",
    "представляем вашему вниманию",
    "уникальный",
    "лучший в своём классе",
  ];
  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;
    const density = kwCount / wordCount;
    if (density > 0.03) {
      issues.push(`Keyword density too high for "${kw}": ${(density * 100).toFixed(1)}%`);
    }
  }

  return { passed: issues.length === 0, issues };
}

Тексты, не прошедшие валидацию, помечаются флагом needs_review и попадают в отдельную очередь для повторной генерации с уточнённым промптом.

Интерфейс ревью

Редактор видит список черновиков с возможностью принять, отклонить или редактировать:

GET /admin/seo-texts?status=draft&page=1
→ список карточек с текстом, кнопки: Опубликовать / Регенерировать / Редактировать

POST /admin/seo-texts/:id/approve
→ меняет status на published, обновляет карточку товара

POST /admin/seo-texts/:id/regenerate
→ добавляет задачу обратно в очередь с пометкой attempt=2

Регенерация с обратной связью — воркер читает причину отклонения и добавляет её в промпт:

if (job.data.rejectionReason) {
  prompt += `\n\nPrevious attempt was rejected. Reason: ${job.data.rejectionReason}. Fix this in the new version.`;
}

Стоимость и масштаб

GPT-4o-mini на момент написания стоит $0.15 за миллион входящих токенов и $0.60 за миллион исходящих. Один товарный текст — примерно 300–500 токенов на вход и 400–500 на выход. Итого около $0.0004 за текст. 10 000 карточек — порядка $4. Это делает массовую генерацию экономически обоснованной даже при частом обновлении каталога.

При большом каталоге стоит настроить триггер на обновление атрибутов товара — если изменилось название или ключевые характеристики, текст автоматически помечается устаревшим и ставится на перегенерацию.