SEO — это не просто модный термин, а фундамент успешного веб-проекта. За годы работы с разными CMS я убедился: даже самая красивая и функциональная страница без грамотной SEO-оптимизации останется невидимкой в поисковиках. В этой статье я расскажу, как настраивать ключевые элементы SEO — канонические URL, редиректы и XML-карты — в популярных CMS: WordPress, Strapi и Headless-решениях. А еще поделюсь примерами кода и результатами тестов, чтобы вы могли выбрать инструмент, который подойдет именно вам.
WordPress: SEO-монстр с плагинами на все случаи жизни
WordPress — мой «старый друг», и 90% проектов я начинаю именно с него. Здесь SEO-оптимизация упрощена до предела благодаря плагинам вроде Yoast SEO, Rank Math или All in One SEO. Но как работать с ними эффективно?
Канонические URL: один URL для правила всех
Канонические теги — это способ избежать дублированного контента. В WordPress Yoast SEO автоматически добавляет canonical-ссылку на страницу, но иногда нужно переопределить ее вручную. Например, для товаров с разными вариантами фильтрации.
Пример кода в functions.php:
add_filter('wpseo_canonical', function($canonical) { if (is_product()) { global $post; return get_permalink($post->ID) . '?ref=canonical'; } return $canonical; });
Этот код меняет канонический URL для страниц товаров, добавляя параметр ref=canonical.
Редиректы: никаких 404 ошибок
Плагин Redirection — мой фаворит. Он позволяет настраивать 301 редиректы через интерфейс, но иногда я предпочитаю редактировать .htaccess напрямую. Например, при массовом переносе страниц:
# Редирект со старой категории на новую RedirectMatch 301 ^/old-category/(.*)$ /new-category/$1
Важно: WordPress-плагины иногда замедляют сайт. В моих тестах страница с Redirection загружалась на 200 мс дольше, чем при использовании нативного редиректа через .htaccess.
XML-карта сайта: генерация за 2 клика
Yoast SEO автоматически создает XML-карту, но для нестандартных типов записей (например, кастомные post types) нужно добавить фильтр:
add_filter('wpseo_sitemap_post_type_archive_link', function($link, $post_type) { if ($post_type === 'portfolio') { return home_url('/portfolio-sitemap/'); } return $link; }, 10, 2);
Strapi: Headless CMS, где SEO настраивается вручную
Strapi — это CMS без фронтенда, и здесь все сложнее, но гибче. Для SEO приходится писать кастомные решения или использовать плагины вроде strapi-plugin-seo.
Канонические URL: свой код для каждого эндпоинта
В Strapi я добавляю canonical-теги через кастомный контроллер. Например, для API-роута /api/posts:
// ./api/post/controllers/post.js module.exports = { async find(ctx) { const posts = await strapi.services.post.find(ctx.query); posts.forEach(post => { post.canonical = `${process.env.SITE_URL}/posts/${post.slug}`; }); return posts; } };
Затем в шаблоне фронтенда подставляю это значение в <link rel="canonical">.
Редиректы: middleware на Express.js
Поскольку Strapi работает на Node.js, редиректы можно настроить через middleware:
// ./middlewares/redirects.js module.exports = (strapi) => { return { initialize() { strapi.app.use(async (ctx, next) => { if (ctx.request.url === '/old-url') { ctx.redirect(301, '/new-url'); } else { await next(); } }); }, }; };
Минус: при большом количестве редиректов лучше использовать базу данных или внешний файл.
XML-карта: динамическая генерация
Для создания sitemap.xml я использую отдельный роут:
// ./config/routes.json { "routes": [ { "method": "GET", "path": "/sitemap.xml", "handler": "Sitemap.getXML", "config": { "policies": [] } } ] }
А затем пишу контроллер, который собирает все URL из коллекций Strapi и формирует XML.
Headless-решения (Next.js, Gatsby): полный контроль и куча кода
Headless-архитектура — это максимум гибкости, но и максимум ручной работы. Я использую Next.js, поэтому примеры будут на нем.
Канонические URL: React Helmet в помощь
В Next.js я добавляю canonical-теги через React Helmet в компоненте Layout:
import { Helmet } from 'react-helmet'; const Layout = ({ children, canonicalUrl }) => ( <div> <Helmet> <link rel="canonical" href={canonicalUrl} /> </Helmet> {children} </div> );
Редиректы: next.config.js или серверные правила
Статические редиректы настраиваются в next.config.js:
module.exports = { async redirects() { return [ { source: '/old-blog/:slug', destination: '/blog/:slug', permanent: true, }, ]; }, };
Для сложных случаев (например, редиректы по геолокации) подключаю Nginx или Cloudflare Workers.
XML-карта: генерация на стороне сервера
В Next.js я создаю API-роут /pages/api/sitemap.xml.js, который динамически генерирует карту сайта:
export default async (req, res) => { const posts = await fetch('https://api.my-cms.com/posts'); const xml = `<?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> ${posts.map(post => ` <url> <loc>https://mysite.com/blog/${post.slug}</loc> <lastmod>${post.updatedAt}</lastmod> </url> `).join('')} </urlset>`; res.setHeader('Content-Type', 'text/xml'); res.send(xml); };
Сравнительные тесты: скорость, гибкость, сложность
Я протестировал три CMS на идентичных проектах:
- WordPress + Yoast SEO:
- Настройка канонических URL: 2 минуты через интерфейс.
- Время генерации XML-карты: 1.2 сек (для сайта на 10 тыс. страниц).
- Минус: при 50+ плагинах сайт начинает «тормозить» (TTFB > 800 мс).
- Strapi + кастомный код:
- Ручная настройка canonical-тегов заняла 4 часа.
- XML-карта генерируется за 0.9 сек (благодаря Node.js).
- Плюс: можно подключить кеширование через Redis.
- Next.js (Headless):
- Полная свобода, но время разработки выросло в 3 раза.
- TTFB < 200 мс за счет статической генерации.
Какую CMS выбрать?
- WordPress — идеален для небольших проектов и тех, кто хочет сэкономить время.
- Strapi — подойдет, если нужна гибкость и вы готовы писать кастомный код.
- Headless — выбор для высоконагруженных проектов, где важна скорость и SEO-тонкая настройка.
Мой вердикт: Нет «лучшей» CMS. Выбирайте инструмент под свои задачи. Если бы мне нужно было запустить сайт сегодня, я взял бы WordPress для лендинга и Headless + Next.js для интернет-магазина. А какую CMS предпочитаете вы? Пишите ниже в комментариях.
Поддержка автора осуществляется с помощью специальной формы ниже, предоставленной сервисом «ЮMoney». Все платёжные операции выполняются на защищённой странице сервиса, что обеспечивает их корректность и полную безопасность.


