固定ページでカテゴリーページを作成する方法を紹介します。
コピペ利用可能なソースコードを詳しい解説付きでお送りします。SEOの観点から問題となるコンテンツの重複についても、具体的な対策を紹介しています。
解決したいこと: 「固定ページでカテゴリーページを作成する」とは
この記事ではどんな問題を解決できるか?
通常、WordPress のカテゴリーページは、投稿や固定ページのような「個別ページ」とは異なり、管理画面で記事を作成することはできません。あらかじめ、テンプレートを作成しておき、表示する記事はいつもアクセスのたびに決定されます。
例えば、ある日、/category/javascript にアクセスがあり、1ページ目に記事ID 5〜1 が表示されたとしても、1週間後再びアクセスがあったときは、10〜6 というように表示が変わってしまうかもしれません。
この動作を「いつも特定の記事のみ表示する」というように変更したいのなら、テーマの中に category-
$slug
.php
(上記の例の場合、category-javascript.php
)を作成します。
この記事で紹介するのは、この工程を固定ページで行う方法です。
実現される動作
前置きを引っ張って申し訳ないのですが、紹介する方法を試すとどういう動作に変わるのかを説明します。
固定ページをカテゴリーページにするのはカテゴリーごとに設定します。設定方法は、カテゴリーのスラッグと同じスラッグで公開状態の固定ページを作成することです。前の例だと、javascript
というスラッグの固定ページを公開します。そうしなかったカテゴリーは通常のテンプレート階層のとおりにテンプレートが適用されます。
- 固定ページを作成・公開した場合: 固定ページが表示される(ただし、
category-
$slug
.php
またはcategory-
$id
.php
があった場合は表示されない) - そうしなかった場合: 通常のカテゴリーと同じ動作
もし、固定ページにカスタムテンプレートが設定されていれば、それを適用するようにします。
また、固定ページ自体にアクセスがあった場合は、通常どおり固定ページを表示します。そのため、SEOの観点から、重複コンテンツが生まれてしまうという問題が発生します。その対策についても記事の後半で解説します。
ソースコード
お待たせしました。実際のコードの紹介です。すべてのカテゴリーページのアクセスをキャッチするため、category.php
に記述を行います。
- <?php
- /**
- * カテゴリースラッグと同じスラッグの固定ページが存在すれば固定ページを表示し、
- * なければアーカイブページを表示する。
- *
- * 1. 公開状態の固定ページあり:
- *
- * 1-1. カスタムテンプレート
- * 1-2. page-$slug.php
- * 1-3. page-$id.php
- * 1-4. page.php
- * 1-5. singular.php
- * 1-6. index.php
- *
- * 2. 公開状態の固定ページなし:
- *
- * 2-1. archive.php
- * 2-2. paged.php (2ページ目以降)
- * 2-3. index.php
- */
- $category_slug = get_query_var('category_name');
- $page = get_page_by_path($category_slug);
-
- if (isset($page) && $page->post_status === 'publish') { # 1. 公開状態の固定ページあり
-
- # メインループの書き換え
- $GLOBALS['wp_the_query']->posts = [$page];
- $GLOBALS['wp_the_query']->post_count = 1;
-
- # カスタムテンプレートのパス
- $template_path = get_post_meta($page->ID, '_wp_page_template')[0];
-
- if ($template_path) {
- if ($template_path !== 'default') {
- # 1-1. $custom.php
- locate_template([$template_path], true);
- }
- } else {
- locate_template([
- "page-{$page->post_name}.php", # 1-2. page-$slug.php
- "page-{$page->ID}.php", # 1-3. page-$id.php
- "page.php", # 1-4. page.php
- 'singular.php', # 1-5. singular.php
- 'index.php', # 1-6. index.php
- ], true);
- }
-
- } else { # 2. 公開状態の固定ページなし
-
- locate_template([
- 'archive.php', # 2-1. archive.php
- (get_query_var('paged', 1) >= 2
- ? 'paged.php' # 2-2. paged.php (2ページ目以降)
- : null),
- 'index.php', # 2-3. index.php
- ], true);
- }
ソースコードの解説
ここからはコードの解説をしていきます。
1. 公開状態の固定ページあり
一番外側の if
文で固定ページの有無を調べて、その結果に応じて擬似的にテンプレート階層を作成しています。既に category.php
が適用されているので、擬似的に階層を再現する必要があります。
- if (isset($page) && $page->post_status === 'publish') { # 公開状態の固定ページあり
メインループの書き換え:
固定ページを適用する場合は、メインループを書き換えます。理由は簡単で、該当の固定ページのみを表示するためです。書き換えを行わなかった場合は、通常のカテゴリー検索結果が表示されてしまいます。
- # メインループの書き換え
- $GLOBALS['wp_the_query']->posts = [$page];
- $GLOBALS['wp_the_query']->post_count = 1;
設定されているカスタムテンプレートの取得:
固定ページはカスタムテンプレートが最優先で適用されます。固定ページに設定されているカスタムテンプレートは、カスタムフィールドで管理されており、フィールド名は「_wp_page_template
」です。
- # カスタムテンプレートのパス
- $template_path = get_post_meta($page->ID, '_wp_page_template')[0];
1-1. カスタムテンプレートの適用
カスタムテンプレートが設定されていた場合はそれを適用します。ここで使用している locate_template()
関数は、第一引数に適用するテンプレートパスを優先順に並べたもので、第二引数を true
にするとテンプレートを読み込みます。
- if ($template_path) {
- if ($template_path !== 'default') {
- # 1-1. $custom.php
- locate_template([$template_path], true);
- }
1-2 ~ 1-6. 各種テンプレートの適用
- } else {
- locate_template([
- "page-{$page->post_name}.php", # 1-2. page-$slug.php
- "page-{$page->ID}.php", # 1-3. page-$id.php
- "page.php", # 1-4. page.php
- 'singular.php', # 1-5. singular.php
- 'index.php', # 1-6. index.php
- ], true);
- }
2. 公開状態の固定ページなし
公開の固定ページがない場合は通常のカテゴリーと同様です。しかし、このテンプレートが category.php であり、より優先度の高い category-
$slug
.php
と category-
$id
.php
は既にスキップされているのでここでは含めません。
- } else { # 2. 公開状態の固定ページなし
-
- locate_template([
- 'archive.php', # 2-1. archive.php
- (get_query_var('paged', 1) >= 2
- ? 'paged.php' # 2-2. paged.php (2ページ目以降)
- : null),
- 'index.php', # 2-3. index.php
- ], true);
- }
SEO対策: 重複コンテンツの対応
ここでは、SEOで問題となる事柄について解説します。
これまでの解説内容を実践すると、カテゴリーページへのアクセスと固定ページへのアクセス両方に同じコンテンツを配信するという性質から、ページへの評価が分散してしまうことになります。
どういうことかというと、カテゴリーページ /category/javascript
へアクセスした場合と 固定ページ /javascript
にアクセスした場合とでコンテンツ内容は同じですが、クローラーからは別ページとして扱われてしまうということです。幸い、この問題を解決する方法が確立されています。
<link>
要素のリンク種別 canonical
属性値は、「正規」または「推奨」バージョンのウェブページを示すことができます。
- <head>
- <link rel="canonical" href="https://example.com/category-name">
- </head>
この仕組み活用して、例えば、カテゴリーページとして使用する固定ページのカスタムテンプレートを次のようにします。
- <?php
- /*
- Template Name: Post
- */
- add_action('wp_head', function () {
- if (is_category()) { # カテゴリーページでの表示の場合
- $category_slug = get_query_var('category_name');
- $page = get_page_by_path($category_slug);
- $canonical = get_permalink($page->ID);
- echo '<link rel="canonical" href="' . $canonical . '">';
- }
- });
- get_template_part('single');
これは、固定ページに投稿のテンプレートを適用するというカスタムテンプレートですが、カテゴリーページとしてアクセスされた場合には canonical
をセットしています。