YII СЕО оптимизация сайта

Written by
  • 2 года ago

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

Заголовок окна и метатеги

По правилам хорошего тона каждая наша запись должна сопровождаться корректным заголовком окна, описанием и ключевыми словами. То есть приблизительно так:

В представлениях мы можем добавлять метатеги как явно, так и как скрипты и стили с помощью компонента clientScript.

Достаточно вписать вручную только формирование заголовка. Для этого в классе CController уже имеется свойство pageTitle, так что мы без проблем можем использовать его в шаблоне:

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

Для хранения значений нужно не забыть добавить соответствующие поля в таблицу и модель наших статей. Если отдельные значения записывать не хочется, то можно генерировать их автоматически:

Хотя это не очень хорошо с точки зрения поисковой оптимизации.

Если конструкция с Yii::app()->clientScript кажется слишком громоздкой, то можно пойти по стопам свойства pageTitle и ввести новые поля description и keywords в базовый контроллер:

Теперь в представлениях достаточно присваивать значения этим полям:

А присвоенные значения уже выводить в шаблоне через clientScript или вручную:

Теперь для всех страниц и новостей можно будет прописывать метатеги.

Дубли значений метатегов

Какие значения <title> будет у первых четырёх страниц при паджинации блога про кроликов? Приблизительно такие:

Все разделы с перелистыванием страниц будут нести одинаковые имена.

Если вы решили закрыть все кроме первой страницы директивой Disallow в файле robots.txt, то переживать не стоит.

Аналогично с описаниями description категории. В панели вебмастеров Google вы встретите негодование поисковой системы по этому поводу. Из-за повторов заголовка в индексе будет находиться всего одна страница.

Самое лучшее решение в случае необходимости индексации всех страниц заключается в написании уникального заголовка для каждой. Это нам врядли под силу, поэтому проще сделать автоматическое добавление номера страницы:

Для этого достаточно получить номер и добавить его к значениям соответствующих полей:

Удобнее переместить всю логику в помощник:

и использовать его:

Теперь на сайте не будет дублирующихся заголовков.

Это не так уж хорошо решает проблемы ранжирования, но немного помогает.

Установка rel=nofollow для ссылок из блоков кода

Представим, что у нас есть какой-либо блок текста или облако меток со ссылками. Порой для исключения их из индексации и из распределения ссылочного веса страниц этот блок нужно поместить в <noindex> и всем ссылкам добавить атрибут rel="nofollow".

Для выполнения этой работы в представлении лучше всего подходит виджет. Напишем его:

Мы включаем буферизацию, получаем переданный HTML-код, удаляем атрибут rel у ссылок и подставляем rel="nofollow".

Теперь достаточно окружить любое меню данным виджетом:

и облако меток или вспомогательное меню не будет больше распылять ссылочный вес.

Определение текущего маршрута

Порой в представлении или шаблоне бывает нужно узнать, из какого действия и какого контроллера это представление вызвали.

В WordPress для определения текущего положения имеются функции is_front_page(), is_category и некоторые другие. Это удобно использовать, например, чтобы не использовать ссылку с логотипа на главной странице.

Для этих целей в Yii удачно подходит параметр route контроллера. Он содержит текущий маршрут, состоящий из имени модуля, контроллера и действия. Если модулей в системе нет, то он содержит только контроллер и действие. Это свойство можно использовать для условных конструкций в представлениях.

Предположим, что у нас есть какой-либо текст в сайдбаре, и мы хотим закрыть его от индексирования для всех страниц, кроме главной.

Для этого в шаблоне мы можем обрамить данный блок конструкцией <noindex> (или её валидным вариантом <!--noindex-->) для всех маршрутов, кроме SiteController::actionIndex:

Аналогично с условным вызовом рассмотренного ранее виджета можно открыть ссылки во вспомогательном меню только на главной странице:

Можно, например, вообще закрыть какое-либо меню на странице записи блога (то есть по маршруту blog/post/view) для избежания утечки ссылочного веса.

Аналогично можно использовать другие свойства контроллера:

Что равносильно прямому вызову соответствующих геттеров:

С их помощью можно легко определить имя текущего контроллера, действия и модуля.

Находясь в виджете переменная $this ссылается на сам виджет, а не на контроллер. Нужно сначала получить контроллер, а уже потом обращаться к нему:

Указание rel=nofollow для активного пункта меню

При построении любого меню с помощью виджета CMenu возникает ситуация, что активный элемент остаётся активной ссылкой и по-прежнему ссылается на текущую страницу. Получается бесконечная циклическая ссылка со страницы, ведущая на саму себя.

Переопределим и немного дополним метод CMenu::normalizeItems в нашем новом классе:

Мы взяли код из исходного метода и дописали пару строк:

в которых активным ссылкам добавляется соответствующий атрибут.

Теперь вместо zii.widgets.CMenu можно использовать свой класс Menu:

