В этой статье приведена инструкция для CMS MODX Revolution по добавлению структурированных данным на страницы, материал на которых соответствует объекту «Article» из «schema.org». В качестве способа разметки будем использовать JSON-LD.

Что такое JSON-LD?

JSON-LD – это формат описания контента (связанных данных) с помощью JSON. Данные в этом формате представляют собой набор пар ключ-значение. Описание данных в JSON-LD можно осуществлять с помощью различных словарей, но в этой статье будем использовать «schema.org».

Для указания словаря используется ключ «@context», а типа описываемой сущности - «@type».

Например:

{
  "@context": "http://schema.org",  
  "@type": "Article"
}

Это зарезервированные ключи. После них нужно описать сам этот объект. Осуществляется это аналогичным образом, т.е. с помощью набора пар ключ-значение. Имена ключей и формат значений, которые они должны содержать в этом случае нужно брать для типа «Article» из словаря «schema.org».

Например:

{
  "@context": "https://schema.org",
  "@type": "Article",
  "mainEntityOfPage": {
    "@type": "WebPage",
    "@id": "https://myblog.ru/post-1"
  },
  "headline":"Нзвание статьи",
  "image":[
    "https://myblog.ru/images/1.jpg",
    "https://myblog.ru/images/2.jpg"
  ],
  "datePublished": "2020-01-19T12:30:00+03:00",
  "dateModified": "2020-01-20T15:17:00+03:00",
  "author": {
    "@type": "Person",
    "name": "Имя автора статьи"
  },
  "publisher": {
    "@type": "Organization",
    "name": "Мой блог",
    "logo": {
      "@type": "ImageObject",
      "url": "https://myblog.ru/images/logo.png"
    }
  },
  "description": "Описание статьи..."}
}

Проверить структурированные данные можно с помощью соответствующего инструмента Google:

Проверка структурированных данных с помощью инструмента Google

Познакомиться с различными элементами структурированных данных можно на ресурсе Google для разработчиков..

Вставка JSON-LD на страницу выполняется следующим образом:

<script type="application/ld+json">
{
  // здесь должны находиться структурированные данные...
}
</script>   

Поместить эту конструкцию согласно рекомендациям Google лучше всего в элемент head.

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

А чем поисковая система лучше поймёт контент страницы, тем она будет более релевантной соответствующему запросу. В результате это приведёт к возрастанию количества целевых пользователей, которые будут переходить из поисковой выдачи на данный сайт.

В настоящее время поисковые системы Google и Яндекс понимают формат JSON-LD и рекомендуют его к внедрению.

Как проверить микроразметку?

Проверка структурированных данных на странице обычное выполняется с помощью соответствующих инструментов Яндекса и Google.

Результат проверки структурированных данных с помощью валидатора микроразметки «Яндекс.Вебмастер»:

Проверка структурированных данных с помощью валидатора микроразметки Яндекса

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

Как сформировать структурированные данные и добавить их на страницу?

Формирование структурированных данных на стороне сервера (с помощью PHP) выполняется довольно просто.

Для этого нужно создать ассоциативный массив и наполнить его определёнными данными.

Например:

<?php

// данные, которые мы получили из базы данных или каким-то другим способом
$url = 'https://myblog.ru/post-1';
$title = 'Название статьи';
$description = 'Описание статьи...';
$images = [
  'https://myblog.ru/images/1.jpg',
  'https://myblog.ru/images/2.jpg'
];
$datePublished = '2020-01-19T12:30:00+03:00';
$dateModified = '2020-01-20T15:17:00+03:00';
$author = 'Имя автора статьи';
$siteName = 'Мой блог';
$siteLogo = 'https://myblog.ru/images/logo.png';

// создадим ассоциативный массив из данных
$data = [
  '@context' => 'https://schema.org',
  '@type' => 'Article',
  'mainEntityOfPage' => [
    '@type' => 'WebPage',
    '@id' => $url
  ],
  'headline' => $title,
  'image' => $images,
  'datePublished' => $datePublished,
  'dateModified' => $dateModified,
  'author' => [
    '@type' => 'Person',
    'name' => $author
  ],
  'publisher' => [
    '@type' => 'Organization',
    'name' => $siteName,
    'logo' => [
      '@type' => 'ImageObject',
      'url' => $siteLogo
    ]
  ],
  'description' => $description
];

