У меня уже был движок — и он окупился
На одном из контентных порталов, которые я веду, давно работает раздел «Афиша концертов»: Python-генератор, который из одного JSON-файла с данными о концертах рождает около 1455 SEO-страниц — город как отдельная страница, артист как отдельная страница. Схему я подробно разбирал раньше: сущность становится страницей, шаблон добавляет уникальный текстовый блок, отдельный скрипт раз в неделю сверяет данные и перегенерирует то, что устарело. Раздел вышел в плюс и продолжает работать без ручного вмешательства.
И вот тут наступает момент, в котором легко ошибиться. Когда у тебя есть работающий раздел, соблазн — масштабировать его вглубь: добавить больше городов, больше артистов, больше данных в ту же вертикаль. Это тоже работает, но прирост становится всё дороже: свежих городов и артистов, под которые реально есть спрос, конечное число. Интереснее вопрос в другую сторону: можно ли тот же движок направить в совершенно другую тематику, а не в ту же самую.
Новая вертикаль: раздел «Спорт» почти бесплатно
Ответ оказался да, и почти буквально «почти бесплатно». Я запустил новый раздел — «Спорт» — с крупными спортивными событиями: Формула-1, теннисные турниры Большого шлема, чемпионат Европы по футболу 2028 года, Олимпиада 2028 года. Механика та же, что в афише: сущность (событие, город, где оно проходит) превращается в отдельную SEO-страницу под конкретный запрос, а не тонет в одном общем разделе «спорт» с фильтрами.
Разница в трудозатратах была разительной. Раздел «Афиша» — это были недели работы: спроектировать структуру данных, написать шаблонизатор, продумать уникализацию текста, вшить монетизацию, настроить автосверку. Раздел «Спорт» занял часы. Не потому что задача была проще по сути — а потому что 80% этой задачи уже было решено в первый раз, и решено было универсально.
Как это устроено технически: импорт, а не копипаста
Ключевое архитектурное решение видно прямо в названии файла. Новый генератор называется gen_sport, и он в буквальном смысле импортирует логику генератора афиши — модуль gen_afisha — вместо того, чтобы копировать его код в новый файл и подгонять под спорт.
from gen_afisha import (
build_entity_page,
enrich_with_unique_text,
inject_monetization,
render_template,
)
SPORT_EVENTS = load_json("sport_events.json")
for event in SPORT_EVENTS:
page = build_entity_page(event)
page = enrich_with_unique_text(page)
page = inject_monetization(page)
render_template(page)
Разница между «импортировать» и «скопировать и переписать» звучит как техническая деталь, но по факту это разница между активом и одноразовым скриптом. Если бы я скопировал код афиши в отдельный файл и подправил под спорт, у меня появились бы две независимые кодовые базы, которые нужно чинить отдельно при любой правке — например, если завтра я захочу поменять формат уникализации текста или добавить новый блок монетизации, придётся вносить правку дважды и следить, чтобы версии не разошлись.
- Данные — спортивные события живут в отдельном JSON-файле: событие, город, дата, категория (Формула-1, теннис, футбол, Олимпиада). Формат данных повторяет структуру афиши, но это отдельный файл про отдельную тему.
- Общая логика — рендеринг страницы, SEO-обогащение, перелинковка и монетизация вынесены в модуль
gen_afishaи написаны один раз, без привязки к тому, что именно на входе — концерт или спортивное событие. - Тонкая надстройка —
gen_sportпросто вызывает эти функции с новыми данными. Всё, что специфично для спорта — категории событий, формулировки текста, — живёт в тонком слое сверху, а не переписывает движок заново. - Наследование инфраструктуры — уникализация текста, партнёрские виджеты, автосверка данных достаются новому разделу даром: это тот же код, что и в афише, просто вызванный с другим входом.
Почему это вообще стало возможно
Такое переиспользование не случается само — оно возможно только потому, что при проектировании первого генератора данные с самого начала были отделены от шаблона, а общая логика — вынесена в отдельный импортируемый модуль, а не размазана внутри одного скрипта вперемешку с данными про концерты.
Если хотите, чтобы программатик-движок стал активом, а не одноразовым скриптом, проектируйте его по двум правилам с самого первого раза, даже если вторая вертикаль ещё не запланирована. Первое: данные всегда отдельно от шаблона — JSON, база, что угодно, но не захардкоженные строки внутри логики рендера. Второе: общая логика (рендер, SEO-обогащение, перелинковка, монетизация) живёт в отдельном модуле, который ничего не знает про конкретную тематику, а новый раздел — это тонкий слой данных и вызовов поверх него, а не копия файла с подмену переменных.
Если бы логика афиши была написана «конкретно под концерты» — с полями вроде artist_name и venue, зашитыми прямо в функции рендера, — переиспользовать её для спорта пришлось бы через болезненный рефакторинг, а не через строчку import. Универсальность движка — это не то, что можно добавить потом. Это решение, которое либо заложено на старте, либо обходится дорого задним числом.
Результат и урок про движок как актив
Главный вывод здесь не про концерты и не про спорт — про то, как думать о программатик-SEO движке в принципе. Написанный один раз генератор — это не разовая экономия времени на одном разделе. Это актив, который можно направить на новую тематику каждый раз, когда для неё есть данные, которые распадаются на сущности того же типа: событие, город, дата.
Разница в экономике огромная. Первая вертикаль стоит недели: архитектура, уникализация, монетизация, автосверка — всё с нуля. Вторая вертикаль на том же движке стоит часы: подключить новый источник данных и написать тонкий слой вызовов. Каждая следующая вертикаль — выставки, туры, что угодно с той же структурой «сущность = страница = запрос» — будет стоить примерно столько же, если движок изначально спроектирован с разделением данных и логики.
Практический вывод для тех, кто строит программатик-контент: не спрашивайте только «как сгенерировать эти страницы», спрашивайте «как сгенерировать эти страницы так, чтобы через полгода я мог направить тот же код на совершенно другую тему за час, а не за две недели». Это тот вопрос, который превращает разовый скрипт в масштабируемый бизнес-актив.