Перейти к содержимому

25. SEO и мета-теги

Правильно настроенные мета-теги — это разница между страницей, которую находят в поиске и расшаривают в соцсетях, и страницей, которая существует только для её автора. Astro даёт полный контроль над <head> без лишних абстракций.

В отличие от фреймворков вроде Next.js, Astro не требует специального компонента для работы с <head>. Вы просто пишете разметку напрямую:

src/layouts/Base.astro
---
const { title, description } = Astro.props;
---
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{title}</title>
<meta name="description" content={description} />
</head>
<body>
<slot />
</body>
</html>
<head>
<!-- Базовые -->
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Заголовок страницы | Сайт</title>
<meta name="description" content="Описание страницы до 160 символов" />
<meta name="keywords" content="astro, web, javascript" />
<meta name="author" content="Алексей Петров" />
<meta name="robots" content="index, follow" />
<!-- Канонический URL — важен при дублировании контента -->
<link rel="canonical" href="https://mysite.com/about/" />
</head>

Open Graph (OG) теги определяют, как страница выглядит при публикации в VK, Telegram, Facebook и других платформах:

<meta property="og:type" content="article" />
<meta property="og:site_name" content="Мой Astro блог" />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={new URL(image, Astro.site)} />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:url" content={Astro.url} />
<meta property="og:locale" content="ru_RU" />

Оптимальный размер OG-изображения: 1200×630 пикселей. Если изображение меньше 200×200 — оно не будет показано.

Twitter имеет собственный формат мета-тегов (работает также для X):

<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@myhandle" />
<meta name="twitter:creator" content="@authorhandle" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={new URL(image, Astro.site)} />

Типы карточек: summary, summary_large_image, app, player. Для большинства статей используйте summary_large_image.

Структурированные данные помогают поисковикам понять содержимое страницы и показывать расширенные сниппеты в результатах поиска:

---
const jsonLd = {
"@context": "https://schema.org",
"@type": "Article",
"headline": post.data.title,
"description": post.data.description,
"author": {
"@type": "Person",
"name": post.data.author,
},
"datePublished": post.data.publishedAt.toISOString(),
"image": new URL(post.data.image, Astro.site).toString(),
};
---
<script type="application/ld+json" set:html={JSON.stringify(jsonLd)} />
src/components/SEO.astro
---
interface Props {
title: string;
description: string;
image?: string;
type?: 'website' | 'article';
noindex?: boolean;
}
const {
title,
description,
image = '/og-default.jpg',
type = 'website',
noindex = false,
} = Astro.props;
const canonical = Astro.url.href;
const ogImage = new URL(image, Astro.site);
const fullTitle = \`\${title} | Мой Сайт\`;
---
<title>{fullTitle}</title>
<meta name="description" content={description} />
<link rel="canonical" href={canonical} />
{noindex && <meta name="robots" content="noindex, nofollow" />}
<meta property="og:type" content={type} />
<meta property="og:title" content={fullTitle} />
<meta property="og:description" content={description} />
<meta property="og:image" content={ogImage} />
<meta property="og:url" content={canonical} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={fullTitle} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={ogImage} />