WordPress: JSON-LD BlogPosting — класс для Custom Post Type
Генератор JSON-LD разметки типа BlogPosting для CPT через wp_head. Защита от дублей через did_action, сериализация через wp_json_encode. По официальной документации WordPress и schema.org/BlogPosting.
Как использовать
- Создайте файл includes/class-jsonld-cpt.php в теме или плагине.
- Замените массив target_post_types на ваши CPT (articles, news и т.д.).
- В functions.php добавьте: require_once get_stylesheet_directory() . '/includes/class-jsonld-cpt.php';
Генерация JSON-LD разметки BlogPosting для страниц Custom Post Type. Hook wp_head выводит разметку в <head>. Сериализация через wp_json_encode() предотвращает поломку JSON из-за кавычек в заголовке. did_action() защищает от дублей при использовании с SEO-плагинами.
Класс и подключение
Файл includes/class-jsonld-cpt.php:
<?php
/**
* JSON-LD Generator for Custom Post Types
* Place in: wp-content/themes/your-theme/includes/class-jsonld-cpt.php
* Or: wp-content/plugins/your-plugin/includes/class-jsonld-cpt.php
*/
class JSONLD_CPT_Generator {
private $target_post_types = ['articles', 'news', 'publications'];
public function __construct() {
add_action('wp_head', [$this, 'output_jsonld'], 10);
}
public function output_jsonld() {
if (!is_singular($this->target_post_types)) {
return;
}
global $post;
if (!$post) {
return;
}
if (did_action('jsonld_cpt_output')) {
return;
}
$jsonld = $this->build_blogposting_schema($post);
if ($jsonld) {
echo "\n" . '<script type="application/ld+json">' . "\n";
echo wp_json_encode($jsonld, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
echo "\n" . '</script>' . "\n";
do_action('jsonld_cpt_output');
}
}
private function build_blogposting_schema($post) {
$author_id = $post->post_author;
$author_name = get_the_author_meta('display_name', $author_id);
$author_url = get_author_posts_url($author_id);
$publish_date = get_the_date('c', $post);
$modified_date = get_the_modified_date('c', $post);
$image_id = get_post_thumbnail_id($post->ID);
$image_url = $image_id
? wp_get_attachment_image_url($image_id, 'full')
: get_stylesheet_directory_uri() . '/assets/images/og-default.png';
$categories = get_the_terms($post->ID, 'category');
$section = $categories && !is_wp_error($categories)
? $categories[0]->name
: 'General';
$schema = [
'@context' => 'https://schema.org',
'@type' => 'BlogPosting',
'mainEntityOfPage' => [
'@type' => 'WebPage',
'@id' => get_permalink($post->ID)
],
'headline' => get_the_title($post->ID),
'description' => get_the_excerpt($post->ID),
'image' => [
'@type' => 'ImageObject',
'url' => $image_url,
'width' => 1200,
'height' => 630
],
'datePublished' => $publish_date,
'dateModified' => $modified_date,
'author' => [
'@type' => 'Person',
'name' => $author_name,
'url' => $author_url
],
'publisher' => [
'@type' => 'Organization',
'name' => get_bloginfo('name'),
'logo' => [
'@type' => 'ImageObject',
'url' => get_stylesheet_directory_uri() . '/assets/images/logo.png',
'width' => 600,
'height' => 60
]
],
'articleSection' => $section,
'wordCount' => str_word_count($post->post_content)
];
$tags = get_the_terms($post->ID, 'post_tag');
if ($tags && !is_wp_error($tags)) {
$keywords = wp_list_pluck($tags, 'name');
$schema['keywords'] = implode(', ', $keywords);
}
return $schema;
}
}
new JSONLD_CPT_Generator();
В functions.php темы:
<?php
// wp-content/themes/your-theme/functions.php
require_once get_stylesheet_directory() . '/includes/class-jsonld-cpt.php';
Замечания
target_post_types— укажите slug вашего CPT. Для таксономий, привязанных к стандартномуpost, категории и теги подтянутся; для CPT с кастомными таксономиями при необходимости доработайтеget_the_terms().- Проверка разметки: Google Rich Results Test (официальный инструмент Google Search).
Подробнее: WordPress: JSON-LD для CPT — дубли и ошибки.