Тема
SEO
SEO Blocks System
Архитектура
- Таблица
seo_blocks:page_type+position+format(html/faq/text) - Шаблоны с переменными в фигурных скобках:
{city},{category_gen},{price} SeoService::render(pageType, position, context)— подставляет переменные, возвращает коллекцию- Blade-компонент
<x-seo-blocks>— вызывает SeoService
Переменные шаблонов
| Переменная | Значение |
|---|---|
{city} | Город (именительный) |
{city_gen}, {city_dat}, {city_prep} | Город в падежах |
{category}, {category_gen} | Категория |
{brand} | Бренд |
{service} | Услуга |
{location} | Район/локация |
{price} | Цена "от X руб." |
{year} | Текущий год |
Positions
top— после H1, перед основным контентомbottom— после контента, перед footersidebar— боковая панель (если есть)
Formats
html— произвольный HTML (описание, преимущества)faq— вопрос-ответ, обёрнут в Schema.org FAQPagetext— plain text, автоформатирование параграфов
Meta-теги
Обязательные на каждой странице
<title>— уникальный, до 60 символов, ключевое слово в начале<meta name="description">— уникальный, до 160 символов, call-to-action<link rel="canonical">— всегда, даже на единственной версии URL- Open Graph:
og:title,og:description,og:url,og:type
Приоритет мета-данных
seo_metaтаблица (ручное переопределение для конкретной страницы)- Шаблон с подстановкой переменных (автогенерация по формуле)
- Default из модели (name / description)
H1
- Один
<h1>на страницу — без исключений - Может отличаться от
<title>(более подробный/с городом) - Иерархия: h1 → h2 → h3, не пропускать уровни
Schema.org (JSON-LD)
Обязательные типы
| Тип страницы | Schema.org type |
|---|---|
| Все страницы | Organization или LocalBusiness |
| Все страницы | BreadcrumbList (через компонент breadcrumbs) |
| FAQ-блоки | FAQPage + Question + Answer |
| Услуги | Service + provider + areaServed |
| Контакты | LocalBusiness с address, phone, geo |
Правила
- JSON-LD в
<script type="application/ld+json">— не microdata - Один
@typeна блок — не мешать несколько типов - Данные из моделей, не хардкод — чтобы обновлялись при изменении
Sitemap
Генерация
- spatie/laravel-sitemap или кастомный
SitemapService - Artisan-команда:
php artisan sitemap:generate - Запуск: при деплое + ежедневно по cron
Приоритеты
| Тип | Priority | ChangeFreq |
|---|---|---|
| Главная | 1.0 | daily |
| Категории | 0.8 | weekly |
| Сущности (услуги, товары) | 0.6 | monthly |
| Справочник, статические | 0.4 | monthly |
Исключить из sitemap
- Admin (
/admin/*) - API (
/api/*) - Auth-страницы
- Error-страницы
- Страницы с
noindex
robots.txt
Обязательные правила:
Disallow: /adminDisallow: /api/Sitemap: https://domain.com/sitemap.xml- Не блокировать CSS/JS файлы — нужны для рендеринга
URL-правила
- Все URL — lowercase
- Slugs — только
[a-z0-9-], без спецсимволов и кириллицы - Trailing slash — единая конвенция в проекте (обычно с
/) - При изменении URL — 301 redirect со старого на новый, навсегда
- Никогда не менять URL без явного одобрения
- Canonical — всегда на предпочтительную версию (с или без trailing slash)
Anti-patterns
| Паттерн | Проблема | Решение |
|---|---|---|
| Одинаковый title на всех страницах | Дубли в индексе, плохой CTR | Уникальный title с переменными |
| Отсутствие canonical | Дубли URL в индексе | Canonical на каждой странице |
| H1 = title | Упущенная возможность для другого ключа | H1 может быть подробнее |
| Несколько H1 на странице | Нарушение семантики | Один H1 |
| Schema.org хардкодом | Устаревает при изменении данных | Данные из моделей |
| sitemap с 404-страницами | Плохой сигнал поисковикам | Генерировать из актуальных данных |
| Блокировка CSS/JS в robots.txt | Google не может рендерить страницу | Разрешить статику |