Как создать 8 000 уникальных SEO-страниц с помощью AI: полный гайд

10.03.2026обновлено 17ч назад

Programmatic SEO — это когда ты генерируешь сотни или тысячи страниц под редкие поисковые запросы. Не руками, конечно. С помощью AI.

Звучит просто: взял шаблон, подставил переменные, получил 25 000 страниц. Но Google не дурак — он увидит 25 000 копий одного текста и проигнорирует их все. Мы проходили через это на реальном проекте и набили все возможные шишки.

В этом гайде — полный пайплайн: от идеи до проиндексированного каталога. С промптами, скриптами проверки и списком граблей, на которые мы уже наступили.

Для кого этот гайд

  • Вайбкодеры, которые делают контентные проекты (образование, каталоги, справочники)
  • Фаундеры, которые хотят SEO-трафик без команды копирайтеров
  • Все, кто слышал про programmatic SEO, но не знает как сделать это правильно с AI

Как это работает: общая схема

Весь процесс состоит из 5 этапов:

  1. Собрать семантику — найти тысячи long-tail запросов в нише
  2. Спроектировать шаблон страницы — какие блоки, какие данные
  3. Написать промпты для генерации уникального контента каждого блока
  4. Сгенерировать страницы батчами через AI API
  5. Проверить качество через AI-агента и поправить косяки

Шаг 1: Сбор семантики

Где брать long-tail запросы

Long-tail — это запросы из 3+ слов с низкой конкуренцией. "Реферат" — не long-tail. "Реферат по экологии на тему загрязнение мирового океана" — long-tail.

Источники:

  • Яндекс Wordstat — основной для РФ. Берите запросы с частотностью 10-500 в месяц
  • Google Keyword Planner — для англоязычных проектов
  • Парсинг конкурентов — посмотрите структуру URL и sitemap конкурентов, которые уже в топе
  • AI-генерация — попросите Claude/GPT сгенерировать варианты тем по вашей нише
  • Подсказки поисковиков — автодополнение в Яндекс и Google

Промпт для генерации тем

Ты — SEO-специалист. Сгенерируй 200 тем для [тип контента] по предмету [предмет].

Требования:
- Каждая тема = реальный поисковый запрос студента/пользователя
- Длина: 5-15 слов
- Темы должны быть конкретными, не абстрактными
- Без дублей и синонимов
- Покрывай разные аспекты предмета

Формат вывода — JSON массив строк:
["тема 1", "тема 2", ...]

Предмет: Гражданское право
Тип: реферат

Как структурировать данные

Создайте CSV или JSON с полями:

{
  "id": 1,
  "topic": "Понятие и виды правонарушений в российском праве",
  "subject": "Право",
  "work_type": "реферат",
  "slug": "ponyatie-i-vidy-pravonarusheniy-v-rossiyskom-prave",
  "status": "pending"
}

Важно: slug генерируйте сразу, транслитерацией. Потом менять URL — потеря индексации.

Шаг 2: Архитектура страницы

Что должно быть на каждой странице

Каждая страница каталога — это не просто текст. Это набор SEO-оптимизированных блоков:

  • Title — уникальный, с ключевым запросом, до 60 символов
  • Meta description — уникальный, 150-160 символов, с призывом к действию
  • H1 — один на страницу, совпадает с темой
  • Введение — 200-400 слов уникального текста
  • Структурированный план — оглавление работы с конкретными названиями
  • FAQ-блок — 3-5 вопросов для featured snippets
  • Список источников — релевантные по теме
  • Внутренние ссылки — 10-15 ссылок на похожие страницы
  • Хлебные крошки — навигация: Главная → Предмет → Тип → Тема
  • Schema.org разметка — Product, FAQ, BreadcrumbList

URL-структура

/katalog/referat-ponyatie-i-vidy-pravonarusheniy/

Правила:

  • Транслитерация, не более 80 символов
  • Тип работы в начале (referat-, kursovaya-, esse-)
  • Без стоп-слов (в, на, по, для)
  • Обязательно trailing slash

Шаг 3: Промпты для генерации уникального контента

Это самый важный этап. Плохой промпт = 8 000 страниц мусора, которые Google проигнорирует.

Главный промпт генерации

Ты — эксперт-академик по предмету "{subject}". Создай уникальный контент для страницы каталога.

ВХОДНЫЕ ДАННЫЕ:
- Тема: {topic}
- Тип работы: {work_type}
- Предмет: {subject}

