Настройка модуля Похожие записи из Jetpack

Jetpack. Похожие записи

Начнем с того что похожие посты не увеличивают трафик. Никак. Я проделал весь этот путь с Jetpack и после месяца использования среднее количество просмотров страниц в день не изменилось. Так что все эти рассказы и байки от маркетологов о похожих товарах постах не более чем мифы. В любом случае, похожие материалы в новостях ничего навязчивого и плохого из себя не представляют, поэтому почему бы не помочь посетителям проще находить похожие материалы?

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

Но ведь все и так работает

По умолчанию обе задачи решает сам Jetpack. Блок похожих публикаций добавляется в конец всех записей, используя фильтр the_content. Этот прием используется многими плагинами для добавления чего угодно в конец статьи — от кнопок социальных сетей, заканчивая формочками подписок. Я не считаю такое поведение хорошим тоном, потому что с точки зрения HTML-разметки к тексту добавляется нечто, что к нему совсем не относится. Пользователи Safari с кнопкой Reader и поисковики этого точно не оценят.

Что же касается стилей — Jetpack добавляет свой дополнительный CSS-файл на страницы, в котором, можно сказать, все в порядке. Но отдельный файл… Я как перфекционист мечтающий о том дне, когда все JS и CSS файлы будут склеены в один, не хочу лишних файлов, когда этого можно избежать. И самое главное — иногда блок выглядит недостаточно симпатично, поэтому следует потратить некоторое время на приведение его к виду и стилистике схожей с вашей темой.

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

Хорошие разработчики тем и плагинов пользуются фильтрами и экшенами, дающими невероятную гибкость. Покопавшись в исходном коде модуля можно убедиться в том, что блок с похожими постами добавляется в конец поста через фильтр.

protected function _action_frontend_init_page() {
	$this->_enqueue_assets( true, true );
	$this->_setup_shortcode();

	add_filter( 'the_content', array( $this, 'filter_add_target_to_dom' ), 40 );
}
public function filter_add_target_to_dom( $content ) {
	if ( !$this->_found_shortcode ) {
		$content .= "\n" . $this->get_target_html();
	}

	return $content;
}

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

function jetpackme_remove_rp() {
	$jprp = Jetpack_RelatedPosts::init();
	$callback = array( $jprp, 'filter_add_target_to_dom' );
	remove_filter( 'the_content', $callback, 40 );
}
add_filter( 'wp', 'jetpackme_remove_rp', 20 );

Отлично, Jetpack_RelatedPosts::init() тот самый аргумент, который мы искали! Но не стоит торопиться вставлять код из примера к себе. Если составить цепочку происходящего, можно заметить, что мы обращаемся к методу класса, которого может и не быть, поэтому при отключенном модуле этот код приведет к фатальной ошибке в PHP. Чтобы найти правильное решение, стоит заглянуть в исходный код самого Jetpack, впрочем, как и всегда. Что именно искать? Нечто, что позволит определять активен ли Jetpack и модуль похожих записей и тут на помощь приходит практика. Например, в плагине bbPress есть экшен bbp_init, к которому можно прицеплять свои функции и уже внутри смело использовать методы из bbPress, ведь bbp_init срабатывает только если bbPress активирован.

В Jetpack есть именные экшены, срабатывающие сразу после загрузки модуля (см. Github).

require Jetpack::get_module_path( $module );
do_action( 'jetpack_module_loaded_' . $module );

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

function selena_jetpack_remove_rp () {
	$jprp = Jetpack_RelatedPosts::init();
	remove_filter (
		'the_content',
		array ($jprp, 'filter_add_target_to_dom'),
		40
	);
}

function selena_jetpack_module_loaded_related_posts () {
	add_action ('wp', 'selena_jetpack_remove_rp', 20);
}
add_action ('jetpack_module_loaded_related-posts', 'selena_jetpack_module_loaded_related_posts');

Что здесь происходит? В момент срабатывания jetpack_module_loaded_related-posts (сработает только в том случае, если модуль активен) происходит добавление функции, которая описана в примере с официального сайта. Таким образом мы сможем включать и отключать модуль в любое время без необходимости вечно переписывать код.

Вывод блока похожих записей

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

<article class="entry">
	<header class="entry-header">
		<!-- Заголовок, имя автора, дата публикации и т. п.
	</header>
	<div class="entry-content">
		<!-- Текст записи -->
	</div>
	<div class="entry-meta">
		<!-- Соц. кнопки, похожие посты, список тегов и рубрик, ссылки на предыдущую и следующую запись и т. п. -->
	</div>
</article>

Уже в другом файле, selena-network/themes/selena/jetpack/related-posts.php, добавляем конструкцию, схожую с той, что удаляла фильтр:

function selena_network_themes_selena_related_posts ($content) {
	// Выводим только на страницах одиночных записей
	// Внимание, is_single() сработает и для других типов постов
	if (is_single ()) {
		// Получаем код блока из Jetpack
		$related = Jetpack_RelatedPosts::init()->get_target_html();
		return $content . '<div class="entry-meta-item">' . $related . '</div>';
	}
	return $content;
}

function selena_network_themes_selena_jetpack_module_loaded_related_posts () {
	// Мой фильтр внутри <div class="entry-meta">
	add_filter ('selena_entire_entry_meta', 'selena_network_themes_selena_related_posts', 15);
}
add_action ('jetpack_module_loaded_related-posts', 'selena_network_themes_selena_jetpack_module_loaded_related_posts');

Ура!

Блок похожих записей внутри тега <footer>

Блок похожих записей внутри тега <footer>

Тонкая настройка

На скриншоте выше можно заметить странные надписи вроде «В “Музыка”». Это рубрика, в которой находится запись, но по-русски будет лучше, если написать «Рубрика “Музыка”». Что ж, в исходном коде модуля похожих записей, как и во всех других, есть еще несколько полезных фильтров. Давайте исправим это.

