📖 11 分で読めます

Astro サイトの SEO:2026 年完全ガイド

Astro サイトを上位表示させるために必要なすべて:メタデータ、サイトマップ、構造化データ、i18n、そして Core Web Vitals。

  • Astro
  • Technical SEO

オーガニック検索を重視するなら、Astro は選べる最良のフレームワークのひとつです。そしてそれは偶然ではありません。HTML を配信する、デフォルトで JavaScript をゼロにする、ビルド時にレンダリングする——という設計思想全体が、検索エンジンが実際に評価するものとほぼ完璧に一致しているのです。あなたが今読んでいるこのサイトも Astro で作られているので、以下に書かれていることはすべて理論ではなく実戦で検証済みです。

このガイドでは、Astro プロジェクトの SEO の全領域を順に解説します。メタデータと canonical、サイトマップと robots、JSON-LD による構造化データ、多言語ルーティング、Core Web Vitals、そして気づかぬうちに順位を奪っていく落とし穴まで。各セクションには、自分のプロジェクトにそのまま貼り付けられる実際のコードを添えています。

Astro が SEO に強い理由

最近のサイトにおける SEO の問題の大半は、ひとつの根本原因にたどり着きます。クローラーがダウンロードするページと、ユーザーが目にするページが違うのです。React や Next のクライアントレンダリングされたルートは、空の <div id="root"></div> を配信し、本当のコンテンツは後からハイドレートします。Google は JavaScript を レンダリングできます が、それは限られた予算のもとで遅れてやってくる二度目の波で行われます。そのパイプラインの内側で実際に何が起きているかは、JavaScript SEO とレンダリング の詳細解説を参照してください。

Astro はこの問題全体を回避します。

観点典型的な SPAAstro(デフォルト)
初期 HTML空のシェル完全にレンダリングされたコンテンツ
配信される JavaScriptアプリ全体のバンドルゼロ(明示的に有効化しない限り)
クロール時に見えるコンテンツレンダリングの波の後最初のリクエストで
Time to first byteサーバーでの計算CDN からの静的ファイル

Astro の Islands アーキテクチャ では、インタラクティブ性はコンポーネント単位でオプトインします。JavaScript が必要な検索ボックスやカルーセルだけをハイドレートし、それ以外はすべてプレーンでクロール可能な HTML のままです。デフォルトの出力は静的(SSG)で、セマンティックで、即座にインデックスできます。

🧑‍💻 開発者視点:Astro における最大の SEO 上のメリットは「何も決めなくていい」ことです。何もしなくても、クライアントバンドルのないサーバーレンダリング済み HTML が手に入ります。他のフレームワークでは、それを得るために戦わなければなりません。

メタデータと canonical

タイトルタグ、メタディスクリプション、canonical URL、Open Graph タグは最低限の必須項目です。多くのチームが犯す間違いは、これらをページごとにばらまいて同期が崩れてしまうことです。解決策は、props を受け取ってどこでも一貫した <head> マークアップを出力する単一のレイアウトを用意することです。

src/layouts/BaseLayout.astro を作成します。

---
interface Props {
  title: string;
  description: string;
  image?: string;
}

const { title, description, image = "/og-default.png" } = Astro.props;

// Build an absolute canonical from the current URL + your site origin.
const canonical = new URL(Astro.url.pathname, Astro.site).href;
const ogImage = new URL(image, Astro.site).href;
---

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>{title}</title>
    <meta name="description" content={description} />
    <link rel="canonical" href={canonical} />

    <!-- Open Graph -->
    <meta property="og:type" content="website" />
    <meta property="og:title" content={title} />
    <meta property="og:description" content={description} />
    <meta property="og:url" content={canonical} />
    <meta property="og:image" content={ogImage} />

    <!-- Twitter -->
    <meta name="twitter:card" content="summary_large_image" />
  </head>
  <body>
    <slot />
  </body>
</html>

Astro.site を解決させるには、astro.config.mjs で設定します。

export default defineConfig({
  site: "https://example.com",
});

これで各ページはデータを渡すだけで済みます。

---
import BaseLayout from "../layouts/BaseLayout.astro";
---
<BaseLayout
  title="SEO for Astro Sites: The Complete 2026 Guide"
  description="Make your Astro site rank with metadata, sitemaps, and more."
>
  <h1>...</h1>
</BaseLayout>