СГЕНЕРИРУЙ JSON со следующими полями:

1. "meta_title" (строка, до 60 символов)
   SEO-заголовок. Формат: "{Тема} — {тип работы} 2026"

2. "meta_description" (строка, 140-160 символов)
   Уникальное описание. Начни с действия: "Скачайте...", "Готовый...", "Пример..."
   Включи тему и призыв к действию.

3. "intro" (строка, 200-350 слов)
   Уникальное введение, которое:
   - Объясняет актуальность КОНКРЕТНО этой темы (реальные факты, тренды, законы)
   - НЕ начинается со слова "Актуальность" — это клише
   - Формулирует цель работы
   - Определяет объект и предмет исследования
   - Содержит 3-5 задач (РАЗНЫХ, не повторяющихся!)
   - Грамотный русский, правильные падежи

4. "chapters" (массив объектов)
   План работы. Для реферата: 3-4 главы. Для курсовой: 3-5 глав с параграфами.
   Каждый элемент: {"title": "название", "description": "1-2 предложения о содержании"}
   Названия КОНКРЕТНЫЕ по теме, НЕ шаблонные.

   ПЛОХО: "Глава 1. Теоретические основы проблемы"
   ХОРОШО: "Глава 1. Понятие правонарушения в российском законодательстве"

5. "faq" (массив из 3-5 объектов)
   Вопросы, которые студент реально гуглит по теме.
   Формат: {"question": "вопрос?", "answer": "ответ 2-3 предложения"}

6. "sources" (массив из 5-8 строк)
   Реальные учебники и статьи по данной теме.
   Формат: "Автор И.О. Название. — Город: Издательство, год. — С. XX-XX."
   НЕ выдумывай авторов. Используй реально существующие учебники.

7. "tasks" (массив из 3-5 строк)
   Задачи исследования. Каждая начинается с глагола:
   "раскрыть...", "проанализировать...", "исследовать...", "определить...", "выявить..."
   Все задачи РАЗНЫЕ по содержанию.

8. "keywords" (массив из 5-7 строк)
   LSI-ключевые слова, которые должны встречаться на странице.

КРИТИЧЕСКИ ВАЖНО:
- Весь текст УНИКАЛЕН для данной темы
- Никаких шаблонных фраз с подстановкой переменных
- Русский язык без ошибок, правильные падежи
- JSON должен быть валидным

Верни ТОЛЬКО JSON, без пояснений.

Почему именно JSON

Текстовый ответ непредсказуем — AI может добавить лишние пояснения, изменить формат, забыть блок. JSON:

  • Легко парсится
  • Валидируется автоматически
  • Каждое поле проверяется отдельно
  • Пропущенное поле = ошибка, а не молчаливый пропуск

Промпт для перелинковки

После генерации основного контента, нужен отдельный проход для внутренних ссылок:

Из списка тем выбери 10-15 наиболее близких к теме "{topic}".
Сгруппируй по 3 категориям: "по предмету", "по типу работы", "смежные темы".
Верни JSON:
{
  "related_by_subject": ["slug1", "slug2", ...],
  "related_by_type": ["slug3", "slug4", ...],
  "related_topics": ["slug5", "slug6", ...]
}

Шаг 4: Генерация батчами

Архитектура пайплайна

CSV с темами
    ↓
Скрипт-генератор (Python)
    ↓
Claude API / GPT API (батчи по 10-20)
    ↓
JSON-файлы с контентом
    ↓
Шаблонизатор (Jinja2 / Next.js / SSG)
    ↓
HTML-страницы
    ↓
Деплой + IndexNow

Пример скрипта генерации

import json, time, os
from anthropic import Anthropic

client = Anthropic()
PROMPT_TEMPLATE = open("prompt.txt").read()

def generate_page(topic, subject, work_type):
    """Генерация контента одной страницы."""
    prompt = PROMPT_TEMPLATE.format(
        topic=topic,
        subject=subject,
        work_type=work_type
    )
    
    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=4096,
        messages=[{"role": "user", "content": prompt}]
    )
    
    text = response.content[0].text
    # Убираем markdown-обёртку если AI добавил ```json
    text = text.strip()
    if text.startswith("```"):
        text = text.split("\n", 1)[1].rsplit("```", 1)[0]
    
    return json.loads(text)

