【WordPress】canonicalを自動生成する方法|SEOプラグイン無しでもOK!functions.phpで正規URLを出力する

WordPressのSEO対策で、意外と見落とされがちなのが canonical(カノニカル) の設定です。

canonicalはGoogleなどの検索エンジンに対して、

「このページの正規URLはこれです!」

と伝える重要なタグ。

正しく設定しておかないと…

  • URLの重複(同じ内容のページが複数URLで存在)
  • 検索順位が分散する
  • 正しいページがインデックスされない

といったSEO上のトラブルにつながることがあります。

今回は、SEOプラグインを使わずに WordPressでcanonicalタグを自動生成して出力する方法を、実際のコード付きで解説します。

canonical(カノニカル)とは?なぜ必要?

canonical(正規URL)とは、ページのHTMLの <head> 内に入れる下記のようなタグです。

<link rel="canonical" href="https://example.com/page/">

このタグがあることで、検索エンジンは

このページの本体(正規URL)はこれ
パラメータ違い・URL違いのページは同一扱いにする

という判断ができます。

canonicalが必要になる典型例

URLが複数ある状態(重複コンテンツ)

WordPressでは、同じ内容が違うURLで見れてしまうケースがよくあります。

  • https://example.com/news/
  • https://example.com/news/?utm_source=twitter
  • https://example.com/news/?ref=xxx

内容は同じでもURLが違うと、検索エンジンは別ページとして扱う可能性があります。

canonicalはSEOプラグインでも設定できるが…

AIOSEO、Yoast、RankMathなどのSEOプラグインを使えば canonical は自動出力されます。

ただ、こんなケースもあります。

  • プラグインを使っていないサイト
  • カスタムテーマで自力SEOをやっている
  • canonicalが二重出力されて崩れている

そんな時に役立つのが今回の方法です。

functions.phpでcanonicalを自動生成して出力する

以下のコードをテーマの functions.php に追加するだけで、ページ種別に応じた canonical を自動生成し、<head> に出力できます。

canonical自動生成コード(コピペOK)

<?php
/**
 * Canonicalを自動出力(プラグイン無し想定)
 * ※SEOプラグインを使っている場合は基本不要(むしろ二重になるので注意)
 */

// もし他でcanonicalが出てる/改変されてるなら一旦止める(必要な場合だけ)
remove_action('wp_head', 'rel_canonical');

// 自前でcanonicalを出す
add_action('wp_head', function () {
  if (is_feed() || is_robots() || is_trackback()) return;
  if (is_search()) return; // 検索結果ページは canonical を出さない派が多い(出すなら home_url('/?s=...') 等)

  $canonical = '';

  // singular(固定・投稿・カスタム投稿)
  if (is_singular()) {
    $canonical = get_permalink();
  }
  // カテゴリ/タグ/カスタムタクソノミー
  elseif (is_category() || is_tag() || is_tax()) {
    $canonical = get_term_link(get_queried_object());
  }
  // 投稿タイプアーカイブ
  elseif (is_post_type_archive()) {
    $canonical = get_post_type_archive_link(get_query_var('post_type'));
  }
  // 日付/著者アーカイブなど
  elseif (is_author() || is_date()) {
    $canonical = home_url(add_query_arg([], $GLOBALS['wp']->request));
    $canonical = trailingslashit($canonical);
  }
  // トップ/フロント
  elseif (is_front_page() || is_home()) {
    $canonical = home_url('/');
  }

  // ページネーションは canonical に /page/2/ を付ける(※好みで1ページ目固定もあり)
  if ($canonical && (is_paged() || get_query_var('paged'))) {
    $paged = max(1, (int) get_query_var('paged'));
    if ($paged > 1) {
      $canonical = trailingslashit($canonical) . user_trailingslashit("page/{$paged}", 'paged');
    }
  }

  if ($canonical && !is_wp_error($canonical)) {
    echo '<link rel="canonical" href="' . esc_url($canonical) . '">' . "\n";
  }
}, 1);

