Маркетплейс готового бизнеса — это не «доска объявлений». Средний чек — от 1 до 20 млн рублей. Покупатель сравнивает объект месяцами. Любая мелочь в интерфейсе или выдаче может стоить сделки.
К нам пришли с рабочим JetEngine-сайтом и чёткой задачей: стать профессиональной площадкой, которая выигрывает у горизонтальных классифайдов (Авито, Циан) по SEO-охвату, доверию и поиску. За 3 месяца мы написали ~19 000 строк PHP в ~60 модулях и сделали 343 коммита. Результат — inbiz.ru.
1. Контекст: почему нельзя было просто «доработать сайт»
К 2026 году поисковые алгоритмы изменились настолько, что «сделать лендинг и купить рекламу» перестало работать в нише с высоким чеком. Google ранжирует по INP (Interaction to Next Paint) и смотрит на structured data для AI-ответов. Яндекс даёт нейро-выдачу тем, у кого есть Product, FAQPage и BreadcrumbList в разметке.
Базовый JetEngine-сайт не давал ни одной программатик-страницы под запросы «купить кофейню в Санкт-Петербурге» или «готовый барбершоп в Москве». Не было скоринга, форма объявлений висела на JetFormBuilder с нескрытой логикой, поиск работал как LIKE '%ключевое_слово%' по заголовку.
Решение: переосмыслить платформу целиком, не патчить существующее.
2. SEO-движок: программатик под тысячи регионов
Покупка бизнеса — локальный запрос. Человек ищет «кофейню в центре СПб до 3 млн» или «барбершоп с клиентской базой в Москве». Чтобы захватить этот трафик, нужны тысячи страниц — и каждая должна быть уникальной, а не дублем с заменой слова.
Мы построили систему /region/{город}/{категория}/:
- Авто-склонение H1: именительный, дательный, винительный — без хардкода, через морфологическую таблицу.
- Динамические токены в мета-тегах, OG, description:
{city},{city_dat},{category},{count}. - Шардированные sitemap: региональный + категорийный, обновляются при публикации.
- Ежедневная отправка свежих объявлений в Google Indexing API и Яндекс через системный cron (не WP-Cron, который пропускает отправки на слабонагруженных сайтах).
Полный structured data: Product с рейтингом и скорингом, Article, FAQPage, BreadcrumbList, WebSite + SearchAction. В 2026 году именно это определяет видимость в AI-ответах. Конкуренты с голым HTML туда не попадают.
Гигиена: 410 Gone для удалённых объявлений, 301 против дублей, HSTS, noindex на технический UI.
«Программатик без корректного склонения — это краш-тест в Яндексе. Первые два месяца мы разбирались с H1 и title по каждому городу отдельно, потому что "Объявления в Санкт-Петербурге" и "Объявления Санкт-Петербурга" — это разные запросы с разным объёмом».— команда Excella
3. Производительность: сборка под INP 2026
В 2026 Google ранжирует по INP — Interaction to Next Paint. Это не то же самое, что старый FID: INP измеряет отклик на каждый клик пользователя, не только первый. Большинство сайтов на WordPress с Elementor, JetEngine и десятком плагинов этот критерий не проходят по дефолту.
- AVIF/WebP-конвертер на лету +
<picture>— минус 40–60% вес изображений. - LCP-промоушн слайдер-изображения — PSI перестал жаловаться на «resource load delay».
- CLS-резервирование для карточек — CLS score < 0.05.
- Дефер 60+ скриптов и стилей — TTI минус 1.2 сек на мобайле.
- FastCGI-кэш nginx (60 мин) — TTFB < 80 мс для анонимов.
- OPcache 512 МБ + Redis object cache — PHP execution минус 35%.
Поиск написан INP-дружелюбно: debounce 180 мс, AbortController на каждый устаревший запрос — браузер не ставит в очередь десятки одновременных фетчей при быстром вводе.
4. Отказ от JetFormBuilder — своя форма объявлений
JetFormBuilder — мощный инструмент, пока логика укладывается в его модель. Как только появляется гостевая загрузка фото, черновики с лимитами, модерация и интеграция с оплатой — начинаются необъяснимые баги, которые невозможно ни отладить, ни покрыть тестами.
Мы написали собственный Abstract Form API (41 итерация, мигрировали 3 формы):
- Гостевая загрузка фото — REST
/v1/media, файлы привязываются к аккаунту после регистрации. Загрузка до авторизации = меньше трений на входе. - Drag-drop сортировка превью с AVIF-ресайзом на лету.
- Черновики —
post_status=draftс лимитами по тарифу и счётчиком в UI. - Срок жизни объявления — 30 дней, брокеры и админ — бессрочно.
- Модерация — новые и отредактированные объявления → pending, публикуются после проверки.
- Интеграция с YooKassa — форма знает о тарифе и инициирует оплату без редиректа на корзину.
// Валидация поля (упрощённо)
$field = new Inbiz_Form_Field_Price( 'ad_stoimost' );
$field->set_required( true )
->set_numeric( true )
->set_min( 1 )
->validate( $payload['ad_stoimost'] );
Каждый компонент — изолированный PHP-класс с явными зависимостями. Можно тестировать без WordPress-окружения.
5. Монетизация и слой доверия
Покупатель дорогого актива смотрит на десятки сигналов доверия до того, как выйти на контакт.
YooKassa без корзины
Прямые заказы wc_create_order, вебхуки с IP-whitelist (включая Cloudflare-диапазоны) и fallback-проверкой статуса на случай пропуска вебхука.
Скоринг бизнеса
Автоматическая оценка объявления по финансовым параметрам: выручка, прибыль, окупаемость, возраст, персонал. Отображается бейджем на карточке в листинге. Первый инструмент такого рода в нише на русском рынке.
Открытая форма «Связаться с продавцом»
Sticky в правом сайдбаре, мультиканал (Звонок / Telegram / WhatsApp / VK Max), авто-фото продавца из профиля, цель Яндекс.Метрики на отправку.
Чат покупатель↔продавец
Ответы через Telegram без входа в личный кабинет. Продавец получает сообщение в бот, отвечает там же, покупатель видит ответ на сайте.
6. Умный поиск: выше Avito по UX
Стандартный поиск классифайда — строка + фасеты. Вводишь «косметология» — ничего не находишь, потому что объявление называется «Салон красоты».
Синонимы → категория-зонтик
«Косметология», «барбершоп», «маникюр», «СПА» → «Красота и здоровье». Словарь синонимов для 16 категорий, написан вручную по частотным запросам.
Русская морфология
Лёгкий консервативный стеммер: «салоны», «салонов», «кофейни» → корневая форма. Без внешних библиотек, без ML — правила окончаний.
Разбор города из запроса
«Кофейня спб» → tax_query по Санкт-Петербургу. «Барбершоп москва» → только Москва. Пересечение нативное через WP_Query.
Поиск по описанию
Дефолтный WordPress ищет только в заголовке и post_content. Наш расширяет posts_search на мета-поле ad_opisanie — охват вырос в 3–5 раз на описательных запросах.
Ранжирование и аналитика спроса
Релевантность → оплаченное продвижение (boost_bumped_at) → скоринг. Запросы с нулевой выдачей пишутся в отдельную таблицу атомарным INSERT … ON DUPLICATE KEY UPDATE — постоянный сигнал для редакции: «это ищут, но не находят».
«Самый частый 0-результат в первую неделю после запуска — "сушилка для рук". Один брокер искал конкретный бизнес. Через неделю в таблице у нас было 47 уникальных бизнес-типов, под которые не было объявлений. Это готовый контент-план».— команда Excella
7. Контент-платформа как актив
В 2026 году SEO-трафик без E-E-A-T (опыт, экспертность, авторитет, доверие) теряет позиции — Google усилил сигналы качества контента.
Журнал
SEO-блог с длинными материалами: sticky TOC с прогрессом чтения, блок автора с E-E-A-T-полями, FAQ-аккордеон под schema, встроенные карточки объявлений (cross-sell), калькулятор окупаемости прямо в статье.
Clips
Stories и Reels: горизонтальный рейл на главной, fullscreen-просмотр с опросами, видеохаб с переключателем источника (VK Video / YouTube / RuTube) — российская аудитория распределена по всем трём платформам.
Собственный трафик = независимость от дорожающей перформанс-рекламы.
8. Что под капотом: безопасность и надёжность
Security review
Публичный REST-поиск (/wp-json/inbiz/v1/search) прошёл полный аудит перед деплоем: параметризованные WP_Query, экранирование на каждом HTML-стыке через esc()/hl(). SQL/XSS-поверхность закрыта, зафиксировано в коммите.
Durable-аналитика без race condition
Лог нулевых запросов хранится не в wp_options (read-modify-write сериализованного блоба = гонка при конкурентных запросах), а в собственной таблице. Суточный wp-cron удаляет шум (hits=1, старше 30 дней) — топ-сигналы остаются навсегда.
Кэш-дисциплина
Три слоя: nginx FastCGI (60 мин) → Redis object cache → OPcache 512 МБ. Чёткие правила инвалидации: кэшируются только анонимные запросы, при публикации объявления кэш связанных страниц инвалидируется через хук save_post.
Архитектура
Весь бизнес-код — в mu-plugins/, тема — только стили и хуки. PHP 8.3 с типизацией. Рефакторинг в изолированные классы. PHPUnit-обвязка вокруг общих хелперов — регрессии ловятся, не копятся.
9. Итог и цифры
- 343 коммита
- ~19 000 строк PHP в mu-plugins
- ~60 модулей
- 3 месяца от JetEngine-шаблона до prod
- 181 fix / 72 feat — продукт доведён, а не накидан
- 8 подсистем с ≥10 итерациями
Профиль «181 fix против 72 feat» говорит о том, что продукт доведён, а не накидан. Граничные случаи, мобайл, прод-инциденты, UX-правки — всё закрыто до релиза.
→ Посмотреть платформу: inbiz.ru


