Пошук уроків, статей та іншого контенту
Додасте JSON-LD до сторінок і опишете структуровані дані для розширених результатів пошуку.
Структуровані дані — це машиночитаний опис вмісту сторінки. Пошукові системи використовують його, щоб краще зрозуміти:
тип сторінки;
назву матеріалу;
автора;
дату публікації;
зображення;
оцінку товару;
ціну та наявність;
інші властивості контенту.
Найпоширеніший формат структурованих даних — JSON-LD. Він міститься у спеціальному елементі:
<script type="application/ld+json">
...
</script>JSON-LD не змінює видимий вміст сторінки. Він додає пошуковим системам додатковий контекст.
Структуровані дані можуть зробити сторінку придатною для розширених результатів пошуку, але не гарантують їх показ. Остаточне рішення приймає пошукова система.
JSON-LD зазвичай описує сутності зі словника Schema.org. Наприклад:
Article — стаття;
Product — товар;
Recipe — рецепт;
Event — подія;
Organization — організація;
BreadcrumbList — навігаційний ланцюжок.
Кожен об’єкт JSON-LD має містити:
@context — словник, зазвичай "https://schema.org";
@type — тип сутності;
властивості, що відповідають цьому типу.
Приклад опису статті:
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Вивчаємо Next.js",
"author": {
"@type": "Person",
"name": "Олена Коваль"
}
}Назви властивостей і їхні типи мають відповідати Schema.org. Не варто вигадувати власні назви на кшталт articleTitle або publishedBy, якщо для цього вже існують headline і author.
У Next.js з App Router JSON-LD можна додати безпосередньо до серверного компонента сторінки. Для цього використовується звичайний HTML-елемент script.
Розглянемо сторінку статті app/articles/[slug]/page.tsx.
type ArticlePageProps = {
params: Promise<{
slug: string;
}>;
};
export default async function ArticlePage({
params,
}: ArticlePageProps) {
const { slug } = await params;
// У реальному застосунку дані можна отримати з CMS або бази даних
const article = {
slug,
title: "Як працює маршрутизація в Next.js",
description:
"Розбираємо файлову маршрутизацію та динамічні сегменти в Next.js.",
content:
"Next.js використовує структуру папок для опису маршрутів застосунку.",
author: "Олена Коваль",
publishedAt: "2026-08-10",
updatedAt: "2026-08-12",
image: "https://example.com/images/nextjs-routing.jpg",
};
const url = `https://example.com/articles/${article.slug}`;
const jsonLd = {
"@context": "https://schema.org",
"@type": "Article",
mainEntityOfPage: {
"@type": "WebPage",
"@id": url,
},
headline: article.title,
description: article.description,
image: [article.image],
datePublished: article.publishedAt,
dateModified: article.updatedAt,
author: {
"@type": "Person",
name: article.author,
},
publisher: {
"@type": "Organization",
name: "Fullstack Academy",
logo: {
"@type": "ImageObject",
url: "https://example.com/logo.png",
},
},
};
return (
<article>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
// Екрануємо символ "<", щоб значення не могло закрити script
__html: JSON.stringify(jsonLd).replace(/</g, "\\u003c"),
}}
/>
<h1>{article.title}</h1>
<p>{article.description}</p>
<p>Автор: {article.author}</p>
<p>Опубліковано: {article.publishedAt}</p>
<div>{article.content}</div>
</article>
);
}У результаті HTML сторінки міститиме JSON-LD приблизно такого вигляду:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Як працює маршрутизація в Next.js"
}
</script>dangerouslySetInnerHTMLReact зазвичай екранує текст, який вставляється в JSX. Для JSON-LD потрібно вставити JSON як вміст елемента script, тому в Next.js використовується dangerouslySetInnerHTML.
Це не означає, що всі дані потрібно вставляти без перевірки. JSON має бути серіалізований через JSON.stringify, а символ < потрібно замінити на \u003c. Інакше значення з недовіреними даними теоретично може містити послідовність, схожу на закривальний тег </script>.
Безпечний шаблон:
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(data).replace(/</g, "\\u003c"),
}}
/>Для сторінки товару використовується тип Product. У ньому можна описати назву, зображення, бренд, пропозицію та оцінки.
export default function ProductPage() {
const product = {
name: "Механічна клавіатура",
description: "Механічна клавіатура з перемикачами Brown.",
image: "https://example.com/images/keyboard.jpg",
sku: "KB-001",
price: "2499.00",
currency: "UAH",
availability: "https://schema.org/InStock",
};
const jsonLd = {
"@context": "https://schema.org",
"@type": "Product",
name: product.name,
description: product.description,
image: [product.image],
sku: product.sku,
offers: {
"@type": "Offer",
priceCurrency: product.currency,
price: product.price,
availability: product.availability,
url: "https://example.com/products/mechanical-keyboard",
},
};
return (
<main>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
// Не дозволяємо даним сформувати новий HTML-тег
__html: JSON.stringify(jsonLd).replace(/</g, "\\u003c"),
}}
/>
<h1>{product.name}</h1>
<p>{product.description}</p>
<p>
Ціна: {product.price} {product.currency}
</p>
</main>
);
}Значення price краще передавати як рядок із десятковим числом. availability має містити повну URL-адресу відповідного значення Schema.org, а не просто "InStock".
У динамічній сторінці JSON-LD потрібно будувати з тих самих даних, які відображаються користувачу.
Наприклад, якщо заголовок на сторінці змінився, але headline у JSON-LD залишився старим, дані стали суперечливими. Пошукова система може проігнорувати таку розмітку.
Для кожної сторінки перевіряйте, що:
headline відповідає видимому заголовку;
description описує реальний вміст;
image доступне за абсолютною URL-адресою;
datePublished є реальною датою публікації;
dateModified не є випадковою датою;
ціна та наявність відповідають поточним даним;
автор і видавець справді пов’язані зі сторінкою.
На одній сторінці може бути кілька структурованих сутностей. Наприклад, стаття може одночасно мати навігаційний ланцюжок.
Для цього можна додати кілька script:
const articleJsonLd = {
"@context": "https://schema.org",
"@type": "Article",
headline: "Вивчаємо Next.js",
};
const breadcrumbJsonLd = {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
itemListElement: [
{
"@type": "ListItem",
position: 1,
name: "Головна",
item: "https://example.com",
},
{
"@type": "ListItem",
position: 2,
name: "Статті",
item: "https://example.com/articles",
},
{
"@type": "ListItem",
position: 3,
name: "Вивчаємо Next.js",
item: "https://example.com/articles/learn-nextjs",
},
],
};
export default function Page() {
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
// Екрануємо небезпечний символ у JSON
__html: JSON.stringify(articleJsonLd).replace(/</g, "\\u003c"),
}}
/>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
// Екрануємо небезпечний символ у JSON
__html: JSON.stringify(breadcrumbJsonLd).replace(
/</g,
"\\u003c",
),
}}
/>
<h1>Вивчаємо Next.js</h1>
</>
);
}Кілька блоків корисні, коли сторінка описує різні пов’язані сутності. Водночас кожен блок повинен бути коректним і відповідати вмісту сторінки.
Після додавання структурованих даних перевірте:
Чи є результат валідним JSON.
Чи присутні @context і @type.
Чи відповідають властивості вибраному типу Schema.org.
Чи збігаються дані JSON-LD з видимим вмістом сторінки.
Чи використовуються абсолютні URL-адреси для зображень і сторінок.
Чи немає в HTML помилково екранованого або обрізаного script.
Для перевірки можна використовувати інструменти тестування структурованих даних пошукових систем або переглянути згенерований HTML сторінки в браузері.
Не слід описувати статтю як Product, якщо сторінка не є сторінкою товару. Тип має відповідати сутності, яку бачить користувач.
Не додавайте в JSON-LD оцінку, ціну або дату, яких немає на сторінці або які не відповідають її поточному стану.
Пошуковим системам надійніше передавати абсолютні адреси:
{
"image": "https://example.com/images/article.jpg"
}Замість:
{
"image": "/images/article.jpg"
}Такий підхід небезпечний:
const json = `{
"@type": "Article",
"headline": "${title}"
}`;Якщо title містить лапки або спеціальні символи, JSON може стати некоректним. Використовуйте об’єкт JavaScript і JSON.stringify.
Не вставляйте довільний JSON у script без підготовки:
dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}Використовуйте екранування символу <:
dangerouslySetInnerHTML={{
__html: JSON.stringify(data).replace(/</g, "\\u003c"),
}}Валідна розмітка лише робить сторінку придатною для певного формату розширеного результату. Вона не гарантує, що пошукова система його покаже.
JSON-LD — це формат структурованих даних для опису вмісту сторінки.
У Next.js JSON-LD можна додавати через script з типом application/ld+json.
Дані потрібно будувати з реального вмісту сторінки.
Для серіалізації використовуйте JSON.stringify.
Перед вставкою JSON у script екрануйте символ <.
@type і властивості мають відповідати словнику Schema.org.
Структуровані дані можуть допомогти отримати розширені результати пошуку, але не гарантують їх появу.