Как создать 8 000 уникальных SEO-страниц с помощью AI: полный гайд
Programmatic SEO — это когда ты генерируешь сотни или тысячи страниц под редкие поисковые запросы. Не руками, конечно. С помощью AI.
Звучит просто: взял шаблон, подставил переменные, получил 25 000 страниц. Но Google не дурак — он увидит 25 000 копий одного текста и проигнорирует их все. Мы проходили через это на реальном проекте и набили все возможные шишки.
В этом гайде — полный пайплайн: от идеи до проиндексированного каталога. С промптами, скриптами проверки и списком граблей, на которые мы уже наступили.
Для кого этот гайд
- Вайбкодеры, которые делают контентные проекты (образование, каталоги, справочники)
- Фаундеры, которые хотят SEO-трафик без команды копирайтеров
- Все, кто слышал про programmatic SEO, но не знает как сделать это правильно с AI
Как это работает: общая схема
Весь процесс состоит из 5 этапов:
- Собрать семантику — найти тысячи long-tail запросов в нише
- Спроектировать шаблон страницы — какие блоки, какие данные
- Написать промпты для генерации уникального контента каждого блока
- Сгенерировать страницы батчами через AI API
- Проверить качество через 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 ваши страницы или нет.
Что проверять
- Уникальность контента между страницами — нет ли повторяющихся фраз
- Грамматика и падежи — AI любит ломать русский язык в шаблонных конструкциях
- Релевантность — соответствует ли введение теме, а не общим словам
- Полнота — все ли поля заполнены, нет ли пустых FAQ
- SEO-атрибуты — title, description, schema.org, canonical, OG-теги
- Технические баги — 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_codeGoogle 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 страниц". Это инструмент, которым нужно пользоваться с умом.
> Пока нет комментариев