def process_batch(topics_file, output_dir, batch_size=20):
    """Обработка тем батчами."""
    with open(topics_file) as f:
        topics = json.load(f)
    
    os.makedirs(output_dir, exist_ok=True)
    
    for i, item in enumerate(topics):
        slug = item["slug"]
        output_path = f"{output_dir}/{slug}.json"
        
        # Пропускаем уже сгенерированные
        if os.path.exists(output_path):
            continue
        
        try:
            content = generate_page(
                item["topic"],
                item["subject"],
                item["work_type"]
            )
            content["slug"] = slug
            content["topic"] = item["topic"]
            
            with open(output_path, "w") as f:
                json.dump(content, f, ensure_ascii=False, indent=2)
            
            print(f"[{i+1}/{len(topics)}] ✅ {slug}")
            
        except Exception as e:
            print(f"[{i+1}/{len(topics)}] ❌ {slug}: {e}")
            with open(f"{output_dir}/_errors.log", "a") as f:
                f.write(f"{slug}: {e}\n")
        
        # Rate limiting: 1 запрос в 1-2 секунды
        time.sleep(1.5)
        
        # Пауза между батчами
        if (i + 1) % batch_size == 0:
            print(f"--- Пауза 30 сек (батч {(i+1)//batch_size}) ---")
            time.sleep(30)

process_batch("topics.json", "generated/", batch_size=20)

Сколько стоит

Примерная стоимость генерации через Claude API:

  • 1 страница ≈ 2000 токенов вход + 2000 токенов выход
  • Claude Sonnet: ~$0.006 за страницу
  • 8 000 страниц ≈ $48
  • Claude Opus (если нужно качество): ~$0.06 за страницу → $480 за 8 000

Sonnet хватает для 90% задач. Opus стоит использовать для сложных тем (медицина, юриспруденция) где нужна точность.

Советы по батчевой генерации

  • Сохраняйте каждую страницу в отдельный JSON — если скрипт упадёт, не потеряете прогресс
  • Логируйте ошибки отдельно — потом перегенерируете только сломанные
  • Не гоните больше 30 запросов в минуту — API зарейтлимитит
  • Делайте по 500-1000 за сессию, проверяйте качество, потом следующий батч

Шаг 5: Проверка качества через AI-агента

Это этап, который все пропускают. И зря — именно он определяет, проиндексирует Google ваши страницы или нет.

Что проверять

  1. Уникальность контента между страницами — нет ли повторяющихся фраз
  2. Грамматика и падежи — AI любит ломать русский язык в шаблонных конструкциях
  3. Релевантность — соответствует ли введение теме, а не общим словам
  4. Полнота — все ли поля заполнены, нет ли пустых FAQ
  5. SEO-атрибуты — title, description, schema.org, canonical, OG-теги
  6. Технические баги — 404, дубли URL, битые ссылки

Промпт для AI-ревьюера

Ты — SEO-аудитор. Проверь качество сгенерированной страницы каталога.

СТРАНИЦА:
Тема: {topic}
Тип: {work_type}
Предмет: {subject}

КОНТЕНТ:
{content_json}

ПРОВЕРЬ по чеклисту и выставь оценку 1-10:

1. УНИКАЛЬНОСТЬ (1-10): Введение уникально для темы? Или это шаблон с подстановкой?
   Красные флаги: "В современном мире...", "Актуальность данной темы...",
   одинаковые формулировки задач.

2. ГРАММАТИКА (1-10): Русский язык без ошибок?
   Проверь: падежи ("в области права", не "праву"), согласование
   ("Вторая глава", не "Второй глава"), окончания.

3. РЕЛЕВАНТНОСТЬ (1-10): Контент действительно про эту тему?
   Или общие слова, которые подойдут к любой теме?

4. ПОЛНОТА (1-10): Все поля заполнены? FAQ содержат реальные вопросы?
   Источники существуют? Задачи разные?

5. SEO (1-10): Title до 60 символов? Description 140-160? Ключевые слова
   присутствуют в тексте?

Верни JSON:
{
  "scores": {"uniqueness": N, "grammar": N, "relevance": N, "completeness": N, "seo": N},
  "total": N,
  "issues": ["описание проблемы 1", "..."],
  "verdict": "pass" | "fix" | "regenerate"
}

Правила:
- total < 30 → "regenerate" (перегенерировать с нуля)
- total 30-40 → "fix" (исправить конкретные проблемы)
- total > 40 → "pass" (всё ок)

Скрипт автоматической проверки

import json, glob