function selena_network_jetpack_relatedposts_post_category_context ($post_cat_context, $category) {
	return sprintf(
		__ ( 'Category &bdquo;%s&ldquo;', 'selena_network' ),
		$category->name
	);
}
add_filter ('jetpack_relatedposts_post_category_context', 'selena_network_jetpack_relatedposts_post_category_context', 10, 2);

function selena_network_jetpack_relatedposts_post_tag_context ($post_tag_context, $tag) {
	return sprintf(
		__ ( 'Tag &bdquo;%s&ldquo;', 'selena_network' ),
		$tag->name
	);
}
add_filter ('jetpack_relatedposts_post_tag_context', 'selena_network_jetpack_relatedposts_post_tag_context', 10, 2);

С помощью фильтров jetpack_relatedposts_post_category_context и jetpack_relatedposts_post_tag_context мы заменяем надписи по умолчанию на свои, с правильными кавычками (в русском языке используются «елочки», а не „лапки“).

Еще можно убрать курсив у заголовка и добавить свои классы (я делаю это все в том же файле selena-network/themes/selena/jetpack/related-posts.php):

function selena_network_themes_selena_related_posts_headline ($headline) {
	return '<h3 class="jp-relatedposts-headline h4">' . __ ('Related posts', 'selena_network') . '</h3>';
}
add_filter ('jetpack_relatedposts_filter_headline', 'selena_network_themes_selena_related_posts_headline');

Напоследок не забудем отключить CSS-файл, который добавил Jetpack, ведь ниже мы напишем свои собственные стили внутри style.css из темы.

// Remove Jetpack styles
function selena_remove_jetpack_styles () {
	wp_dequeue_style ('jetpack_related-posts');
}
add_action ('wp_print_styles', 'selena_remove_jetpack_styles');
add_filter ('jetpack_implode_frontend_css', '__return_false');

На этом мы заканчиваем с выводом блока и займемся его стилизацией.

Стили

PHP-функция, которая используется для вывода похожих постов, на самом деле выводит лишь контейнер с заголовком. Все остальное генерируется с помощью Java Script.

<div id='jp-relatedposts' class='jp-relatedposts' >
<h3 class="jp-relatedposts-headline h4">Похожие посты</h3>
</div>

Здесь я не буду давать каких-то конкретных рекомендаций — все зависит от ваших предпочтений и темы. Строчки с категориями или тегами можно скрыть (display: none;), цвет ссылок или фона изменить, добавив фоновую картинку и т. д. В моей теме все стили для всех страниц содержатся в единственном файле для стилей — style.css. Ниже пример моего макета. Я нашел подходящую фотографию, которая немного взаимодействует с контентом.

Блок становится более интересным, если рядом добавить небольшую иллюстрацию

Блок становится более интересным, если рядом добавить небольшую иллюстрацию

Но об одной детали стоит упомянуть. Стили, которые добавляет Jetpack делают так, что ссылка на статью накладывается поверх контента с помощью position:absolute;, поэтому контент выглядит словно на нем нет ссылки, но становится кликабельным.

Схема верстки блока похожих записей

Некоторые сложности возникают для :hover-состояния. Контент находится вне ссылки, а значит селектор вроде a:hover .header не сработает. Поэтому в самом Jetpack hover-стили указываются не у ссылки, а у <div>. Это накладывает некоторые ограничения на верстку. К примеру, сетка из Bootstrap использует отрицательные margin-ы, в комлекте с этим hover даст неприятный эффект. Наводя курсор на <div>, он превращается в pointer, а кликнуть на самом деле нельзя, потому что это div, а не ссылка. Я выкрутился, используя хитрые селекторы. Такая конструкция заработала в последнем Хроме и IE, но в Safari на Маке двойной плюсик почему-то не сработал.

/*
 * Сработает для .jp-relatedposts-post-title
 * расположенного сразу после .jp-relatedposts-post-aoverlay
 * при наведении на .jp-relatedposts-post-aoverlay
 */
.jp-relatedposts-post-aoverlay:hover+.jp-relatedposts-post-title .jp-relatedposts-post-a {}


/*
 * Сработает для класса .jp-relatedposts-post-excerpt
 * при наведении курсора на .jp-relatedposts-post-aoverlay
 */
.jp-relatedposts-post-aoverlay:hover + .jp-relatedposts-post-title + .jp-relatedposts-post-excerpt

Для тех кто не очень понял что тут произошло рекомендую ознакомиться со списком селекторов. Если коротко, то символ + в селекторах означает, что необходимо выбрать те элементы, которые располагаются сразу после того, что было указано перед плюсиком 🙂

Заключение

В результате мы получили вывод «служебной» информации в месте, где она и должна логически находиться. Сделали верстку лучше и отзывчевее. Уменьшили количество подключаемых CSS-файлов на странице. Разобрались с очередностью срабатывания экшенов в Jetpack и WordPress. Настроили работу модуля таким образом, что при его отключении сайт не будет ломаться и выдавать фатальные ошибки.

При подготовке иллюстрации использовалась фотография Люкаса Кёллера.

Advertisements

One thought on “Настройка модуля Похожие записи из Jetpack

  1. “Начнем с того что похожие посты не увеличивают трафик. Никак. Я проделал весь этот путь с Jetpack и после месяца использования среднее количество просмотров страниц в день не изменилось. Так что все эти рассказы и байки от маркетологов о похожих товарах постах не более чем мифы.”
    Если пользоваться jetpack, который похожие записи выдаёт в js, то конечно никакого эффекта не будет, перелинковка-то больше для поисковиков нужна, а им подавай ссылки в html

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s