『basersマガジン』では「はじめまして!」のteckingです。『WordPressユーザーのbaserCMS覚え書き』というサイトを運営してます。こちらの世界でもどうぞよろしくお願いします!
検索結果のパンくずリスト?
さてみなさん、ウェブ検索しているときにこんな表示に遭遇したことはありませんか?
ページタイトルの下にパンくずリスト状の文字列が出ていますよね。通常、この欄にはページのURLしか出ませんが、パンくずリストが表示されることで目指す記事が属する階層(カテゴリー)を一目で把握できるようになります(なりますよね? なりますよね!)。
検索結果にパンくずリストを表示させるには、サイト内にパンくずリストを置くだけではダメで、検索エンジンに「検索結果にも反映させてね」と教えてあげる必要があります。
そのための手がかりを「構造化データ」といい、一定のフォーマットが決められています。ということで、baserCMSでつくったサイトのパンくずリストに「構造化データ」を取り入れて検索結果をカスタマイズしてみましょう。
構造化データの基本
まずは、パンくずリストに使われる構造化データの記述をおさえておきましょう。英語版ではあるものの、Googleが公式ドキュメントを公開しています。
- Breadcrumbs - Structured Data — Google Developers
https://developers.google.com/structured-data/breadcrumbs
「Properties」(プロパティ)の項で
- title …… パンくずのタイトル文字列
- url …… パンくずのリンク先URL
- child …… パンくずリストの「子要素」にあたることを示す識別子
の3つの属性が示され、その下の「Example」欄で実際のマークアップ例が示されています。
「The following sections describe how to mark up this content using microdata or RDFa.」とあるように、構造化データの形式として
- microdata
- RDFa
の二通りを受け付けるようなことが書かれていますが、そもそもの話「Properties」での属性がmicrodataのものなので、ここではmicrodata形式でパンくずリストをマークアップすることにします。
パンくずリストを作るための関数(BcBaserヘルパー)
マークアップに入る前に、baserCMSでのパンくずリスト実装をあたらめて確認しておきましょう。
テーマによってパンくずリストが組み込まれていることもありますが、実装の基本を学ぶなら /lib/Baser/View/Elements/crumbs.php を見るとよいでしょう。独自テーマにパンくずリストを実装する場合も、同ファイルを /app/webroot/theme/{使用中のテーマディレクトリ}/Elements 内にコピーしてカスタマイズするのがおすすめです。
さて、同ファイルを開いてみると
- addCrumb …… パンくずリストの要素を追加する
- crumbs …… パンくずリストを出力する
などなど $this->BcBaser で始まる関数がいくつか見えますよね(関数の詳細はbaserCMS公式Wikiを参照ください)。これらの関数をベースに、構造化データが出力されるよう手を加えることにします。
「独自ヘルパー」で構造化データを追加
といっても /lib/Baser/View/Helper/BcBaserHelper.php を開いて、関数の中身を直接いじるのはNG。アップデートとともに苦労の痕跡がきれいさっぱり流れてしまいます。
そこで、関数のおいしいところをいただきつつオリジナル関数をつくることにします。baserCMSの核となるCakePHPの世界で「独自ヘルパー」とも呼ばれるこの関数は、下のような書式で /app/View/Helper 内に FooHelper.php として配置します。
<?php class FooHelper extends AppHelper { /** * 独自ヘルパーの処理 */ }
CakePHPのお作法にのっとり、PHPファイル名(FooHelper.php)とクラス名(FooHelper)は必ず同じものにします。ここでは例示の意味で FooHelper としましたが、
- アプリケーションが使うファイル名・クラス名(例:BcBaserHelper)と重ならない
- ファイル名・クラス名を「アッパーキャメルケース」で書く
ことが守られていれば任意の名前をつけてかまいません。
さて、前置きがずいぶん長くなったので実際のコードを見てみることにしましょう。
(サイトの仕様上インデントが効かないようなので、整形したソースをGistにアップしました)
<?php /** * SDHelper パンくずリストに構造化データを追記するヘルパー * テーマファイル内で $this->SD->foo() の記述で呼び出す */ class SDHelper extends AppHelper { /** * ヘルパー */ public $helpers = array('BcBaser', 'BcHtml'); /** * パンくずリストの要素を追加する * パラメータ, 返り値は $this->BcBaser->addCrumb() に準ずる */ public function addCrumb($name, $link = null, $options = array()) { $options = array_merge(array( 'forceTitle' => true ), $options); if (!empty($link)) { $options['itemprop'] = 'url'; $this->BcHtml->addCrumb($this->BcHtml->tag('span', $name, array('itemprop' => 'title')), $link, $options); return; } $this->BcHtml->addCrumb($name, $link, $options); } /** * パンくずリストを出力する * パラメータ, 返り値は $this->BcBaser->crumbs() に準ずる */ public function crumbs($separator = '»', $startText = false) { $crumbs = $this->BcHtml->getStripCrumbs(); if (empty($crumbs)) { return; } $out = array(); if ($startText) { $out[] = $this->BcHtml->tag('span', $this->BcBaser->getLink($this->BcHtml->tag('span', $startText, array('itemprop' => 'title')), '/', array('itemprop' => 'url')), array('itemscope', 'itemtype' => 'http://data-vocabulary.org/Breadcrumb')); } foreach ($crumbs as $crumb) { if (!empty($crumb[1])) { $out[] = $this->BcHtml->tag('span', $this->BcBaser->getLink($crumb[0], $crumb[1], $crumb[2]), array('itemscope', 'itemtype' => 'http://data-vocabulary.org/Breadcrumb', 'itemprop' => 'child')); } else { $out[] = $crumb[0]; } } echo implode($separator, $out); } }
コード解説
今回はコードのひな形として /lib/Baser/View/Helper/BcBaserHelper.php 内の
- addCrumb
- crumbs
をおいしいトコどりしつつ、「Structured Data(=構造化データ)」の頭文字をとった「SDHelper」という独自ヘルパーをつくりました。ポイントは二つ。
一つは
public $helpers = array('BcBaser', 'BcHtml');
の記述。独自ヘルパー内でbaserCMS標準の関数(ヘルパー)を使いたいときにこのように書くことで、テーマファイルのように
$this->BcBaser->foo()
と呼び出せるようになります。この仕組みを初めて知ったとき、あまりの簡単さに思わず「ほえーっ」と声を上げましたね私。
もう一つのポイントは
$this->BcHtml->tag()
です。なんとなく使い方を察していただけるかもしれませんが、任意のタグを生成したいときに便利な関数で下のような書式で使います。
$this->BcHtml->tag($tag, $text, $attributes)
- $tag …… 生成するタグ(文字列)
- $text …… タグで挟みたいテキスト(文字列)
- $attributes …… タグに挿入する属性と値(配列)
書式に従って
$this->BcHtml->tag('span', $this->BcBaser->getLink($this->BcHtml->tag('span', $startText, array('itemprop' => 'title')), '/', array('itemprop' => 'url')), array('itemscope', 'itemtype' => 'http://data-vocabulary.org/Breadcrumb'))
と記述すると span > a > span とタグが入れ子になり、下のようなHTMLが出力されます。
{$startText}
ではテーマファイルに実装!
話題をぎゅいーんと巻き戻しまして /app/webroot/theme/{使用中のテーマディレクトリ}/Elements 内にコピーした crumbs.php の話。ファイルを開き
$this->BcBaser->addCrumb('' . $crumb['name'] . '');
とか
$this->BcBaser->crumbs(' > ', 'ホーム');
など、baserCMS標準関数で書かれた箇所を独自ヘルパーの記述に置き換えます……といっても修正は簡単。
$this->SD->addCrumb($crumb['name']);
$this->SD->crumbs(' > ', 'ホーム');
これだけで独自ヘルパーが反映され、パンくずリストのHTMLにも
<span itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb"><a href="/" itemprop="url"><span itemprop="title">ホーム</span></a></span>
<strong><span itemprop="title">記事タイトル</span></strong>
といったように構造化データが追記されます。
($this->BcBaser->element('crumbs') で パンくずリストのエレメントを出力させることをお忘れなく)
通常はbaserCMS標準のヘルパー(BcBaserHelper)を使うので $this->BcBaser と書くところ、独自ヘルパー(SDHelper)を使うことから $this->SD に置き換えたというわけです。
無事にHTMLへ出力できたら念のためGoogleの構造化データテストツールで文法チェックしておきましょう。
上のキャプチャ画像は、私が運営している『WordPressユーザーのbaserCMS覚え書き』(http://baser-for-wper.tecking.org)を検索した結果です。構造化マークアップした後にXMLサイトマップを再送信したところ、3日くらい後からじわじわとウェブ検索へ反映されるようになりました。
余談:アイキャッチ画像について
パンくずリストネタの記事だったので、その語源とされている童話『ヘンゼルとグレーテル』の挿絵をWikipediaから引用しました。著作権保護期間が切れたパブリックドメイン(PD)の挿絵とのことで、今までブログなどいろんな記事を書いてきてPDの画像を使ったのは初めての経験でした。