Как сделать микроразметку schema.org для рецептов при помощи функции

Опубликовано ,

Сразу оговорюсь — плагин Schema Creator by Raven я попробовала, но мне не особо понравилось, хоть и перевела его под собственные нужды. Поэтому взяла за основу только идею, но об этом позже.

Сначала хотела уместить все в одном файле, но текст получился уж больно объемным. Поэтому разделен на 2 части + введение.

Содержание:

Часть 1. Общая информация

Микроразметка schema.org: коротко о главном

Часть 2. Function

  1. Введение
  2. Микроразметка при помощи функций
    • Плюсы и минусы метода;
    • Разметка этапов приготовления;
    • Разметка ингредиентов;
    • Разметка изображений.

Часть 3. Custom fields

На истину в последней инстанции не претендую и готова выслушать все предложения =)

А так у нас выглядит плагин Schema Creator by Raven — в принципе, тоже неплохой вариант, но мне не захотелось его использовать ибо больная голова ногам покою не дает:

schema-creator-raven

За основу своей разметки я беру пример, приводимый в разделе «Помощь» Яндекс.Вебмастера. вот он:

html-microrazmetka schema.org

Для каждого рецепта у нас обязательные всего три поля: name (название), ingredients (ингредиенты) и recipeInstructions (инструкция по приготовлению), — их мы и разметим при помощи функции. Остальные пункты при желании можно задать при помощи произвольных полей. О том, как это сделать я расскажу в следующий раз.

Таким образом, каркас нашего рецепта будет выглядеть следующим образом:

<div itemscope itemtype="http://schema.org/Recipe"> /*задаем словарь*/
  <h1 itemprop="name">Заголовок</h1>                /*название рецепта*/
    <i itemprop="author">Автор</i>                  /*автор рецепта*/
       <h2>Ингредиенты:</h2>                        /*ингредиенты - маркированный список*/
          <ul>
            <li itemprop="ingredients">...</li>
            ....
          </ul>
       <h2>Приготовление:</h2>                      /*этапы - нумерованный список*/
          <ol itemprop="recipeInstructions">
            <li>текст этапа
               <img itemprop="image" src=" "/> 
            </li>
            .....
          </ol>
</div>

Если интересно, вот список всех поддерживаемых полей (мне достаточно необходимого минимума):

Поддерживаемые поля для разметки рецепта schema.org

Как вы понимаете, вручную вбивать это довольно нудно. Что ж, будем автоматизировать процесс.

Для работы нам понадобятся:

  • Размеченный как статья (Article) шаблон одиночной записи single.php;
  • Раздел «Рецепты» на блоге;
  • Внимательность

Микроразметка страницы с рецептом

Плюсы:

  • Полная автоматизация, никаких лишних действий
  • Минимальные исправления в шаблоне

Минус:

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

Разметка для названия и автора (если брать автор статьи — это автор рецепта) рецепта у нас такая же, как для Article, так что тут ничего менять не надо:

/*автор*/
<i itemprop="author"><?php the_author(); ?></i>

/*заголовок*/
<h1 itemprop="name"><?php the_title(); ?></h1>

Для внедрения микроразметки schema.org в шаблон записи я буду использовать функцию str_replace, заменяющую заданное выражение на новое. Однако, как мы видим из представленного выше шаблона разметки, тег <li> встречается у нас как в маркированном, так и в нумерованном списках, при этом в списке ингредиентов атрибут надо добавлять в каждую строчку. Так что, одной функцией в этот раз мы не отделаемся.

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

Для этого зайдем в админке «Записи/Рубрики» и выберем нужную категорию. У меня это, соответственно, «Рецептики». Для быстрого определения ID я добавила в файл функций function.php специальный сниппет, взятый с wp-kama, так что узнать номер рубрики не составляет труда:

id категории

Если же у вас не добавлена такая функция, заходим на страничку рубрики, щелкаем по адресу и смотрим айди:

id категории по адресу

Напоминаю. Не забывайте делать резервные копии при редактировании файлов шаблона. Лучше всего работать через FTP-клиент

1. Обозначим этапы приготовления

Что ж, начинаем писать первую функцию:

//микроразметка для этапов приготовления
function replace_recipe($recipe){
        $replace = array(
                // 'что заменяем' => 'на что заменяем'
                '<ol'=> '<ol itemprop="recipeInstructions"',
	); 
if(in_category(13)) {                      //задаем категорию
$recipe = str_replace(array_keys($replace), $replace, $recipe); //производим замену
}      
 return $recipe;                             //возвращаем значение функции
}
add_filter('the_content', 'replace_recipe');

Здесь мы задаем массив $replace, в котором в качестве ключа (array_keys($replace)) указываем, что требуется заменить, а в качестве значения — на что. При помощи функции замены str_replace заменяем существующие выражения на новые.

В данном примере массив состоит из одной строки, я оставила это так на случай, если придется вносить еще какие-то изменения в разметку рецепта.

Смотрим результат валидаторе Яндекса:

article-val

Как вы видите, у нас осталась микроразметка статьи — Article, следует ее заменить на Recipe. Поэтому открываем файл single.php и ищем блок, в котором задается тип шаблона. У меня он выглядит так:

<div itemscope itemtype="http://schema.org/Article" class="main_content">

Заменяем ее на следующее (не забываем добавить свой ID):

<?php if (in_category(13)) { ?>  /*для категории "Рецепты" - тип рецепты*/
    <div itemscope itemtype="http://schema.org/Recipe" class="main_content">
<? } else { ?>                   /*для остальных - статья*/
    <div itemscope itemtype="http://schema.org/Article" class="main_content">
<? } ?>

Проверяем в валидаторе:

recipe-val

Как видите, у нас осталось еще два лишних атрибута. Заменяем их аналогично:

/*атрибут для текста статьи*/
<?php if (in_category(13)) { ?>
   <?php the_content(); ?>
<? } else { ?>
   <div itemprop="articleBody"><?php the_content(); ?></div>
<? } ?>

/*атрибут для рубрики*/
<?php if (in_category(13)) { ?>
   <?php the_category(', ') ?>
<? } else { ?>
   <span itemprop="articleSection"><?php the_category(', ') ?></span>
<? } ?>

И снова проверяем:

instructions-val

Отлично, теперь переходим к следующему этапу.

2. Добавляем атрибуты к ингредиентам

val-recipe-ingredients

Теперь задание посложнее — следует добавить атрибут только к <li>, находящимся внутри маркированного списка <ul>

//разметка ингредиентов
function ingredients($ingr){ 
if(in_category(13)) {            //задаем категорию
$ingr = Preg_Replace_Callback(
    '!<ul>(.*?)</ul>!si',      //регулярное выражение для тегов и их содержимого
    Create_Function(
        '$matches',
        'Return Str_Replace("<li>", "<li itemprop=\"ingredients\">", $matches[0]);'   //заменяем
    ),
	$ingr
);
}     
 return $ingr;      
}
add_filter('the_content', 'ingredients');

В этот раз мы используем preg_replace_callback, которая осуществляет поиск по регулярному выражению и замену. От preg_replace данная функция отличается использованием дополнительной функции обратного вызова. В данном случае это create_function. Таким образом, мы ищем в тексте теги <ul>…</ul> и добавляем атрибут в каждый из <li> внутри.

Обратите внимание на «<li itemprop=\»ingredients\»>» — кавычки в атрибуте приходится экранировать.

Затем возвращаем результат.

Надеюсь, все понятно…

Проверяем:

ingredients-val

3. Заменяем изображения

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

//микроразметка для изображений
function schema_image($img){     
    $img = str_replace('<img','<img itemprop="image"', $img);    
    return $img;      
}
add_filter('the_content', 'schema_image');

Ну и проверка в валидаторе:

image-val

 

Вот и все =) Добавлять все три функции следует в файл functions.php перед закрывающим тегом ?>

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

Если что не получается или есть какие-то предложения — обязательно говорите.