def audit_page(content, client):
    """Проверка одной страницы через AI."""
    audit_prompt = AUDIT_TEMPLATE.format(
        topic=content["topic"],
        work_type=content.get("work_type", "реферат"),
        subject=content.get("subject", ""),
        content_json=json.dumps(content, ensure_ascii=False, indent=2)
    )
    
    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=2048,
        messages=[{"role": "user", "content": audit_prompt}]
    )
    return json.loads(response.content[0].text)

def audit_batch(generated_dir):
    """Проверка всех сгенерированных страниц."""
    results = {"pass": [], "fix": [], "regenerate": []}
    
    for path in glob.glob(f"{generated_dir}/*.json"):
        if path.endswith("_errors.log"):
            continue
            
        with open(path) as f:
            content = json.load(f)
        
        audit = audit_page(content, client)
        verdict = audit["verdict"]
        results[verdict].append({
            "slug": content["slug"],
            "total": audit["total"],
            "issues": audit["issues"]
        })
        
        print(f"{'✅' if verdict == 'pass' else '⚠️' if verdict == 'fix' else '❌'} "
              f"{content['slug']}: {audit['total']}/50 — {verdict}")
    
    # Сводка
    print(f"\n--- ИТОГО ---")
    print(f"✅ Прошли: {len(results['pass'])}")
    print(f"⚠️ Нужен фикс: {len(results['fix'])}")
    print(f"❌ Перегенерация: {len(results['regenerate'])}")
    
    return results

Проверка дублей между страницами

AI-ревьюер проверяет одну страницу. Но главная проблема — одинаковые фразы на РАЗНЫХ страницах. Для этого нужен отдельный скрипт:

from collections import Counter

def find_duplicates(generated_dir, field="intro", 
                    ngram_size=5, threshold=3):
    """Найти повторяющиеся фразы между страницами."""
    ngram_counts = Counter()
    ngram_sources = {}
    
    for path in glob.glob(f"{generated_dir}/*.json"):
        with open(path) as f:
            content = json.load(f)
        
        text = content.get(field, "")
        words = text.lower().split()
        
        for i in range(len(words) - ngram_size + 1):
            ngram = " ".join(words[i:i + ngram_size])
            ngram_counts[ngram] += 1
            if ngram not in ngram_sources:
                ngram_sources[ngram] = []
            ngram_sources[ngram].append(content["slug"])
    
    # Фразы, встречающиеся на threshold+ страницах
    duplicates = {
        ngram: sources 
        for ngram, sources in ngram_sources.items()
        if ngram_counts[ngram] >= threshold
    }
    
    if duplicates:
        print(f"⚠️ Найдено {len(duplicates)} повторяющихся фраз:")
        for ngram, sources in sorted(
            duplicates.items(), 
            key=lambda x: len(x[1]), 
            reverse=True
        )[:20]:
            print(f"  [{len(sources)}x] \"{ngram}\"")
    
    return duplicates

Если нашли дубли — добавьте в промпт генерации явный запрет: "НЕ используй фразу '...'".

Шаг 6: SEO-атрибуты страниц

Обязательные мета-теги

<title>{meta_title}</title>
<meta name="description" content="{meta_description}">
<link rel="canonical" href="https://site.ru/katalog/{slug}/">
<meta property="og:title" content="{meta_title}">
<meta property="og:description" content="{meta_description}">
<meta property="og:url" content="https://site.ru/katalog/{slug}/">
<meta property="og:type" content="article">

Schema.org разметка

{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "{topic}",
  "description": "{meta_description}",
  "author": {"@type": "Organization", "name": "Название сайта"},
  "datePublished": "2026-01-15",
  "mainEntityOfPage": "https://site.ru/katalog/{slug}/"
}

Для FAQ-блока добавьте отдельную schema:

{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Вопрос?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Ответ."
      }
    }
  ]
}

Хлебные крошки

{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {"@type": "ListItem", "position": 1, "name": "Главная", "item": "https://site.ru/"},
    {"@type": "ListItem", "position": 2, "name": "{subject}", "item": "https://site.ru/katalog/?subject={subject_slug}"},
    {"@type": "ListItem", "position": 3, "name": "{work_type}", "item": "https://site.ru/katalog/?type={type_slug}"},
    {"@type": "ListItem", "position": 4, "name": "{topic}"}
  ]
}

Внутренняя перелинковка

Минимум 10 ссылок на каждой странице:

  • 5 по тому же предмету
  • 3 по тому же типу работы
  • 2-3 на смежные темы
  • Блок "Похожие работы" внизу страницы

