darudaru

だるだるしてるエンジニア

wordpressのプラグインなしでSEOに適したパンくずを表示させる

wordpressのパンくずをプラグインを使わないでPHPで実装したので紹介します。

パンくずの仕様を決める

頂点をブログトップとし、その下にカテゴリ、記事タイトルという階層構造のパンくずを作ります。

トップ
┝プログラミング
┝映画
┗雑記
┗記事タイトル

アーカイブページや固定ページも忘れず考えます。タグ別ページや、年月日ページのことです。
基本的に「HOME > タグ名称」「HOME > 固定ページタイトル」というように、トップ下に各ページのタイトルを表示させるパンくずを作って行きます。
混乱しそうな場合は、一つ一つパターンを書いていくとコードに落としやすいと思います。

そして、パンくずはmicrodataで実装します。Googleが推奨している設置方法です。
仕様はBreadcrumbList - schema.orgに詳しく書いてあります。
難しそうに見えますが、普通にolでパンくずを実装するときとやることは変わりません。

schema.org

ちゃんと実装すると、Googleの検索結果にもパンくずが表示されるようになります。

f:id:skanoemon:20170305182640p:plain

パンくずをPHPで実装する

index.php

パンくずのタグ部分は各ページ共通部品となるため、別テンプレートに切り出すことにしました。
get_template_part()がパンくずの生成処理を呼び出す箇所です。
この記述をパンくずを設置したいpage.phpやsingle.phpに書いていくことで、トップと同じようにパンくずを表示させることができます。

<div class="container clearfix">
<?php get_template_part('breadcrumb'); ?>
<div class="posts">

breadcrumb.php

パンくずの部品です。各ページからget_template_part()で呼び出されるファイルとなります。

<div class="breadcrumb">
  <?php
    echo breadcrumb();
  ?>
</div>

functions.php

パンくずのhtml生成処理です。
breadcrumb()でhtmlのタグを生成し、getBreadcrumbData()でパンくずの元となるデータの生成処理を行っています。 本当は、データ生成処理をfunctions.phpに書いて、htmlの生成はviewのテンプレートで行いたかったのですが、
パンくずのmicrodataのmetaのカウント部分を書こうとすると処理が複雑となってしまい可読性が悪そうだったので、htmlの生成処理までfunctions.phpに持ってきています。
getBreadcrumbData()では早めのreturnを心がけています。

function breadcrumb(){
  $html = '<ol itemscope itemtype="http://schema.org/BreadcrumbList">';

  $breadcrumb = getBreadcrumbData();
  if(empty($breadcrumb)){
    return '';
  }

  $positionNum = 1;
  foreach($breadcrumb as $item){
    $html .= '<li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">';
    $html .= '<a itemscope itemtype="http://schema.org/Thing" itemprop="item" href="' . $item['url'] . '">';
    $html .= '<span itemprop="name">' . $item['name'] . '</span>';
    $html .= '</a>';
    $html .= '<meta itemprop="position" content="' . $positionNum . '" />';
    $html .= '</li>';
    $positionNum++;
  }
  $html .= '</ol>';
  return $html;
}

function getBreadcrumbData(){
  $breadcrumbs = array();
  $breadcrumbs[] = array(
    'name' => 'HOME',
    'url' => home_url()
  );

  // トップページの場合
  if(is_front_page() && is_home()){
    return $breadcrumbs;
  }

  // 自身のページ情報を取得
  $pageInfo = get_queried_object();

  // 固定ページの場合
  if(is_page()){
      $breadcrumbs[] = array(
        'name' => $pageInfo->post_title,
        'url' => get_the_permalink()
      );
      return $breadcrumbs;
  }

  // タグページの場合
  if(is_tag()){
    $breadcrumbs[] = array(
      'name' => $pageInfo->name,
      'url' => get_tag_link($pageInfo->term_id)
    );
    return $breadcrumbs;
  }

  // 日付別のページの場合
  if(is_date()){
    $breadcrumbs[] = array(
      'name' => get_query_var('year') . '年' . get_query_var('monthnum') . '月',
      'url' => get_month_link(get_query_var('year'), get_query_var('monthnum'))
    );
    return $breadcrumbs;
  }

  $category = get_the_category();
  if(empty($category)){
    return $breadcrumbs;
  }

  $breadcrumbs[] = array(
    'name' => $category[0]->name,
    'url' => get_category_link($category[0]->term_id)
  );

  // カテゴリページの場合
  if(is_category()){
    return $breadcrumbs;
  }

  // 記事ページの場合
  if(is_single()){
    $breadcrumbs[] = array(
      'name' => $pageInfo->post_title,
      'url' => get_the_permalink()
    );
    return $breadcrumbs;
  }
  return $breadcrumbs;
}

テストする

構造化テストツールでエラーがでないか確認しましょう。

完成したパンくず

見た目はこんな感じ。ブログ、カテゴリ、記事タイトル、という階層になっています。

f:id:skanoemon:20170305182642p:plain

html

<div class="breadcrumb">
 <ol itemscope="" itemtype="http://schema.org/BreadcrumbList">
  <li itemprop="itemListElement" itemscope="" itemtype="http://schema.org/ListItem">
   <a itemscope="" itemtype="http://schema.org/Thing" itemprop="item" href="http://darudaru-life.com">
    <span itemprop="name">HOME</span>
   </a>
   <meta itemprop="position" content="1">
  </li>
  <li itemprop="itemListElement" itemscope="" itemtype="http://schema.org/ListItem">
   <a itemscope="" itemtype="http://schema.org/Thing" itemprop="item" href="http://darudaru-life.com/category/programming">
    <span itemprop="name">プログラミング</span>
   </a>
   <meta itemprop="position" content="2">
  </li>
  <li itemprop="itemListElement" itemscope="" itemtype="http://schema.org/ListItem">
   <a itemscope="" itemtype="http://schema.org/Thing" itemprop="item" href="http://darudaru-life.com/programming/nodejs-version-up">
    <span itemprop="name">node.jsをnodebrewを使ってバージョンアップする</span>
   </a>
   <meta itemprop="position" content="3">
  </li>
 </ol>
</div>

css

最初の要素じゃないliタグの前に「>」を設置する、をcssの疑似クラスで実装しています。

.breadcrumb li {
  display: inline-block;
}

.breadcrumb li:not(:first-child):before {
  content: '>';
  margin: 0px 5px;
}

functions.phpでは、自分のブログに必要なパターンのパンくず生成処理しか書いてません。404ページ等の処理も必要な場合は、その分if文を増やして頂く必要があります。
wordpressにはパンくずを生成してくれるプラグインもあるようですが、難しいものではないので自分で実装できるならしちゃったほうが処理も軽くなってよいと思います。