Последнее обновлене - 15 января 2023 в 16:55
Как оказалось, разметить сайт по Schema.org не представляет особой сложности. Главное понимать структуру файлов установленной темы и знать, какой код отвечает за вывод тех или иных элементов страницы и где он расположен.
Содержание:
Я не буду здесь углубляться в теорию и рассказывать для чего служит семантическая разметка страниц и о том, как наши космические корабли бороздят бескрайние просторы Вселенной. Ведь об этом прекрасно и доходчиво написано на ruschema.org, а также в статье «Введение в schema.org» в Яндекс.Вебмастере.
Отмечу лишь то, что при помощи тегов сущностей и их свойств, применяемых в Schema.org, поисковым системам проще определять, о чём повествует контент, размещённый на странице. Это облегчает поисковикам более точно отображать информацию.
Разметку Schema.org внедрил на все свои сайты около месяца назад. Ошибок в валидаторах микроразметки Яндекса и Google не наблюдаю. Однако, я бы не сказал, что это как-то улучшило показатели. Например, на посещаемости это никак не отразилось.
Чтобы проверить правильность разметки, я использовал валидатор микроразметки от Яндекс, а также инструмент проверки структурированных данных Google. Если оба эти инструмента не покажут ошибок, это просто супер.
В моём случае, гугловский инструмент показал вот такие результаты.
Отображение результатов проверки микроразметки в Яндексе выглядит не так компактно, как в Google, поэтому показываю видео.
Теги сущностей и их свойств
Для начала, приведу некоторые теги сущностей и их свойств, используемых в разметке Schema.org.
/***Список анонсов***/
itemscope itemtype="http://schema.org/BlogPosting"
/***Контент страницы записи***/
itemscope itemtype="http://schema.org/Article"
/***Комментарии***/
itemprop="comment" itemscope itemtype="http://schema.org/Comment"
/***Обычная статическая страница***/
itemscope itemtype="http://schema.org/Article"
/***Сайдбар (боковая колонка)***/
itemscope itemtype="http://schema.org/WPSideBar"
/***Footer (подвал сайта)***/
itemscope itemtype="http://schema.org/WPFooter"
/***Навигация сайта (главное меню)***/
itemscope itemtype="http://schema.org/SiteNavigationElement"
/***Изображения***/
itemscope="" itemtype="https://schema.org/ImageObject"
/***Постоянная ссылка на страницу***/
itemscope itemprop="mainEntityOfPage" itemType="https://schema.org/WebPage"
/***Организация***/
itemscope itemtype="https://schema.org/Organization"
/***Адрес***/
itemscope itemtype="http://schema.org/PostalAddress"
Теги свойств выглядят следующим образом.
Название страницы (текста) - itemprop="headline"
Текст записи - itemprop="articleBody" (возможно применять и для описания, если оно формируется, как часть из полного текста)
Описание - itemprop="description"
Дата публикации - itemprop="datePublished"
Автор - itemprop="author"
Категория статьи - itemprop="articleSection"
Изображение - itemprop="image"
Текст комментария - itemprop="text"
Имя комментатора - itemprop="creator"
Дата комментария - itemprop="datePublished"
Ссылка (применимо к главному меню и к изображению) - itemprop="url"
Год копирайта в футере - itemprop="copyrightYear"
Дата последнего изменения страницы - itemprop="dateModified"
Адрес - itemprop="address"
Улица - itemprop="streetAddress"
Индекс - itemprop="postalCode"
Расположение адреса - itemprop="addressLocality"
Телефон - itemprop="telephone"
Длина изображения - itemprop="width"
Ширина изображения - itemprop="height"
Логотип - itemprop="logo"
Как разметить пост (статью)
Первым делом, надо определиться с файлом темы, который отвечает за вывод поста. Как правило, это single.php. В моём случае файл называется content-single.php. У вас могут быть другие варианты.
Для разметки зададим сущность. Для этого необходимо найти тег, при помощи которого обёрнута область контента, то есть название статьи, сам текст и комментарии. У меня этот тег называется article, в других темах он может называться по иному, например div.
Тег article находится в файле content-single.php в самом начале и может выглядеть так:
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
Теперь, внутрь открывающего тега article я внесу тег сущности поста, и тогда строка примет вот такой вид:
<article itemscope itemtype="http://schema.org/Article" id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
Теперь сущность объекта размечена, осталось разметить её свойства, то есть такие данные, как адрес главной страницы, даты публикации и последнего изменения страницы, автор, текст статьи и другие. Действуем подобным образом, то есть внутри открывающих тегов дополняем их соответствующими значениями.
Сразу после открывающего тега article вставляю следующие строки:
//эта строка указывает на адрес страницы
<meta itemscope itemprop="mainEntityOfPage" itemType="https://schema.org/WebPage" itemid="<?php the_permalink() ?>"/>
//эта строка указывает на дату последнего изменения страницы
<meta itemprop="dateModified" content="<?php the_modified_time('Y-m-d')?>"/>
Далее, после вышеуказанных строчек, вставим следующий код, при помощи которого укажем сведения о том, кто опубликовал пост, его адрес, логотип и название сайта.
<div itemprop="publisher" itemscope itemtype="https://schema.org/Organization">
<div itemprop="address" itemscope itemtype="http://schema.org/PostalAddress" style="display:none;"> //при помощи display:none скрываем данные во фронтэнде, а показываем только поисковикам
<span itemprop="streetAddress">Улица</span>
<span itemprop="postalCode">Почтовый индекс</span>
<span itemprop="addressLocality">Страна, Область, Город</span>
<span itemprop="telephone">Номер телефона</span>
</div>
<div itemprop="logo" itemscope itemtype="https://schema.org/ImageObject">
<img itemprop="url" itemprop="image" src="путь к логотипу" style="display:none;"/>
<meta itemprop="width" content="ширина изображения логотипа">
<meta itemprop="height" content="высота изображения логотипа">
</div>
<meta itemprop="name" content="название сайта">
</div>
Дело осталось за малым. Найти в коде файла теги, отвечающие за вывод заголовка, категории, даты публикации и автора.
Например, код для заголовка у меня выглядел вот так:
the_title( '<h1 class="entry-title">', '</h1>' );
После внесённых изменений код приобретёт такой вид:
the_title( '<h1 itemprop="headline" class="entry-title">', '</h1>' );
Разметим дату публикации, автора и категорию, к которой относится пост.
Было так:
<span class="entry-author"><?php echo get_avatar( get_the_author_meta( 'ID' ), 48 ); ?> <?php esc_html_e('Hobo', 'bloger'); ?></span>
<span class="entry-date"><?php echo get_the_date(); ?></span>
<span class="entry-category"><?php esc_html_e('in', 'bloger'); ?> <?php vt_blogging_first_category(); ?></span>
А теперь:
<span class="entry-author" itemprop="author"><?php echo get_avatar( get_the_author_meta( 'ID' ), 48 ); ?><?php esc_html_e('Hobo', 'bloger'); ?></span>
<span class="entry-date" itemprop="datePublished"><?php echo get_the_date(); ?></span>
<span class="entry-category" itemprop="articleSection"><?php esc_html_e('in', 'bloger'); ?><?php vt_blogging_first_category(); ?></span>
Разметим текст статьи. Изначально код был таким:
<div class="entry-content">
код вывода текста
</div>
А теперь он выглядит так:
<div class="entry-content" itemprop="articleBody">
код вывода текста
</div>
Часто записи содержат медиафайлы, то есть изображения. Их мы также не можем оставить без внимания. Каждый пост может содержать различное количество изображений. Делать их разметку вручную каждый раз очень неудобно. Поэтому, воспользуемся следующим кодом, который поможет сделать разметку картинок в автоматическом режиме.
function micro_images_captions ($a , $attr, $content = null){
extract(shortcode_atts(array('id' => '', 'align' => 'alignnone', 'width' => '', 'caption' => ''), $attr));
if ( 1 > (int) $width || empty($caption) )
return $content;
$caption = html_entity_decode( $caption );
if ( $id ) $id = 'id="' . esc_attr($id) . '" ';
return '<div itemprop="image" itemscope itemtype="https://schema.org/ImageObject" ' . $id . 'class="wp-caption ' . esc_attr($align) . '" style="width: ' . (10 + (int) $width) . 'px">
' . do_shortcode( $content ) . '
' . $caption . '
</div>';}
function micro_image($content) {
$ar_mk = '!<img (.*?) width="(.*?)" height="(.*?)" (.*?)/>!si';
$br_mk = '<span itemprop="image" itemscope itemtype="https://schema.org/ImageObject"><img itemprop="url image" \\1 width="\\2" height="\\3" \\4/><meta itemprop="width" content="\\2"><meta itemprop="height" content="\\3"></span>';
$content = preg_replace($ar_mk, $br_mk, $content);
return $content;
}
add_filter('the_content', 'micro_image');
add_filter('img_caption_shortcode', 'micro_images_captions', 10, 3);
Работает ещё такой код, но с ним в разметке не отобразятся размеры изображения:
function micro_image($content) {
global $post;
$pattern = "<img";
$replacement = '<img itemprop="image"';
$content = str_replace($pattern, $replacement, $content);
return $content;
}
add_filter('the_content', 'micro_image');
Как разметить главную страницу
Будем работать с файлом главной страницы. Это может быть index.php. В моей теме за вывод главной отвечает файл с другим названием.
В этом файлике нам необходимо найти код, который ответственен за вывод списка анонсов статей. Для разметки надо взять тег сущности списка анонсов. Я нашёл общий тег, который оборачивает весь код в шаблоне и внутри открывающего тега внедрил сущность списка записей блога — blogposting.
Вначале код выглядел так:
<div id="post-<?php the_ID(); ?>" <?php post_class( $class ); ?>>
тут какой-то код
</div>
А теперь так:
<div itemscope itemtype="https://schema.org/BlogPosting" id="post-<?php the_ID(); ?>" <?php post_class( $class ); ?>>
тут какой-то код
</div>
Дальнейшая разметка главной страницы полностью аналогична разметке шаблона для записей. Структура её точно такая же. Различие только в том, что выводятся фрагменты текста (анонсы).
Отличаться будет только код, при помощи которого мы разметим миниатюры анонсов. В файл functions.php необходимо внести такой код:
function mayak_filter_thumbnail($content) {
$ar = '!<img width="(.*?)" height="(.*?)" (.*?)/>!si';
$br = '<span itemprop="image" itemscope itemtype="https://schema.org/ImageObject"><img itemprop="url image" width="\\1" height="\\2" \\3/><meta itemprop="width" content="\\1"><meta itemprop="height" content="\\2"></span>';
$content = preg_replace($ar, $br, $content);
return $content;
}
add_filter('post_thumbnail_html', 'mayak_filter_thumbnail');
Микроразметка страниц рубрик производится точно так же, как и разметка главной страницы. Необходимо только определиться с файлом, который отвечает за их вывод.
Микроразметка комментариев
Микроразметку комментариев я выполнил путём вставки кода в файл functions.php и изменения функции, при помощи которой выводятся комментарии.
Итак, в файл functions.php я добавил этот код:
/*** Микроразметка в комментариях start ***/
function micro_comment($comment, $args, $depth){
$GLOBALS['comment'] = $comment;
if ( 'div' == $args['style'] ) {
$tag = 'div';
$add_below = 'comment';
} else {
$tag = 'li';
$add_below = 'div-comment';
}
?>
<<?php echo $tag; ?> <?php comment_class( empty( $args['has_children'] ) ? '' : 'parent' ); ?> id="comment-<?php comment_ID(); ?>">
<?php if ( 'div' != $args['style'] ) : ?>
<div id="div-comment-<?php comment_ID(); ?>
" class="comment-body" itemscope itemtype="http://schema.org/Comment">
<?php endif; ?>
<div class="comment-author">
<?php if ( 0 != $args['avatar_size'] ) echo get_avatar( $comment, $args['avatar_size'] ); ?>
</div>
<?php printf( __('<div class="comment-author" itemprop="creator">%s:</div>' ), get_comment_author_link() ); ?>
<?php if ( '0' == $comment->comment_approved ) : ?>
<em class="comment-awaiting-moderation"><?php _e( 'Your comment is awaiting moderation.' ) ?></em>
<?php endif; ?>
<div class="comment-meta commentmetadata">
<span itemprop="datePublished" class="comment-author"><?php /* translators: 1: date, 2: time */ printf( __( '%1$s' ), get_comment_date('Y-m-d')); ?></span><?php edit_comment_link( __( '(Edit)' ), ' ', '' ); ?>
</div>
<div itemprop="text"><?php comment_text( get_comment_id(), array_merge( $args, array( 'add_below' => $add_below, 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) ); ?></div>
<div class="reply">
<?php comment_reply_link( array_merge( $args, array( 'add_below' => $add_below, 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) ); ?>
</div>
<?php if ( 'div' != $args['style'] ) : ?>
</div>
<?php endif; ?>
<?php
}
/*** Микроразметка в комментариях end ***/
Далее, в файле comments.php я нашёл функцию вывода комментариев, которая выглядит следующим образом:
<ol class="comment-list">
<?php wp_list_comments( array( 'style' => 'ol',
'short_ping' => true,
'avatar_size' => 70,
) );
?>
</ol>
<!-- .comment-list -->
Изменим код вот так:
<ol class="comment-list">
<?php wp_list_comments( array( 'style' => 'ol',
'short_ping' => true,
'avatar_size' => 70,
'callback' => 'micro_comment',
) );
?>
</ol>
<!-- .comment-list -->
Функция вывода комментариев может выглядеть и немного по-другому. Я приведу примеры функции до и после изменений:
//Если функция имеет следующий вид:
<?php wp_list_comments(); ?>
//То вызов функции, размещённой в файле functions.php делаем так:
<?php wp_list_comments('callback=micro_comment'); ?>
//Если изначально функция такая:
<?php wp_list_comments('type=comment&avatar_size=70'); ?>
//То меняем её на такой код:
<?php wp_list_comments('type=comment&avatar_size=70&callback=micro_comment'); ?>
Хотите показать поисковикам количество комментариев к статье? Никаких проблем! Ищем, код, похожий на этот:
<?php comments_number ?>
В открывающий тег, который оборачивает эту функцию (например, span), внедрим вот такой тег:
itemprop="commentCount"
Теперь функция приобретёт вид:
<span itemprop="commentCount"><?php comments_number('0','1','%') ?></span>
А вот ещё вариант разметки комментариев.
<?php comment_class( empty( $args['has_children'] ) ? '' : 'parent' ) ?> id="comment-<?php comment_ID() ?>" itemprop="comment" itemscope="itemscope" itemtype="http://schema.org/Comment">
//информация об авторе
<?php printf( __( '<cite class="fn" itemprop="creator">%s</cite>' ), get_comment_author_link() ); ?>
//время размещения комментария
<span itemprop="datePublished">
<?php printf( __('%1$s'), get_comment_date('Y-m-d')); ?>
</span>
в <?php comment_time('H:i'); ?>
//разметка текста комментария
<div itemprop="text"><?php comment_text(); ?></div>
Микроразметка шапки сайта (header)
Для разметки верхней части страницы необходимо внести изменения в файл темы:
header.php
Отыскиваем секционный элемент header и внутри открывающего тега добавим микроразметку. Получим следующее:
<body itemscope="itemscope" itemtype="http://schema.org/WebPage">
Далее, разметим название и описание сайта. Название блога я оборачиваю динамически в различные теги, в зависимости от того, на какой странице находится посетитель. Если это главная страница, то название блога в h1, анонсы же имеют заголовки в h2. Когда открыта страница записи (поста), название статьи отображается как заголовок верхнего уровня (h1), а название блога — это ссылка на главную страницу.
Выглядит это так:
<?php if (!is_home()): ?>
<a itemprop="name" href="<?php bloginfo('url'); ?>"><?php bloginfo('name'); ?></a>
<?php else : ?>
<h1 itemprop="name"><a href="<?php bloginfo('url'); ?>"><?php bloginfo('name'); ?></a></h1>
<?php endif; ?>
Для разметки, как видите, я использовал свойство name.
Описание размечаем атрибутом itemprop со свойством description:
<span itemprop="description"><?php bloginfo('description'); ?></span>
Микроразметка сайдбара (боковой колонки)
Разметка боковой колонки (сайдбара) проводится аналогично. За вывод этой части сайта, как правило, отвечает файл:
sidebar.php
Здесь нам надо найти блок содержимого боковой колонки и внутри открывающего тега (в моём случае — aside) разместить тег сущности, соответствующей сайдбару. Вот так:
<aside itemscope itemtype="https://schema.org/WPSideBar" id="secondary" class="widget-area sidebar">
Чтобы указать свойства сайдбара (название каждого используемого виджета), необходимо открыть файл функций functions.php
и изменить код:
register_sidebar( array(
'name' => esc_html__( 'Sidebar', 'vt-blogging' ),
'id' => 'sidebar-1',
'description' => esc_html__( 'Add widgets here.', 'vt-blogging' ),
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h3 class="widget-title"><span>',
'after_title' => '</span></h3>',
) );
Обратите внимание на 7 и 8 строки кода выше. Они определяют, что выводится перед заголовком виджета и после него. Это тег span. Внутри открывающего тега span (7 строка) укажем свойство имени:
itemprop="name"
В результате, код должен выглядеть так:
register_sidebar( array(
'name' => esc_html__( 'Sidebar', 'bloger' ),
'id' => 'sidebar-1',
'description' => esc_html__( 'Add widgets here.', 'bloger' ),
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h3 class="widget-title"><span itemprop="name">',
'after_title' => '</span></h3>',
) );
Микроразметка футера (подвала)
В файле footer.php я нашёл блок с содержимым нижней части сайта. В моей теме я работаю с открывающим тегом footer. Внутри него я прописываю тег сущности WPFooter.
<footer itemscope itemtype="http://schema.org/WPFooter" id="colophon" class="site-footer">
Далее, можно разметить дату копирайта внутри открывающего тега. Используем тег свойства:
itemprop="copyrightYear"
В конечном итоге, код приобретёт такой вид:
<div itemprop="copyrightYear"><?php echo date("Y"); ?></div>
copyrightYear
должно быть числовое значение даты. Если в тег обернуть слово или символ, валидатор микроразметки укажет на ошибку.Микроразметка главного навигационного меню
Чтобы разметить главное меню сайта, снова вернёмся к файлу header.php, где необходимо найти код, при помощи которого выводится меню.
У меня функция вывода меню выглядит так:
<?php if ( has_nav_menu( 'primary' ) ) { wp_nav_menu( array( 'theme_location' => 'primary', 'menu_id' => 'primary-menu', 'menu_class' => 'sf-menu' ) );
} else {
?>
Функция в моём случае обёрнута тегом nav, в который я внедряю тег сущности главного меню:
<nav itemscope itemtype="http://schema.org/SiteNavigationElement" id="primary-nav" class="main-navigation">
Но это ещё не всё. Ссылкам в меню надо добавить атрибут itemprop=»url». Поисковики будут видеть, что пункт меню — это ссылка. Если меню создано вручную, то весь код будет выглядеть так:
<nav itemscope itemtype="http://www.schema.org/SiteNavigationElement">
<ul class="menu">
<li itemprop="name"><a itemprop="url" href="https://hoboweb.ru/">Главная</a></li>
<li itemprop="name"><a itemprop="url" href="https://hoboweb.ru/kontakti/">Контакты</a></li>
</ul>
</nav>
В данном случае для атрибута itemprop используем свойства name и url.
Но мой сайт работает на CMS WordPress и меню формируется динамически. Поэтому, чтобы атрибут itemprop="url"
автоматом подставлялся к любому пункту менюшки, надо в файл functions.php внести вот такой код:
/* микроразметка menu */
function nav($content) {
$pattern = "<a ";
$replacement = '<a itemprop="url" ';
$content = str_replace($pattern, $replacement, $content);
return $content;
}
add_filter('wp_nav_menu', 'nav');
Можно добавить коды в тему
У всех темы разные и обладают различным набором функций. По желанию код можно унифицировать, для чего вставить соответствующие коды и внедрить разметку schema.org. Здесь уже ничего размечать не надо, просто копируем и вставляем в соответствующие файлы темы. Не забываем про стилевое оформление выводимых данных.
/***вывод даты публикации записи ***/
<span class="the_date" itemprop="datePublished"><?php echo get_the_date('Y-m-d'); ?></span>
/***вывод автора***/
<span class="author_line_block_about">Автор: <span itemprop="author"><?php the_author(); ?></span></span>
/***вывод количества комментариев***/
<span>Комментариев: <span itemprop="commentCount"><?php comments_number('0','1','%') ?></span></span>
/***вывод заголовка страницы***/
<h1 itemprop="headline"><?php the_title(); ?></h1>
/***вывод категории***/
<span id="category_line_block_about">
<!--noindex--><?php $current_categ = get_the_category(); if($current_categ) { foreach($current_categ as $cat){ $current_category_name = $cat->name;
$current_category_link = $cat->cat_ID;
}}
echo '<a rel="nofollow" href="'.get_category_link($current_category_link).'"><span itemprop="articleSection">'.$current_category_name.'</span></a>';
?> <!--/noindex-->
</span>
В посте рассмотрен достаточно большой объём информации, но и это ещё не всё. В отдельной публикации я покажу, как сделать микроразметку видеоролика при помощи плагина и без него. Посмотрите, как получить ссылку на превью ролика YouTube.
Тоже удалось разметить shema.org свой сайт по этой инструкции. оказывается, не так сложно.
Надеюсь, теперь вид сниппетов сайта в поисковой выдаче улучшился.
Разметил статьи, валидатор вроде ошибок не выдает.
Прекрасно!
Спасибо тебе чувак за подробную инструкцию. У меня получилось с разметкой.
Всегда пожалуйста!
Повлияло на посещаемость?
Не особо.
Спасибо хобо, я разметил!
Великолепно, Витя!
Только собрался разметить сайт по Schemaorg и тут нашёл ваш пост. спасибо, получилось у меня все сделать.
Вот и здорово, Антон, поздравляю с новой разметкой на сайте!