Шаг 7: Индексация

Sitemap

При 8 000+ URL разбивайте sitemap на файлы по 5 000:

<!-- sitemap-index.xml -->
<sitemapindex>
  <sitemap><loc>https://site.ru/sitemap-catalog-1.xml</loc></sitemap>
  <sitemap><loc>https://site.ru/sitemap-catalog-2.xml</loc></sitemap>
</sitemapindex>

IndexNow

Не ждите, пока Google сам найдёт страницы. Отправьте их через IndexNow:

import requests

def submit_indexnow(urls, host, key):
    """Отправка URL в IndexNow (Яндекс + Bing)."""
    payload = {
        "host": host,
        "key": key,
        "urlList": urls[:10000]  # Максимум 10К за запрос
    }
    
    r = requests.post(
        "https://yandex.com/indexnow",
        json=payload,
        headers={"Content-Type": "application/json"}
    )
    print(f"IndexNow: {r.status_code} ({len(urls)} URLs)")
    return r.status_code

Google Search Console

Отправьте sitemap через GSC. Следите за отчётом "Страницы":

  • "Просканировано, не проиндексировано" — Google видит, но считает контент недостаточно ценным
  • "Обнаружено, не проиндексировано" — Google знает URL, но ещё не дошёл
  • "Проиндексировано" — победа

Грабли, на которые мы наступили

1. Шаблонный текст = thin content

Первая итерация: шаблон с подстановкой {тема}. Google просканировал 397 страниц и проигнорировал все. Он умеет определять, что 25 000 страниц — это одна страница с разными названиями.

Решение: каждая страница генерируется индивидуально через AI с уникальным контентом.

2. AI дублирует задачи

Claude/GPT любит выдавать 5 одинаковых задач разными словами: "изучить основы...", "рассмотреть основы...", "проанализировать основы...". Добавьте в промпт явное: "Все задачи РАЗНЫЕ по содержанию. Если две задачи про одно и то же — это ошибка."

3. Грамматические ошибки в падежах

"В области праву", "Второй глава посвящена" — AI ломает падежи когда подставляет тему в шаблонную конструкцию. Лечится: "Проверь согласование. Каждое предложение должно быть грамматически верным."

4. Фейковые источники

AI выдумывает книги. "Петров А.А. Основы экологии. — М.: Наука, 2023" — такой книги может не существовать. Решение: попросите "только реально существующие учебники" и проверяйте выборочно.

5. 404 на части URL

28.8% страниц отдавали 404 из-за спецсимволов в slug. Проверяйте ВСЕ URL автоматически:

cat urls.txt | xargs -P 10 -I {} curl -s -o /dev/null -w "%{http_code} {}\n" {}

6. AI-агенты врут при проверке

Субагенты проверяли мета-теги через readability extraction и доложили, что "meta description отсутствует". На самом деле он был — просто readability-парсер его вырезал. Урок: проверяйте raw HTML, не рендеренный текст.

7. Казахские темы в русском каталоге

AI-генератор тем подсунул 310 тем на казахском языке. Фильтруйте по языку до генерации контента.

Чеклист перед запуском

  • Все URL отдают 200 (не 404, не 301)
  • Title уникален и до 60 символов на каждой странице
  • Meta description уникален и 140-160 символов
  • Canonical указывает на саму страницу
  • OG-теги заполнены
  • Schema.org: Article + FAQ + BreadcrumbList
  • Введение уникально (проверка дублей n-gram)
  • Минимум 10 внутренних ссылок на каждой странице
  • Sitemap обновлён и отправлен в GSC
  • IndexNow отправлен
  • robots.txt не блокирует каталог
  • Нет grammarly-уровня ошибок в текстах
  • Выборочная проверка 50 случайных страниц AI-ревьюером

Результаты

На реальном проекте:

  • Первая итерация (шаблон): 25 595 страниц → Google проигнорировал 397 из 397 просканированных
  • Вторая итерация (уникальная генерация): 8 000 страниц → Яндекс начал обход за 2 дня, индексация пошла

Стоимость второй итерации: ~$50 на Claude Sonnet API + 2 дня работы на промпты и скрипты.

Programmatic SEO работает. Но только если контент реально уникальный. Google в 2026 году отлично отличает шаблон от настоящего текста. AI-генерация — не волшебная кнопка "сделать 10 000 страниц". Это инструмент, которым нужно пользоваться с умом.

TG

> Пока нет комментариев