💡 ヒント:自己参照型の canonical(ページが自身のクリーンな URL を指すこと)は、クエリ文字列・トラッキングパラメータ・末尾スラッシュの差異から生じる重複コンテンツ問題に対する、最も効果的な防御策です。

サイトマップと robots

サイトマップは、どの URL が存在し、いつ更新されたかを検索エンジンに伝えます。Astro には公式の統合があります。インストールして登録しましょう。

npx astro add sitemap

このコマンドは設定を次のように編集します。

import sitemap from "@astrojs/sitemap";

export default defineConfig({
  site: "https://example.com",
  integrations: [sitemap()],
});

astro build を実行すると、dist/sitemap-index.xml とページ分割された子サイトマップが生成されます。この統合は site が設定されている場合にのみ機能します。そのオリジンがすべての URL の接頭辞になるからです。

robots.txt については、静的ファイルを使わず、サイトマップ URL が設定と同期し続けるように動的なエンドポイントを使いましょう。src/pages/robots.txt.ts を作成します。

import type { APIRoute } from "astro";

const robots = (sitemapURL: URL) => `
User-agent: *
Allow: /

Sitemap: ${sitemapURL.href}
`.trim();

export const GET: APIRoute = ({ site }) => {
  const sitemapURL = new URL("sitemap-index.xml", site);
  return new Response(robots(sitemapURL), {
    headers: { "Content-Type": "text/plain" },
  });
};

⚠️ 注意:robots.txt の Disallow がブロックするのは クロール であって インデックス ではありません。外部リンクのある Disallow 指定の URL は、リンクだけの形で検索結果に表示されることがあります。ページをインデックスから除外したい場合は、クロールを許可したうえで <meta name="robots" content="noindex"> を追加してください。

構造化データ(JSON-LD)

構造化データは、リッチリザルト——記事の署名、パンくずリスト、FAQ アコーディオン、星評価——を獲得するための手段です。Google はそれをスクリプトタグ内の JSON-LD として読み取ります。Astro でのきれいなパターンは、frontmatter でオブジェクトを組み立て、レイアウトでシリアライズすることです。

BaseLayout.astro で、オプションの schema プロパティを受け取り、クォートがエスケープされないように set:html で出力します。

---
interface Props {
  title: string;
  description: string;
  schema?: Record<string, unknown>;
}
const { title, description, schema } = Astro.props;
---
<head>
  <!-- ...other tags... -->
  {schema && (
    <script
      type="application/ld+json"
      set:html={JSON.stringify(schema)}
    />
  )}
</head>

ブログ記事のページなら、Article オブジェクトを渡します。

---
const schema = {
  "@context": "https://schema.org",
  "@type": "Article",
  headline: "SEO for Astro Sites: The Complete 2026 Guide",
  datePublished: "2026-06-21",
  author: { "@type": "Person", name: "Your Name" },
};
---
<BaseLayout title="..." description="..." schema={schema}>

💡 ヒント:schema オブジェクトを手書きするのはミスを招きやすい作業です。私たちの Schema ジェネレーター は一般的なタイプの有効な JSON-LD を生成するので、そのまま props に貼り付けられます。出力は必ず Google の Rich Results Test で再確認してください。

多言語対応(i18n)

複数の言語を提供する場合、ルールはシンプルかつ容赦ありません。あるページのすべての言語バージョンは、自己参照を含めて、他のすべてのバージョンを hreflang で宣言しなければなりません。これを誤ると、Google は間違った言語を表示するか、各バリアントを重複として扱います。

astro.config.mjs でルーティングを設定します。

export default defineConfig({
  site: "https://example.com",
  i18n: {
    defaultLocale: "en",
    locales: ["en", "fr", "ja"],
    routing: { prefixDefaultLocale: true },
  },
});

prefixDefaultLocale: true を指定すると、コンテンツは /en//fr//ja/ の下に置かれます。言語パスと競合する曖昧なルートは存在しません。次に、<head>hreflang のクラスタを出力します。

---
const locales = ["en", "fr", "ja"];
// Strip the current locale prefix to get the shared path segment.
const path = Astro.url.pathname.replace(/^\/[a-z]{2}/, "");
---
{locales.map((loc) => (
  <link
    rel="alternate"
    hreflang={loc}
    href={new URL(`/${loc}${path}`, Astro.site).href}
  />
))}
<link
  rel="alternate"
  hreflang="x-default"
  href={new URL(`/en${path}`, Astro.site).href}
/>

x-default エントリは、ユーザーにどの言語も一致しないときに表示すべきバージョンを Google に伝えます。翻訳は並行したファイル(content/blog/en/post.mdxcontent/blog/fr/post.mdx)として保ち、上記のパス計算が単純なままになるようにしましょう。

Core Web Vitals

Astro の静的出力は最初から優位を与えてくれます。ハイドレーションのコストがなく、レイアウトをずらすクライアントフレームワークもなく、HTML は CDN から直接配信されます。これだけで Largest Contentful Paint(LCP)と Interaction to Next Paint(INP)の大半が無料でカバーされます。それでも悩みの種として残るのが、画像とフォントの 2 つです。

Astro 組み込みの <Image /> コンポーネントを使いましょう。モダンなフォーマットを生成し、リサイズし、寸法を強制してくれます。

---
import { Image } from "astro:assets";
import hero from "../assets/hero.png";
---
<Image
  src={hero}
  alt="Descriptive alt text"
  width={1200}
  height={630}
  format="webp"
  loading="eager"
/>

グリーンゾーンに入るための短いチェックリストです。

  • すべての画像に明示的な width/height を設定し、レイアウトシフト(CLS)を防ぐ。
  • LCP となる画像には loading="eager" を、ファーストビュー外のものには lazy を使う。
  • フォントをセルフホストし、font-display: swap を追加して、フォント読み込み前にテキストを表示させる。
  • 最も重要なフォントファイル 1 つだけをプリロードする。すべてをプリロードしてはいけない。
  • ファーストペイントで表示されるコンテンツには、client:* ディレクティブを一切付けない。
指標測定するものAstro のデフォルトの挙動
LCP最大要素の描画時間良好——静的 HTML を CDN 配信
CLS視覚的な安定性画像に寸法があれば良好
INP入力応答性優秀——デフォルトでハイドレーションなし

よくある落とし穴

これらは、ローカルテストは通るのに、それでも順位を急落させる間違いです。

  • client:only のコンテンツはクローラーから見えない。 client:only コンポーネントはサーバー側で 何も レンダリングしません。フォールバックの HTML が存在しないのです。重要なコンテンツがその中にあると、インデックスされません。client:load(こちらはサーバーレンダリングも行う)を使うか、もっと良いのはプレーンな .astro にコンテンツを置くことです。
  • 末尾スラッシュの不整合。 Astro の trailingSlash オプション("always""never""ignore")は、ホストがファイルをどう配信するか、そして内部リンクが何を使うかと一致していなければなりません。不一致は /page/page/ を 2 つの URL として生み出し、リンク評価を分散させます。1 つを選び、設定に書き、すべての内部リンクを揃えましょう。
  • site 設定の欠落。 site が未設定だと、canonical とサイトマップは静かに壊れるか、相対 URL を生成します。これは空または無効なサイトマップの最も一般的な原因です。
  • 薄いページに noindex を付け忘れる。 タグアーカイブやページネーションのページは、価値を加えないことがよくあります。クロール予算を薄めさせるのではなく、それらに noindex メタタグを追加しましょう。
  • 正規化をリダイレクトに頼る。 canonical タグはヒントであり、301 は指示です。真の重複(HTTP 対 HTTPS、www 対非 www)については、ホストや CDN のレベルでリダイレクトを強制してください。canonical タグだけに頼ってはいけません。

⚠️ 注意:開発サーバーではなく、必ず実際の成果物で検証してください。astro build を実行して dist/ を調べ、生成された HTML を開いて、コンテンツ・メタタグ・JSON-LD が本当に静的出力に含まれているか確認しましょう。astro dev はレンダリングの差異を覆い隠すことがあります。

まとめ

Astro は、ほとんどのフレームワークが手作業で組み立てさせる土台を最初から渡してくれます。サーバーレンダリングされた HTML、デフォルトでゼロの JavaScript、そしてクローラーと Core Web Vitals の両方が好む高速な静的出力です。あなたの仕事は、その上に意図的なシグナルを重ねることです。一貫したメタデータと canonical を注入する単一のレイアウト、サイトマップと動的な robots エンドポイント、リッチリザルトのための JSON-LD、すべての言語に対する正しい hreflang クラスタ、そして規律ある画像とフォントの扱い。

これらをきちんとやれば、検索エンジンがあなたを下位に置く技術的な理由は、ほぼすべて取り除いたことになります。

次のステップ: