Евгений Горяев
Разработка, поддержка и развитие сайтов

Базовая поисковая оптимизация проекта на Yii2

Обложка для статьи Базовая поисковая оптимизация проекта на Yii2

В этой статье речь пойдет о том, на какие детали нужно обратить внимание и какие действия совершить с вашим проектом на yii2, чтобы начиная с первых дней после запуска, сайт хорошо индексировался поисковиками.  Те советы, которые я дам в этой статье, я вычислил из многочисленных технических заданий seo-оптимизаторов, которые работали с моим проектами. Безусловно, в каждом конкретном случае, был ряд индивидуальных рекомендаций, однако, есть целая группа правил и действий, которые можно (и нужно!) применить к любому проекту на yii2, если он является публичным веб-сайтом.

Для того, чтобы качественно и быстро выполнить анализ разрабатываемого вами сайте, я рекомендую установить такую программу как Screaming Frog. Это программа является эмулятором поискового паука. Она проходит по всем ссылкам на сайте, анализирует все заголовки, мета теги, показывает битые ссылки, и вообще является незаменимым инструментом для анализа сайта.

Далее я буду перечислять все те действия для первоначальной поисковой оптимизации, которые считаю делать необходимыми для успешного запуска сайта, и которые накопил на основе многих рекомендаций от сеошников. Некоторые из них будут совсем очевидными (но от этого не менее важными), значимость некоторых из них можно поставить под вопрос и долго о них дискутировать. Но для максимальной эффективности, я бы рекомендовал использоваться их все.

Рекомендации по оптимизации

SSL-сертификат

Использование защищенного соединения уже давно стало стандартом. Современные браузеры могут выдавать неприятные путающие пользователя сообщения, если сайт отдается по голому http, вместо защищенного https. Считается, что и поисковики, среди прочих равных, отдают предпочтение сайтам, отдающим контент по защищенному каналу.  Впрочем, даже если обратиться к здравому смыслу, то поддерживать шифрованное соединение между сервером и клиентом, даже если ваш сайт достаточно простой и не собирает у пользователя никаких данных - идея очень хорошая. Особенно, если учесть, что с финансовой стороны это не стоит ничего, а установка сертификатов Let’s Encrypt не займет более 10-15 минут.

Единый адрес сайта

По умолчанию, с настроенным ssl, сайт может быть доступен сразу по 4м адресам:

  • http://test.ru
  • http://www.test.ru
  • https://test.ru
  • https://www.test.ru

Необходимо сразу определиться, какой из этих 4х адресов будет основным. Для всех остальных доменов необходимо прописать редирект с кодом 301 на главный адрес, при этом не забывать пробрасывать с редиректом все параметры запроса, если они есть. Таким образом наш сайт будет иметь только один основной адрес, что избавит нас от задвоения контента в поисковом индексе. Если наш сайт должен открывать еще по каким-то дополнительными доменным именам, со всех этих адресов также делаем редирект с кодом 301.

Что касается реализации, то в конфиге nginx это выглядит проще некуда:

server {
    listen 212.24.44.179:80;
    server_name www.testsite.ru www.test-site.ru test-site.ru;
    return 301 https://testsite.ru$request_uri;
}

Очистка слешей на конце адреса

По-умолчанию, при работе с фреймворком yii2 с включенными prettyUrl, каждая страница сайта будет доступна по двум адресам без завершающего слеша и со слешем: “/task/index” и “/task/index/” буду оба отдавать 200й код и запускать нужный экшн в контроллере. Безусловно, можно попробовать проконтролировать все ссылки на сайте, чтобы нигде не было ссылки со слешем на конце, но помимо этого, можно потратить пару минут чтобы при запросах к сайту со слешем на конце, фреймворк сам редиректил их с 301 кодом на страницы без слешей.

Для этого в конфиге приложения указываем какой класс нам использовать и какой метод в нем запускать на при событии beforeRequest:

return [
    'on beforeRequest' => ['\frontend\components\SlasherRemover', 'run'],
    'id' => 'app-frontend',
    ...

Ну и сам код этого примитивного функционала:

namespace frontend\components;

use \Yii;

class SlasherRemover { public function run() { $pathInfo = Yii::$app->request->pathInfo; $query = Yii::$app->request->queryString; if (!empty($pathInfo) && substr($pathInfo, -1) === '/') { $url = '/' . substr($pathInfo, 0, -1); if ($query) { $url .= '?' . $query; } Yii::$app->response->redirect($url, 301); Yii::$app->end(); } } }

Хлебные крошки с микроразметкой

Хлебные крошки это вообще вещь полезная, с точки зрения опыта использования вашего сайта. Они помогают пользователю лучше ориентироваться на сайте, особенно, если у него сложная структура. Но не менее важно дать представление о структуре вашего сайта поисковому роботу. Для этого, помимо всего прочего, существует специальная микроразметка для хлебных крошек. Почитать о ней можно здесь и здесь. Написав однажды простой компонент для работы таких хлебных крошек, вы можете с легкостью использовать его во всех своих проектах. Собственно говоря, именно так я и поступаю. При этом, сейчас я даже не вижу смысла выносить этот функционал в отдельный composer-компонент. Я просто копирую руками помещаю свой компонент Breadcrumbs  в попку компонентов и вызываю его где мне надо, плюс закидываю нужный стили в scss или css-файл.

Open Graph для всего важного

Стандарт разметки open graph изначально был придумал в фейсбуке, но теперь используется повсеместно для прорисовки снипитта вашей страницы разными социальными сетями. Почитать о нем можно много где, просто загуглив эти два слова. Смысл его в том, что в блоке head вашей страницы необходимо разместить группу специфических мета-тегов, которые подскажут и социальным сетям, и поисковым роботам, какого рода контент является главным на этой странице и о чем она вообще. Для всех основных страниц сайта (статей, главной, страниц с видео-роликами, аудио материалами) необходимо корректно прописать эти самые open graph мета теги. Для этого можно использовать готовые решения с гитхаба, например dragonjet/yii2-opengraph, или достаточно быстро написать что-то подобное самому. В любом случае, использование open graph в современном мире необходимо. Подключайте его сразу, еще на стадии разработки проекта.

Robots.txt 

О том, что этот файл важный и нужный, думаю знают все. Но есть один момент, на который я бы хотел обратить внимание: разные файлы robots.txt для prod и dev окружения. Дело в том, во время разработки нам обязательно нужно закрыть сайт от индексирования. Часто так бывает, что нам нужно продемонстрировать новую или, скажем. промежуточную версию проекта заказчику, и мы разворачиваем ее на каком-то поддомене, в то время, как на основном домене у нас уже работает основная версия проекта. При этом у нас уже установлены на сайте счетчики аналитики и метрики.

В результате, когда мы запускаем сайт на тестовом поддомене, счетчики начинают отправлять в гугл и яндекс информацию, что сайт доступен и на других доменах. Хоть мы нигде не публиковали адрес тестовой копии, поисковые роботы начнут заходить на нее, индексировать, анализировать.

Чтобы избежать этого, нам надо закрыть от индексации всю тестовую копию. Если вы используете advanced template для вашего проекта, то в нем есть специальный скрипт для инициализации приложения (./init) и папки с конфигами и файлами для разного окружения (environments). Если вы используете basic template для вашего приложения, то рекомендую организовать там что-то аналогичное (можно легко перенести с темплейта advanced и сделать все по аналогии).

После этого, сохраните в папке environments свои варианты robots.txt - один для продакшена (со всеми необходимыми правилами), а второй для разработки и тестов, c правилом, запрещающим индексацию совсем. Таким образом, вы защитите свои неосновные копии сайта от попадания в индекс и образования в нем задвоения вашего уникального контента.

Что же касается “боевого” robots.txt, то главное, что нужно не забыть  в нем, это:

  • указать директиву Host, указывающую на ваш основной домен
  • обязательно указать ссылку на sitemap, при этом не относительную, а с вместе с доменом:
    Host: https://test.ru/
    Sitemap: https://test.ru/sitemap.xml
  • закрыть от индексации все служебные разделы, например всё, что связано с восстановлением пароля и личным кабинетом.
  • разрешить для индексации картинки роботам YandexImages и Googlebot-Image.

Sitemap.xml

Для генерации sitemap.xml у меня обычно всегда предусмотрен свой экшн в дефолтном SiteController. Если сайт особенно большой, нужно добавить кэширование. C технической точки зрения, тут нет ничего сложного. Сначала мы собираем массив всех страниц, которые необходимо отобразить в sitemap. Для этого сначала я наполняю его вручную основными разделами, потом пробегаю по необходимым моделям данных и добавляю в массив ссылки на страницы с активными объектами. В массив можно добавлять как вес страницы (priority), так и дату последнего изменения (modified, если необходимо). А дальше этот массив уже отправляем во вьюху, где в цикле из нее генерируется содержимое в формате xml. Простой вид контроллера:


public function actionSitemap()
{
    // Задаем хост
    $host = 'https://auto-mos.ru';
// Прописываем статические разделы
$ret[] = ['url' => $host . '/', 'priority' => 1];
$ret[] = ['url' => $host . '/articles', 'priority' => 0.5];
$ret[] = ['url' => $host . '/news', 'priority' => 0.5];
$ret[] = ['url' => $host . '/overviews', 'priority' => 0.5];


// Собираем адреса активных страниц
$pages = Page::find()->where(['status' => Page::STATUS_ACTIVE])->orderBy('path_full')->all();
if ($pages) foreach ($pages as $page) {
$ret[] = ['url' => $host . '/' . $page->path_full, 'priority' => 0.5, 'lastmod' => date("c", strtotime($page->updated))];
}

// Собираем адреса активных статей
$articles = Article::find()->where(['status' => Article::STATUS_ACTIVE])->orderBy('name')->orderBy('type, path')->all();
if ($articles) foreach ($articles as $article) {
if (!is_numeric($article->path))
$ret[] = ['url' => $host . '/' . $article->url, 'priority' => 0.5, 'lastmod' => date("c", $article->updated)];
}

// Выставляем формат ответ в XML
Yii::$app->response->format = \yii\web\Response::FORMAT_RAW;
$headers = Yii::$app->response->headers;
$headers->add('Content-Type', 'text/xml');

// Рендерим вьюху
return $this->renderPartial('sitemap', ['urls' => $ret]);

}


Хорошей практикой было бы автоматически проверить, все ли ссылки из sitemap действительно работают, открываются и отдают код 200.  Для этого можно даже было бы написать отдельный тест и таскать его из проекта в проект, но это как-нибудь в следующий раз.

Порядок в разметке страниц

Как это не банально, но необходимо также помнить и соблюдать базовые правила примитивной seo-оптимизации вашего сайта, а именно: 

  • На всех без исключения страницах должны быть заполнены поисковые мета-теги keywords и description
  • На всех страницах должен быть нормальный заголовок h1, причем я обычно делаю так, чтобы title страницы с ним совпадал
  • Желательно наличие и подзаголовка h2
  • Для всех изображений на сайта (и в дизайне сайта, и непосредственно в контенте) необходимо заполнять alt и title;
  • Предотвратить ссылки страниц на саму себя

Итоги

Подводя итог можно сказать, что для того, чтобы выполнить базовую seo оптимизацию вашего yii2 проекта перед запуском, можно сделать совсем небольшое количество действий, которые окажут крайне позитивное влияние на индексацию вашего сайта с самого начала. Если коротко, то всё вышеописанное можно привести к короткому чек-листу, выполнив который, можно получить хороший профит сразу после старта проекта. Итак, коротко о главном:

  • Нормальная верстка и разметка страниц (title, meta, alt, h1,h2);
  • Наличие адекватного robots.txt, закрывающего все в dev окружении;
  • Формирование актуального sitemap.xml;
  • 301й редирект со всех неосновных доменов с сохранением параметров запроса;
  • 301й редирект со страниц с слешем на конце;
  • Хлебные крошки с микроразметкой;
  • Разметка Open Graph на всех важных страницах сайта (в идеале - на всех).
  • Наличие SSL соединения на продакшене