このコードの仕組みをわかりやすく解説

「なんとなくコピペしたけど…ちゃんと理解したい!」という方向けに、重要なポイントを噛み砕いて解説します。

① WordPress標準canonicalを止める

remove_action('wp_head', 'rel_canonical');

WordPressには、デフォルトでcanonicalを出す機能があります。

ただしテーマによって

  • canonicalが出ない
  • canonicalが変な形で出てる
  • プラグインが上書きしてる

などが起こりやすいので、「一旦止めて自作で統一する」という方針になっています。

※SEOプラグインを使ってる場合はここが危険(canonical二重出力)なので注意!

② 出力しないページを除外

if (is_feed() || is_robots() || is_trackback()) return;
if (is_search()) return;
  • RSS(feed)
  • robots.txt
  • trackback
  • 検索結果ページ

こういったページにcanonicalを出す必要はない/出すと逆効果なことがあるので除外しています。

③ 投稿・固定ページなどは get_permalink()

if (is_singular()) {
  $canonical = get_permalink();
}

投稿ページ/固定ページ/カスタム投稿タイプなどは
正規URL=パーマリンクなので get_permalink() でOKです。

④ カテゴリ/タグ/カスタムタクソノミー

elseif (is_category() || is_tag() || is_tax()) {
  $canonical = get_term_link(get_queried_object());
}

カテゴリやタグの一覧ページなどは get_term_link() を使います。

⑤ 投稿タイプアーカイブにも対応

elseif (is_post_type_archive()) {
  $canonical = get_post_type_archive_link(get_query_var('post_type'));
}

例えば items 投稿タイプの一覧ページ(アーカイブ)などもcanonicalを正しく出せます。

⑥ 著者・日付アーカイブ

elseif (is_author() || is_date()) {
  $canonical = home_url(add_query_arg([], $GLOBALS['wp']->request));
  $canonical = trailingslashit($canonical);
}

著者ページや日付アーカイブは URL生成が特殊なことがあるので、requestベースで作っています。

⑦ トップページにも対応

elseif (is_front_page() || is_home()) {
  $canonical = home_url('/');
}

トップページは canonical を / に統一。これが正解です。

ページネーションのcanonical対応も抜かりなし!

一覧ページでよくあるのが

  • 1ページ目:/news/
  • 2ページ目:/news/page/2/

この時、canonicalを全部 /news/ にすると逆にSEO評価が崩れることがあります。

このコードはページネーションがある場合、

page/2 を canonical に反映
page/3 も同様に反映

できるようになっています。

if ($canonical && (is_paged() || get_query_var('paged'))) {
  $paged = max(1, (int) get_query_var('paged'));
  if ($paged > 1) {
    $canonical = trailingslashit($canonical) . user_trailingslashit("page/{$paged}", 'paged');
  }
}

SEOプラグイン導入済みの場合は要注意(canonical二重問題)

ここ本当に大事です。

AIOSEO/Yoast/RankMath を入れている場合

→ ほぼ100% canonical が自動出力されています。

functions.php側でも canonical を出すと…

  • canonicalが二重に出る
  • 検索エンジンが混乱する
  • SEO的に逆効果

という事故になりやすいです。

プラグインを使うなら、今回のコードは基本不要!

canonicalが正しく出ているか確認する方法

最後に確認手順です。

  1. canonicalを確認したいページを開く
  2. 右クリック →「ページのソースを表示」
  3. canonical で検索

正しく出ていれば:

<link rel="canonical" href="https://example.com/page/">

<head> 内に表示されています。

まとめ|canonicalは「サイトのSEOを守る保険」

canonicalをちゃんと設定しておくと

重複コンテンツを防ぐ
インデックスが整理される
SEO評価が分散しにくい

というメリットがあります。

SEOプラグインを使っていない方や、テーマを完全自作している方には、今回のコードはかなり実用的です。