Затем полученный массив необходимо перевести в формат JSON и возвратить его в качестве результата:

echo json_encode($data, JSON_UNESCAPED_UNICODE);

После этого результат вышеприведенного скрипта необходимо поместить в элемент script с типом «application/ld+json»:

<!-- data_in_json.php - это скрипт, который возвращает данные в формате JSON-LD для этой статьи -->
<script type="application/ld+json"><?php include 'data_in_json.php'; ?></script>   

В зависимости от того, как у вас организована бэкенд-часть сайта, вышеприведённый пример в большинстве случаев нужно будет каким-то определённым образом адаптировать под неё.

Данная инструкция применительно к CMS MODX Revolution будет иметь следующий вид.

Инструкция по добавлению JSON-LD для CMS MODX

Добавить структурированные данные в формате JSON-LD на страницу со статьями в CMS MODX можно следующим образом.

1. Создать сниппет и поместить в него следующий код:

Создание сниппета для формирования структурированных данных в формате JSON-LD
<?php

// если на этой странице контент не является объектом "Article", то завершаем работу (на сайте статьи имеют шаблон с id = 2)
if ($modx->resource->get('template') !== 2) {
  return;
}

// URL сайта
$siteUrl = $modx->getOption('site_url');
// id страницы
$id = $modx->resource->get('id');
// id главной страницы
$startId = $modx->getOption('site_start');

// url страницы
// 1 способ
// $url = $modx->makeUrl($id, '', '', 'full');
// 2 способ
if ($id == $startId) {
  $url = $siteUrl;
} else {
  $url = $siteUrl . $modx->resource->get('uri');
}

// заголовок страницы
$title = mb_strimwidth($modx->resource->get('pagetitle'), 0, 110, '...');
// описание страницы
$description = $modx->resource->get('description');
// все изображения, расположенные в контенте страницы
$images = [];
preg_match_all('/<img\s+.*?src=[\"\']?([^\"\' >]*)[\"\']?[^>]*>/i', $modx->resource->get('content'), $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
  $image = $match[1];
  if (mb_strpos($image, '/') === 0) {
    $image = $siteUrl . mb_substr($image, 1);
  } elseif (mb_strpos($image, $siteUrl) !== 0) {
    $image = $siteUrl . $image;
  }
  $images[] = $image;
}
// дата публикации статьи
$datePublished = date("c", strtotime($modx->resource->get('publishedon')));
// дата последнего изменения статьи
if ($modx->resource->get('editedon')) {
  $dateModified = date("c", strtotime($modx->resource->get('editedon')));
} else {
  $dateModified = $datePublished;
}
// автор статьи
$author = $modx->getObject('modUserProfile', $modx->resource->get('publishedby'))->get('fullname') ;
// имя сайта
$siteName = $modx->getOption('site_name');
// логотип сайта
$siteLogo = '/assets/images/logo.png';

// создадим ассоциативный массив из данных
$data = [
  '@context' => 'https://schema.org',
  '@type' => 'Article',
  'mainEntityOfPage' => [
    '@type' => 'WebPage',
    '@id' => $url
  ],
  'headline' => $title,
  'image' => $images,
  'datePublished' => $datePublished,
  'dateModified' => $dateModified,
  'author' => [
    '@type' => 'Person',
    'name' => $author
  ],
  'publisher' => [
    '@type' => 'Organization',
    'name' => $siteName,
    'logo' => [
      '@type' => 'ImageObject',
      'url' => $siteLogo
    ]
  ],
  'description' => $description
];

$output = $modx->getChunk('jsonld.tpl', array(
   'output' => json_encode($data, JSON_UNESCAPED_UNICODE)
));
return $output;

В этом снимаете необходимо вместо цифры 2 указать id шаблона, который у вас используется для вывода ресурсов со статьями.

2. Создать чанк с именем «jsonld.tpl» и следующим содержимым:

<script type="application/ld+json">[[+output]]</script>

3. Вставить вызов только что созданного сниппета в шаблон:

...  
<head>
  ...
  <!-- getJSONLD - это имя только что созданного сниппета -->
  [[getJSONLD]]
  ...

Вариант формирования JSON-LD для описания статьи и строки навигации

Ещё один пример сниппета для CMS MODX. В этом сниппете добавим структурированные данные не только для описания статьи, но и для строки навигации.

<?php

// если на этой странице контент не является объектом "Article", то завершаем работу (на сайте статьи имеют шаблон с id = 2)
if ($modx->resource->get('template') !== 2) {
  return;
}

// URL сайта
$siteUrl = $modx->getOption('site_url'); //$modx->getOption('http_host'); //$modx->getOption('site_url');
// id страницы
$id = $modx->resource->get('id');
// id главной страницы
$startId = $modx->getOption('site_start');

// url страницы
// 1 способ
// $url = $modx->makeUrl($id, '', '', 'full');
// 2 способ
if ($id == $startId) {
  $url = $siteUrl;
} else {
  $url = $siteUrl . $modx->resource->get('uri');
}

// заголовок страницы
$title = mb_strimwidth($modx->resource->get('pagetitle'), 0, 110, '...');
// описание страницы
$description = $modx->resource->get('description');
// все изображения, расположенные в контенте страницы
$images = [];
preg_match_all('/<img\s+.*?src=[\"\']?([^\"\' >]*)[\"\']?[^>]*>/i', $modx->resource->get('content'), $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
  $image = $match[1];
  if (mb_strpos($image, '/') === 0) {
    $image = $siteUrl . mb_substr($image, 1);
  } elseif (mb_strpos($image, $siteUrl) !== 0) {
    $image = $siteUrl . $image;
  }
  $images[] = $image;
}
// дата публикации статьи
$datePublished = date("c", strtotime($modx->resource->get('publishedon')));
// дата последнего изменения статьи
if ($modx->resource->get('editedon')) {
  $dateModified = date("c", strtotime($modx->resource->get('editedon')));
} else {
  $dateModified = $datePublished;
}
// автор статьи
$author = $modx->getObject('modUserProfile', $modx->resource->get('publishedby'))->get('fullname');
// имя сайта
$siteName = $modx->getOption('site_name');
// логотип сайта
$siteLogo = '/assets/images/logo.png';


// хлебные крошки
$breadcrumbs = [];
$crumbs = [];

// добавлем текущую страницу
$crumbs[] = ['name' => $title, 'item' => $url];
// получаем родительский ресурс
$parent = $modx->getObject('modResource', $modx->resource->get('parent'));
// пока родительский ресурс не равен null выполняем...
while ($parent != null) {
  $item = $parent->get('id') == $startId ? $siteUrl : $siteUrl . $parent->get('uri');
  $crumbs[] = ['name' => $parent->get('menutitle'), 'item' => $item];
  if ($parent->get('id') == $startId) {
    break;
  }
  $parent = $modx->getObject('modResource', $parent->get('parent'));
  if ($parent == null) {
    $parent = $modx->getObject('modResource', $startId);
  }
}
$index = 1;
for ($i = count($crumbs) - 1; $i >= 0; $i--) {
  $bredcrumbs[] = [
    '@type' => 'ListItem',
    'position' => $index++,
    'name' => $crumbs[$i]['name'],
    'item' => $crumbs[$i]['item']
  ];
}

// создадим ассоциативный массив из данных
$data = [
  [
    '@context' => 'https://schema.org',
    '@type' => 'Article',
    'mainEntityOfPage' => [
      '@type' => 'WebPage',
      '@id' => $url
    ],
    'headline' => $title,
    'image' => $images,
    'datePublished' => $datePublished,
    'dateModified' => $dateModified,
    'author' => [
      '@type' => 'Person',
      'name' => $author
    ],
    'publisher' => [
      '@type' => 'Organization',
      'name' => $siteName,
      'logo' => [
        '@type' => 'ImageObject',
        'url' => $siteLogo
      ]
    ],
    'description' => $description
  ], [
    '@context' => 'https://schema.org',
    '@type' => 'BreadcrumbList',
    'itemListElement' => $bredcrumbs
  ]
];

$output = $modx->getChunk('jsonld.tpl', array(
   'output' => json_encode($data, JSON_UNESCAPED_UNICODE)
));
return $output;