38 комментариев

  1. Антонина

    Добрый день, Анастасия! Хочу по вашей статье сделать микроразметку, но не поняла с какими файлами работаем. Открыть существующий single.php или (Размеченный как статья (Article) шаблон одиночной записи single.php;)создаем новый? Куда вставлять? Как это все должно выглядеть поэтапно? Как потом работать с рецептами? Вопросов очень много. Можно поподробней расписать для новичков? Спасибо.

    Ответить
    1. Анастасия

      Здравствуйте, Антонина, ссылка на начальную разметку дана в начале статьи — http://wp-fairytale.ru/optimization/mikrorazmetka-schema-org.html
      Подробнее расписать смогу только через неделю-две, спасибо за вопросы, учту в дальнейших статья.
      Немного переработала метод из этой статьи, уже действует на кулинарном сайте. Об этом и напишу

      Ответить
  2. Артем

    Приветствую! Интересные решения, взял на заметку. Правда я больше предпочитаю полями размечать, хотя на действующих сайтах умрешь конечно.
    Такой вопрос, как размечать главную для рецептов под Яндекс. Яша в своем репертуаре, обязательных тег у него — ингредиенты, а вот как их на главной не заметно вывести уже бошку сломал…. Ведь ингредиентов может быть много…

    Ответить
    1. Анастасия

      Здравствуйте, а зачем главную страницу размечать ингредиентами? И что значит незаметно? =)
      То, что тут описано, хорошо действует, но я уже путь проще нашла, опишу, как будет время

      Ответить
      1. Артем

        Согласно Яндекса, при разметке рецептов должно быть 2 обязательных поля: название и ингредиенты. Причем Гугу требуется только название. Так вот когда делается разметка рецептов, то на странице рецепта, естественно указываются все возможные сущьности (название, время, категорию и тд), а вот на странице со списком (главная, архивы, страница рубрик, в общем, там где идет лента рецептов), не обязательно размечать все. Но при этом Яндекс-то требует ему еще ингредиенты показать, а как правило этих ингредиентов может быть много, вот я и думаю как сделать разметку рецептов в ленте, но при этом Яша ошибку не выдавал и ингредиенты в ленте не показывать.
        Если не секрет, какой еще путь? Куда проще-то…

        Ответить
        1. Анастасия

          В ленте не надо ингредиенты размечать, она как лента постов размечается. Как рецепт размечается конкретно рецепт.

          Ответить
          1. Артем

            Почему? Как-то не логично получается, там рецепт, а в ленте посты. Ели уж размечать, то надо и в ленте указывать, что вот это рецепт, а вот этот анонс- просто статья

            Ответить
          2. Анастасия

            Потому что см. документацию Яндекса:

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

            Ответить
          3. Артем

            Ссылочку можно, а то что такого не нашел в документации

            Ответить
          4. Анастасия

            Вот https://help.yandex.ru/webmaster/recipes/culinary-owners.xml
            Плюс в самой спецификации schema.org нет ничего для разметки списка рецептов

            Ответить
          5. Артем

            Спасибо. Спорить не буду, но должна прослеживаться логика. Формально лента — это список страниц или в случае с рецептами: список рецептов. Лучше уж тогда вообще никак не размечать, логичнее будет
            В схемаорг и про блог ничего нету про список постов, но при этом все размечают. Хотя по той же спецификации можно использовать ListItem

            Ответить
  3. Тоха

    Анастасия помогите мне настроит для блога разметку. ОШИБКА: префикс article неизвестен валидатору, укажите его явно атрибутом prefix

    http://secret-recipe.ru/vipechka/pechene-s-tvorogom-k-chayu.html

    В долгу не останусь $

    Ответить
    1. Анастасия

      Здравствуйте, эта ошибка обычно создается СЕО плагинами или соц плагинами при подключении разметки для соц. сетей Open Graph, ибо ими она создается под Гугл, а Яндекс его не понимает.
      Для исправления следует переписать добавляемый плагином prefix

      Ответить
    2. Артем

      Кому интересно, я решил как убрать данную ошибку https://www.youtube.com/watch?v=TJV4JOPul1E

      Ответить
      1. Анастасия

        Привет =) А я просто функцию написала под Yoast SEO, которая ее правит. Выложу, как будет время

        Ответить
        1. Артем

          Привет! Ну и я функцию написал, там функция-то совсем простая

          Ответить
          1. Анастасия

            Уже вижу =)
            Я до простого добавления не додумалась, отключила фильтр Йоста и заново прописала))

            Кстати, я микроразметку рецептов стала немного по-другому в последних проектах делать, над статью переписать.

            Смотрю у тебя дизайн новый, мне нравится. Тольк доктор Веб почему-то блокировать сайт стал, пришлось в исключения добавлять

            Ответить
          2. Артем

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

            Статью переписывай, интересно что придумала новенького…

            Ответить
          3. Анастасия

            Я все иду о пути упрощения. Добавила функции, шорткод и произвольные поля. Объединю скорее всего в самый простой плагин под Яндекс, но пока некогда.
            Сейчас эту систему буду тестировать на сайте заказчицы.
            Меня вообще заказчицы мотивируют наипростейшие способы выдумывать

            Ну у меня Опен Граф добавляется плагином соц сетей, там гораздо все проще настраивается. Йоста для интереса поковыряла, для клиентов))

            Ответить
          4. Артем

            Плагин — это хорошо и правильно, ели сайт новый, а вот зачем нужны поля есть сайт действующий? Заказчицы будут все статьи перелопачивать и добавлять данные или ты как-то данные подтягиваешь автоматом?

            Кстати, а что у тебя за плагин соц сетей? Платное что-то?

            Ответить
          5. Анастасия

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

            Плагин платный, да, но очень его люблю и ставлю себе на все сайты. Easy social share button

            Ответить
          6. Артем

            Все логично. А зачем категорию включать? Это же таксономия, зачем ее через поле вносить?

            Ответить
          7. Анастасия

            Категорию рецепта,имею в виду. Ну там горячее и тп

            Ответить
          8. Артем

            А-а-а, это то, что называется метод приготовления…

            Ответить
          9. Анастасия

            Я, кстати, решила, что не буду писать статьи на темы, которые сейчас все обмусоливают. Типа как ссылки скриптов закрыть, плагин настроить и тп, тольк про свои разработки, идеи.
            Открою ещё информационный раздел, там распишу ответы на вопросы, что чаще всего мне заказчики задают, чтоб по десять раз не отвечать

            Ответить
          10. Артем

            Хорошая идея, А что задают?

            Ответить
          11. Артем

            Кстати, есть предложение. Если разобралась с Дженезис фреймворком, то про него можно писать. В рунете ничего про него нет, ни сниппеты, ни решения, ни как вообще пользоваться. А вещь-то удобная!

            Ответить
          12. Анастасия

            Мне генезис очень нравится, я часто под него делаю. Сейчас потихоньку от него ухожу, уже разработала свой каркас, теперь допиливаю. Надеюсь, будет время и наконец закону две бесплатные темы
            Мне кажется, у нас никто не покупает его, если тольк с инета прут)) не любит у нас народ по 60 баксов тратить
            Я планируют на английском дочерние темы под него

            Ответить
          13. Артем

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

            Да дочерки под него неплохие должны получаться…

            Ответить
          14. Анастасия

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

            Ответить
          15. Анастасия

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

            Ответить
          16. Артем

            Это что, новая волна блоггеров пошла или со старыми сайтами?

            Ответить
          17. Анастасия

            Да что новый, что годовалый, как показывает практика, ошибки те же))

            Ответить
  4. Артур

    Спасибо! Очень полезная статья.

    Ответить
  5. Елена Прекрасная

    Привет, Настя! Классная разметка для рецептов, я себе уже тоже такую захотела для рубрики Кулинария)

    Ответить
  6. Света

    Подскажите Анастасия. Если добавить все это, то надо будет все опуликованные рецепты на сайте удалять и добавлять снова, или эта микроразметка итак будет загружается из function.php с уже опубликованными рецептами? И ещё вопрос, если у меня несколько категорий, где рецепты, то id каждой категории надо через запятую приписывать в (in_category(13)) или как?

    Ответить
  7. Михаил

    Ура, всё получилось! Спасибо вам Анастасия! Очень полезная статья.

    Ответить
  8. Людмила

    Нужно ли сейчас прописывать что-то кроме itemprop=»image»‘ для картинок?

    Например конструкция вида

    <pre class="prettyprint lang-html data-start-line="1" data-visibility="visible"<img itemprop=»url» src=»адрес_изображения» alt=»****» width=»ширина» height=»высота»/>
    <meta itemprop=»width» content=»ширина»>
    <meta itemprop=»height» content=»высота»> </div>

    Ответить

А что вы думаете по этому поводу?

Ваш e-mail не будет опубликован.

Добавить в комментарий код: CSSHTMLPHP