a-blog cmsで記事に著者情報を表示する方法と構造化データについて
更新情報
2022-01-08 : Twitterで ジェノベーゼ寺崎 (@genovese115) さんがご提案くださった素敵な実装アイデアを追記しました。
この記事について
この記事は、a-blog cms Advent Calendar 2021 - Adventar 10日目の記事です。
記事に執筆者情報を掲載するサイトが一般的になってきました。
国産CMS a-blog cmsでは、カスタムフィールドを柔軟に設定・表示することができるため、CMSが提供している標準機能で実装が可能です。
今回は、実装方法を3つ、考えてみました。
1と3は、実案件で実装検証済です。
2に関しても、テスト環境である程度実証済です。
- ユーザーを利用する
- カテゴリーを利用する
- エントリーを利用する
エントリーに表示させたい執筆者情報とは
まず、記事(エントリー)には、以下の情報が掲載できれば良いのではと思います。
- プロフィール写真
- 名前
- 肩書
- プロフィール文章
- 執筆者のウェブサイト・プロフィールページ
- 執筆者のSNS
それぞれの実装方法によって、表示できたり、できなかったり、工夫が必要だったりします。
共通のメリットとして検討したいこと
いずれの方法でも、執筆者の情報は一元管理する事が第一条件です。
ユーザーを利用する
概要
この方法では、エントリーを執筆したCMSのユーザー情報をエントリーに表示することができます。
a-blog cmsのユーザーには、デフォルトで以下のような情報が登録できます。
ここにない情報も、カスタムフィールドを作成することが可能です。
ユーザー情報にカスタムフィールドを用意するには、以下のファイルに入力用のコードを記述します。
themes\{your-theme}\admin\user\field.html
ここに記述した内容が、ユーザー管理のカスタム設定に表示されるようになります。
エントリーにユーザー情報を表示させる方法
CMSに登録したユーザー情報はカスタムフィールドを含め、エントリー本文(Entry_Body)
モジュールのuserField
ブロックで表示することができます。
Entry_Body
の変数表はこちら
https://developer.a-blogcms.jp/document/acms-code/vars/Entry_Body.html?cache=off
共通メリット : 執筆者の一元管理
この方法の場合、ユーザー管理の子ブログへの権限
にチェックを入れれば、子ブログ間でも執筆者情報を表示できるため、ユーザー情報の一元管理管理が可能です。
メリット01 : 管理面で、誰が書いたのかが分かりやすい
この方法のメリットの一つは、誰がそのエントリーを書いたのかが分かりやすいという点です。
管理画面にログインして、エントリーを確認した時に、「ああ、このエントリーはこの人が書いたのか」と、すぐに分かります。
例えば、複数人でサイトを運用していて、エントリーの修正が必要になった場合、誰に修正を依頼すれば良いのか、すぐにわかります。
一番分かりやすい運用方法なのではないかと思います。
メリット02 : エントリーにユーザーのカスタムフィールドを表示できる
エントリー本文(Entry_Body)
のuserField
ブロックでは、ユーザーのカスタムフィールドを表示できます。
冒頭に記載しましたエントリーに表示させたい情報のうち、デフォルトのフィールドとカスタムフィールドを分けるなら以下の通りです。
- プロフィール写真 (デフォルト)
- 名前 (デフォルト)
- 肩書 (カスタムフィールド)
- プロフィール文章 (カスタムフィールド)
- 執筆者のウェブサイト・プロフィールページ (デフォルト)
- 執筆者のSNS (カスタムフィールド)
いずれにしてもカスタムフィールドが使えるので、実装は楽です。
デメリット : ユーザー数の制限がある
デメリットとしては、プランによっては、ユーザー数の上限があることでしょうか。
プラン(ライセンス)に関してはこちら
ライセンス | 使いやすさで選ぶ国産CMS | a-blog cms
規模の大きなメディアサイトで、執筆者=CMSのユーザーでないという場合、かつ、低コストで運用を始めたいという場合は、別の方法の検討が必要になりそうです。
あるいは、ライターさんから記事を頂いて、それをサイト管理者が登録するという運用体制の場合がこれに当たるかと思います。
カテゴリーを利用する
概要
この方法では、執筆者をカテゴリーとして管理します。
a-blog cmsのカテゴリーには、デフォルトで以下のような情報が登録できます。
ここにない情報も、カスタムフィールドを作成することが可能です。
カテゴリーにカスタムフィールドを用意するには、以下のファイルに入力用のコードを記述します。
themes\{your-theme}\admin\category\field.html
ここに記述した内容が、カテゴリーのカスタム設定に表示されるようになります。
なお、カテゴリーに応じてカスタムフィールドを変更したい場合は、themes\{your-theme}\admin\category\field.html
のファイルに条件分岐を記述することで振り分けが可能になります。
あるいは、URLコンテキスト別に振り分ける場合は、field.html
に以下の記述をし、該当するディレクトリにそれぞれのファイルを用意します。
@include("/admin/category/bcd/%{BCD}.html")
@include("/admin/category/rccd/%{RCCD}.html")
@include("/admin/category/ccd/%{CCD}.html")
このあたりは、配布されているテーマファイルを色々と眺めていると非常に勉強になります。
カテゴリーを利用する場合の実例を考える
さて、この場合、エントリーのメインのカテゴリは別に存在していて、そのエントリーに執筆者情報を付与したいという運用が考えられます。
a-blog cms でサブカテゴリー機能をする場合、設定が必要です。
管理ページ > コンフィグ > 編集設定
で、「サブカテゴリー」を「有効」にしましょう。
詳しくは以下の公式ドキュメントにまとめられています。
新機能サブカテゴリーを使ってみよう | 2018秋合宿 | ハンズオン | a-blog cms developer
カテゴリー構造をどうするか
以下のような構造での実装を考えてみます。
- ルートブログ
- カテゴリー : ニュース
- カテゴリー : 製品情報
- カテゴリー : 執筆者 *グローバルにする
- カテゴリー : 山田太郎 *グローバルにする
- 子ブログ
- 様々なカテゴリ
エントリーにサブカテゴリー情報を表示させる方法
ここでも、エントリーを表示させる基本的なモジュールエントリー本文(Entry_Body)
を利用します。
この運用の場合、例えば、エントリーのメインのカテゴリーが製品情報
で、執筆者情報のためのサブカテゴリー山田太郎
が適用されると想定します。
エントリーに登録される執筆者情報は、サブカテゴリーになります。
エントリー本文(Entry_Body)
では、sub_category
のブロックでサブカテゴリー情報を表示できますが、メインのカテゴリーと異なり、サブカテゴリーの場合、カスタムフィールドを表示することができません。
そのため、エントリーには、以下の赤枠のように、カテゴリー名に設定した執筆者の名前のみが表示できます。
この運用の場合、執筆者の情報はカテゴリーに以下のようにして登録することとします。
そしてこの場合、エントリー本文(Entry_Body)
では、カスタムフィールドは表示できない、という事になります。
- プロフィール写真 (カスタムフィールド)
- 名前 (デフォルト)
- 肩書 (カスタムフィールド)
- プロフィール文章 (カスタムフィールド)
- 執筆者のウェブサイト・プロフィールページ (カスタムフィールド)
- 執筆者のSNS (カスタムフィールド)
では、カテゴリーのカスタムフィールドをどう表示させるか
これは、ひと工夫が必要になりそうです。
後述する、エントリーにを利用した実装と同じ工夫で実現可能かと思います。
共通メリット : 執筆者の一元管理
執筆者の一元管理はカテゴリーでも実現できます。
カテゴリーの設定では、そのカテゴリーを 下の階層のブログが利用することを許可する ためのグローバル
にする、という選択肢があります。
以下の赤枠の項目です。
これにより、子ブログを作成しているサイトであっても、執筆者情報を一元管理することができます。
サイト全体で管理したいカテゴリーがある場合は、この機能が便利です。
メリット01 : 執筆者の記事一覧を表示しやすい
カテゴリーを使うメリットは、エントリーサマリー : Entry_Summary
といった、記事の一覧を表示するモジュールを使って、執筆者別の記事を一覧表示しやすい事です。
メリット02 : 簡易的なプロフィールページが作れる
執筆者情報をカテゴリーで管理すると、一覧ページを簡単なプロフィールページにできます。
記事に適用する執筆者情報はサブカテゴリーとして登録するため、エントリー本文(Entry_Body)
で、サブカテゴリーのカスタムフィールドを表示することはできないのですが、カテゴリーそのものに優劣はありません。
そのため、執筆者カテゴリーのカスタムフィールドの情報は、エントリーサマリー : Entry_Summary
等で表示可能です。
例えば、記事Aがあったとします。
その記事には、以下のカテゴリーが登録されています。
- エントリー : 記事A
- メインカテゴリー : 製品情報
- サブカテゴリー : 執筆者カテゴリーの子カテゴリーの山田太郎
ここで気を付けたいのは、製品情報というカテゴリーも、山田太郎というカテゴリーも、メインやサブという優劣はなく、カテゴリーであるという事です。
サブカテゴリー機能とは、あくまで、1つのエントリーに対して、メインとサブを登録する機能です。
よって、エントリーサマリー : Entry_Summary
で、カテゴリー別のエントリー一覧を表示する場合は、どのカテゴリーでも、カスタムフィールドが表示できます。
例えば、執筆者カテゴリーの子カテゴリーの山田太郎のエントリー一覧を表示する場合は、以下のようなURLが考えられます。
https://domain/author/yamadataro/
エントリー一覧を表示するためにエントリーサマリー : Entry_Summary
モジュールを使えば、categoryField
ブロックでカスタムフィールドを表示できるので、このURLでアクセスした際に、執筆者のカテゴリーに用意した以下のようなカスタムフィールドも表示できます。
- プロフィール写真 (カスタムフィールド)
- 名前 (デフォルト *これはデフォルで用意されている名でもOKですし、カスタムフィールドで別途用意してもOK)
- 肩書 (カスタムフィールド)
- プロフィール文章 (カスタムフィールド)
- 執筆者のウェブサイト・プロフィールページ (カスタムフィールド)
- 執筆者のSNS (カスタムフィールド)
つまり、記事一覧ページに執筆者のプロフィールを表示できます。
デメリット : エントリーにカスタムフィールドを表示させるには工夫が必要
前述の通り、エントリー本文(Entry_Body)
では、サブカテゴリーのカスタムフィールドを表示することができないので、エントリーに執筆者の詳しい情報を表示するには工夫が必要です。
これは後述します。
エントリーを利用する
概要
この方法では、執筆者登録用のブログを作成し、執筆者情報をエントリーとして管理します。
ブログの構造
以下のような構造を想定します。
- ルートブログ
- カテゴリー
- 執筆者情報のためのブログ :
執筆者ブログ
とします- 執筆者情報のためのエントリー
- 様々な子ブログ
- カテゴリー
エントリーに執筆者エントリーの情報を表示させる方法
この場合は、カスタムフィールドの活用が必須になります。
まず、執筆者ブログ
のエントリーに、以下のカスタムフィールドを用意します。
名前だけは、カスタムフィールドではなく、エントリーの名前とします。
- プロフィール写真
- 名前 (エントリーの名前にします)
- 肩書
- プロフィール文章
- 執筆者のウェブサイト・プロフィールページ
- 執筆者のSNS
エントリーのカスタムフィールドは、以下に記述するか、条件分岐で振り分けします。
\{your-theme}\admin\entry\field.html
URLコンテキストで条件分岐させる場合は、field.html
に以下の記述をします。
@include("{your-theme}/admin/entry/bcd/%{BCD}.html")
執筆者のブログコードをauthor
とした場合、以下のディレクトリにファイルを置いて、カスタムフィールドの記述をすることで条件分岐できます。
\{your-theme}\admin\entry\bcd\authors.html
記事の表示には、ここでもエントリー本文(Entry_Body)
を利用します。
執筆者ブログのエントリーに登録したカスタムフィールドは、他の記事のエントリーでは、そのままでは表示できません。
この2つを結びつける必要があります。
- 記事としてのエントリー (以降、
記事
とします) - 執筆者情報を登録する
執筆者ブログ
のエントリー (以降、執筆者ブログのエントリー
とします)
これを実現する方法のひとつとして、以下の方法を利用できます。
- 記事のエントリーに、執筆者情報を表示するためのカスタムフィールドを用意して、その値に
執筆者ブログのエントリー
のカスタムフィールドの値を選択させる
この方法を利用した場合、記事のエントリーの編集画面は以下のようになります。
これを実現するためには、執筆者ブログのエントリータイトルを、通常の記事のエントリーの編集画面で、Entry_List
などのモジュールで、一覧表示して選べるようにします。
そして、そこで選択した執筆者名を、記事のエントリーに用意したカスタムフィールドに格納します。
執筆者のプロフィール文章などのカスタムフィールドは、上記の執筆者ブログのエントリータイトルをフックに選択させることが可能です。
この、執筆者名に不随する情報は、自動的に選択させるため、管理画面上に表示させる必要はないため、"display: none;"
などとすると良いかと思います。
実際のコード
ここでは、通常記事のエントリーの管理画面上で執筆者名を選択させ、選択した執筆者に不随するプロフィール写真の情報(執筆者ブログのエントリー
のカスタムフィールド)を自動的に適用する例を紹介します。
執筆者情報が何も選択されていなければ、明示的に指定したデフォルトの執筆者名を適用し、既にエントリーに情報が格納されていれば、その値を表示し、そうでなければ、新たに選択した執筆者情報を格納します。
この例では、JavaScriptを利用します。
利用する変数は以下の通りです。 執筆者の名前である、{title}と{entry_author_name}を連動させます。
- 執筆者の名前
- {title} : 執筆者ブログのエントリータイトル
- {entry_author_name} : 通常の記事のエントリーに用意したカスタムフィールド
- 執筆者の写真
- {pic} : 執筆者ブログのエントリーに用意したカスタムフィールド
- {entry_author_pic} : 通常の記事のエントリーに用意したカスタムフィールド
以下が、エントリーのカスタムフィールドのHTMLのサンプルです。
Entry_List
を使って、執筆者ブログのエントリータイトルを表示させています。
<table class="adminTable acms-admin-table-admin-edit">
<tr>
<th>執筆者ID
<i class="acms-admin-icon-tooltip js-acms-tooltip"></i>
</th>
<td>
<select name="entry_author_name" class="acms-admin-form-width-full">
<!-- 新規エントリー作成など、何も指定されていなければデフォルトの執筆者を適用する -->
<!-- BEGIN_IF [{entry_author_name}/em] -->
<option value="デフォルトの執筆者" {entry_author_name:selected#}デフォルトの執筆者>デフォルトの執筆者</option>
<!-- ELSE -->
<!-- 指定されていればその値を適用 -->
<option value="{entry_author_name}" {entry_author_name:selected#}{entry_author_name}>{entry_author_name}</option>
<!-- /指定されていればその値を適用 -->
<!-- END_IF -->
<!-- /新規エントリー作成など、何も指定されていなければデフォルトの執筆者を適用する -->
<!-- 執筆者ブログのエントリーを取得 -->
<!-- BEGIN_MODULE Entry_List id="admin_entry_list_author" -->
<!-- BEGIN entry:loop -->
<option value="{title}" {entry_author_name:selected#}{title}>{title}</option>
<!-- END entry:loop -->
<!-- END_MODULE Entry_List -->
<!-- /執筆者ブログのエントリーを取得 -->
</select>
<input type="hidden" name="field[]" value="entry_author_name" />
</td>
</tr>
</table>
<!-- プロフィール写真 -->
<table class="adminTable acms-admin-table-admin-edit" style="display: none;">
<tr>
<th>プロフィール写真</th>
<td>
<select name="entry_author_pic" class="acms-admin-form-width-full">
<!-- 執筆者が指定されていればその値を適用 -->
<!-- BEGIN_IF [{entry_author_pic}/nem] -->
<option value="{entry_author_pic}" {entry_author_pic:selected#}{pic@squarePath}>{entry_author_pic}</option>
<!-- END_IF -->
<!-- /執筆者が指定されていればその値を適用 -->
<!-- 執筆者ブログのエントリーを取得 -->
<!-- BEGIN_MODULE Entry_List id="admin_entry_list_author" -->
<!-- BEGIN entry:loop -->
<option data-author="{title}" value="{pic@squarePath}" {entry_author_pic:selected#}{pic@squarePath}>{pic@squarePath}</option>
<!-- END entry:loop -->
<!-- END_MODULE Entry_List -->
<!-- /執筆者ブログのエントリーを取得 -->
</select>
<input type="hidden" name="field[]" value="entry_author_pic" />
</td>
</tr>
</table>
以下が、JavaScriptのサンプルです。
// 執筆者名をキーに、非表示のセレクトボックスを選択させる
const setAuthor = function () {
let current_name_selected_val = $('#js-entry-author-name option:selected').val();
// プロフィール写真のセレクトボックスの操作
$('#js-entry-author-pic option[data-author=' + '"' + current_name_selected_val +'"]').prop('selected', true);
}
// 執筆者の選択時に実行
$('#js-entry-author-name').on('click', function () {
setAuthor();
});
// ロード時にも実行
$(window).on('load', function () {
setAuthor();
});
共通メリット: 執筆者の一元管理
執筆者情報を専用のブログで一元管理できます。
メリット01 : 執筆者のプロフィールページを作りやすい
この方法のメリットは、執筆者のプロフィールページを作りやすい点にあります。
執筆者のプロフィールページが、エントリーであるため、エントリーに用意しているユニットが利用できるためです。
詳細なプロフィールページを作る場合、エントリーを利用した方が、表現の幅が広がるため、この実装方法が有効かと思います。
デメリット : 執筆者の情報を表示するのに工夫が必要
上述の通り、記事のエントリーにカスタムフィールドを表示するには、工夫が必要です。
執筆者の記事一覧を表示させるには
この方法の場合、カテゴリーと異なり、ポストインクルードなどで、エントリーを絞り込み表示させる必要があります。
執筆者をカテゴリーで管理する場合にも転用できる
エントリー本文(Entry_Body)
では、サブカテゴリーのカスタムフィールドを表示することができませんが、この方法を利用して、執筆者カテゴリーのカスタムフィールドを通常のエントリーのカスタムフィールドに渡す事で、エントリー本文(Entry_Body)
モジュールでもカテゴリーに登録されたカスタムフィールドを表示することが可能かと思います。
コンビネーション (2022-01-08 追記)
Twitterでジェノベーゼ寺崎さんが、合わせ技を教えてくださいました。
a-blog cms awards 2021を受賞された清水さんの記事!
— ジェノベーゼ寺崎 (@genovese115) December 9, 2021
僕が実装するならあわせ技で
①執筆者情報はユーザで管理
②ユーザはライセンス制限のない「読者」権限で発行
③エントリーにユーザIDをカスタムフィールドで保存
④User_Fieldモジュール(ctxで③の値を渡す)で情報を表示
のようにするかな〜 https://t.co/8BYi19dMF1
読者権限
なら、ユーザー数制限がないため、とても効率的な方法だなと、目から鱗でした。
有難うございました!
構造化データのマークアップ
さて、今回紹介した実装方法では、構造化データのマークアップが可能です。
a-blog cmsでは、配布されているテーマで、構造化データのマークアップ用のテンプレートファイルが提供されており、パンくずの構造化データに対応しています。
そのため、こちらをカスタマイズすることで、新たにデータを追加できます。
構造化データ用のテンプレートファイルは、以下に用意されています。
\{your-theme}\include\head\structured-data.html
Googleでは、検索結果の表示を拡張するためのリッチリザルトという仕組みを用意していますが、一般的な記事ページは、Article
の構造化データのマークアップが利用できます。
リッチリザルトや、それをさらに強化したエンリッチリザルトの情報は、以下の記事をご参照ください。
以下は、Article
タイプの構造化データと、パンくずの構造化データを組み合わせる例です。
{}
の中に、エントリーやユーザー、カテゴリーの情報を出力します。
[
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "{article-headline}",
"description": "{article-description}",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "{article-url}"
},
"image": {
"@type": "ImageObject",
"url": "{article-image-path}",
"width": {article-image-width},
"height": {article-image-height}
},
"datePublished": "{article-published-date}",
"dateModified": "{article-updated-date}",
"author": {
"@type": "Person",
"name": "{article-author-name}",
"image": "{article-author-image-path}",
"url": "{article-author-url}",
"sameAs": [
"{article-author-sns-url-01}",
"{article-author-sns-url-02}"
],
"alternateName": "{article-author-other-name}",
"worksFor": {
"@type": "Corporation",
"name": [
"{article-author-organization-name-01}",
"{article-author-organization-name-02}"
],
"url": "{article-author-organization-url}",
"url": "{article-author-organization-other-url}"
}
}
},
{
"@context": "http://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
// デフォルトのテンプレートファイルの記述
]
}
]
構造化データのマークアップは、Article
の他にも、動画やレシピ、求人など、Googleが色々と採用していますが、a-blog cmsのカスタムフィールドと条件分岐を活用すると、様々なタイプに適用できるのではないかと思います。
余談
執筆者情報をポストインクルードで表示させる方法も試したのですが、この場合、執筆者情報を構造化データとして出力することができそうになかったため、検討から省きました。