и активная ссылка будет автоматически снабжена атрибутом rel="nofollow".

Noindex для «хвоста» хлебных крошек

При использовании «хлебных крошек» с включённым выводом текущего заголовка у нас на странице будет дублирование текста. Например, так:

Одна и та же фраза (заголовок) написана два раза рядом, что не очень хорошо.

Для борьбы с таким контентным «спамом» можно заменить шаблон последнего элемента:

Если используются темы, то можно вернуть стандартное включение:

и использовать глобальную конфигурацию или скин views/skins/CBreadcrumbs.php:

Теперь активный пункт хлебных крошек будет неиндексируемым.

Борьба с дубликатами страниц

Как мы уже говорили в статье о маршрутизации, использование так называемых «правил по умолчанию» и достаточно гибкая система маршрутизации даёт нам весьма спорную возможность обращаться к одному и тому же действию по разным адресам:

Это относится и к главной странице сайта:

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

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

Рассмотрим несколько путей решения проблемы уникализации адресов.

Переадресация средствами сервера

Довольно банальный способ. Заключается в том, что нужно просто добавить редиректы в файл .htaccess. Сложно, муторно, но возможно.

Использование StrictParsing

Более эффективно использовать уже имеющиеся настройки компонентов. Кроме отключения showScriptName для скрытия index.php из адреса полезно включить строгую маршрутизацию useStrictParsing:

В этом режиме будут срабатывать только те правила, которые прописаны в rules, а адреса вроде /index.php/site больше не будут распознаваться как корректные. Это нам и нужно.

Но рассмотрим ещё раз правила по умолчанию (если вы их используете):

Первое, второе и последнее правила позволяют вполне «законно» использовать несколько вариантов адресов:

Поэтому нам необходимо отказаться от имеющихся правил по умолчанию и явно указать правила так, чтобы закрыть все возможные обходные пути, например:

Теперь имеются только строго заданные маршруты и одно и то же действие нельзя открыть по двум разным адресам.

Здесь мы также включили в адрес и параметр page, так как хотим, чтобы он входил в адрес, а не подписывался как отдельный GET-параметр через вопросительный знак.

Универсальные правила можно оставить для контроллеров или модулей панели управления. Но правила по умолчанию можно и оставить, если использовать канонические адреса, которые мы рассмотрим ниже.

Другой пример с модулями мы рассмотрели в статье о маршрутизации, на которую ссылались выше.

Псевдонимы записей

Предположим, что в своём блоге к ID записи нам нужно добавить человекопонятный «хвост», то есть вместо банального:

Выводить адрес с псевдонимом:

Для этого достаточно добавить правило:

И использовать псевдоним при создании адреса:

Теперь в действии view как и раньше получаем нужную запись по ID и выводим её на экран:

Всё бы хорошо, но так как здесь не учитывается переданный псевдоним, то его можно указать любым:

По всем возможным адресам будет открываться одна и та же запись.

Поэтому нужно либо добавить учёт псевдонима alias:

При этом при любой опечатке в псевдониме мы получим ошибку.

Либо, что интереснее, можно добавить ещё одно правило:

и ввести проверку адреса с принудительной переадресацией на правильный адрес

Тогда какой бы адрес мы ни ввели в адресную строку, с псевдонимом или без:

нас всегда будет перекидывать с неправильных адресов на единственно привильный:

Канонические ссылки

Успешно зарекомендовавший себя в SEO инструмен для внутренней оптимизации – это канонические ссылки. Например, мы можем зайти на сайт по ссылке в твиттере, рассылке или в рекламном блоке. Если эта система так работает или если вебмастеру хочется отслеживать источник прихода посетителя, то могут быть использованы дополнительные GET-параметры, например:

Чтобы поисковые системы вместо них засчитывали это как ссылку на «чистый» адрес, нужно добавить в HTML-код страницы каноническую ссылку на первоисточник:

Прстейший способ это сделать – это отбросить все GET-параметры, идущие после вопросительного знака (за это отвечает метод getPathInfo) и вставить исходный адрес прямо в код шаблона:

Либо разместить динамическое добавление поля в любом месте кода:

Например в методе beforeAction базового контроллера.

Теперь с какими бы GET-параметрами к нам не зашли, в индексе будет фигурировать только страница с «чистым» адресом.

Упорядочивание GET параметров

Если сложно прописать в правилах маршрутизации для нескольких параметров все возможные варианты, то можно добавить звёздочку в конце:

и Yii воспримет это так, что все параметры станет достраивать в путь в виде параметр/значение/параметр/значение, то есть будут доступны следующие адреса:

Теперь из метода getUrl типа товара мы можем вернуть адрес с параметром type:

что превратится в ссылку /shop/catalog/type/5.

А из аналогичного метода категории (которая, например, должна обязательно содержать тип) можно вернуть вторую ступень: