MENU

問い合わせ


    【WordPressで作るキュレーションメディア 第6回】著者・監修者プロフィールを表示する(E-E-A-T の考え方)

    キュレーションメディアの記事を読んだ読者が最初に気にするのは、「この情報は誰が書いて、誰が確認したのか」です。特にセキュリティやお金、健康など、判断を誤ると困る分野では、書き手の経歴や監修の有無が記事を信頼できるかどうかの手がかりになります。

    「記事に著者と監修者のプロフィールを出したい。WordPress の標準機能だけで足りる? 監修者は記事ごとに選べるようにしたい」

    結論から言うと、著者の肩書き・専門分野はユーザーメタ(=ユーザーごとの追加情報)、監修者は投稿メタ(=記事ごとの追加情報)として小さなプラグインに登録し、表示は「著者ボックス」ブロックをテンプレートに置く形が保守しやすくおすすめです。WordPress 6.8 の標準の仕組み(register_meta、エディターのサイドバー拡張、動的ブロック)で実装できます。

    前回の第5回では、まとめリストと比較表をパターンとブロックスタイルで作りました。第6回の今回は、著者・監修者のプロフィールを登録・表示する仕組みを作ります。

    目次

    E-E-A-T と著者情報:Google の説明を正しく押さえる

    著者情報の話になると、よく「E-E-A-T」という言葉が出てきます。まず、Google 自身がどう説明しているかを確認しておきます(以下は2025年8月時点の Google 検索セントラルの記述に基づきます)。

    • E-E-A-T は、エクスペリエンス(Experience)、専門性(Expertise)、権威性(Authoritativeness)、信頼性(Trustworthiness)の頭文字で、中でも信頼性が最も重要とされています。
    • Google は、E-E-A-T 自体はランキングに直接影響する要因ではないと明記しています。
    • そのうえで、コンテンツを「誰が、どのように、なぜ」作ったかという観点で見直すことを勧めており、「誰が」については、著者が誰かを明確にしているか、しかるべき場所にバイライン(=著者名の表示)があるか、それが著者の経歴や専門分野の情報につながっているか、といった問いを挙げています。

    📰 出典:Google 検索セントラル「有用で信頼性の高い、ユーザーを第一に考えたコンテンツの作成」

    つまり、著者・監修者を表示すれば検索順位が上がる、というものではありません。この連載では、著者情報の表示を「読者が記事の信頼性を自分で判断するための情報」として実装します。検索エンジンのためではなく、読者のために書き手を明らかにする、という位置づけです。

    今回のゴールと、データの置き場所

    完成すると、次のように動きます。

    • 「ユーザー > プロフィール」に、肩書き・専門分野・プロフィールURLの入力欄が増える
    • 投稿の編集画面の右側(「投稿」タブ)に「監修」パネルが増え、監修者と監修日を選べる
    • 記事の本文の下に、著者のプロフィールが表示される。監修者を設定した記事でのみ、監修者のプロフィールと監修日も表示される
    • 著者名から著者アーカイブ(その人の記事一覧)に移動でき、そこにもプロフィールが表示される

    データの置き場所は次のように分けました。

    情報保存先理由
    名前・紹介文WordPress 標準のユーザー情報(表示名、プロフィール情報)既存の項目をそのまま使う
    肩書き・専門分野・プロフィールURLユーザーメタ(curation_job_title など)人に付く情報で、どの記事でも同じ
    監修者・監修日投稿メタ(_curation_supervisor_id、_curation_supervised_on)記事ごとに違う情報

    監修者も WordPress のユーザーとして登録し、記事ではユーザーを選ぶ方式にしました。名前を記事ごとに手入力すると、表記ゆれや経歴の更新漏れが起きるためです。

    今回追加・変更したファイル

    ファイル内容
    プラグイン includes/profile-fields.phpユーザーメタの登録とプロフィール画面の入力欄(新規)
    プラグイン includes/meta.php監修者・監修日の投稿メタと、監修パネルの読み込み(新規)
    プラグイン editor/supervisor-panel.jsエディターの「監修」パネル(新規)
    プラグイン blocks/author-box/著者ボックスの動的ブロック(新規)
    プラグイン webpack.config.jsブロック以外の JS もビルドする設定(新規)
    プラグイン curation-tools.php読み込みとブロック登録の追加、バージョン 0.6.0
    テーマ parts/author-box.html著者・監修者のテンプレートパーツ(新規)
    テーマ templates/single*.html3つの記事テンプレートにパーツを追加
    テーマ templates/author.html著者アーカイブ(新規)
    テーマ theme.json・style.cssテンプレートパーツの登録、バージョン 0.6.0

    著者のプロフィール項目をユーザーメタで追加する

    まず、肩書き・専門分野・プロフィールURLをユーザーメタとして登録します。

    wp-content/plugins/curation-tools/includes/profile-fields.php(抜粋)

    function curation_tools_register_profile_meta() {
    	foreach ( curation_tools_profile_fields() as $key => $field ) {
    		register_meta(
    			'user',
    			$key,
    			array(
    				'type'              => 'string',
    				'description'       => $field['label'],
    				'single'            => true,
    				'default'           => '',
    				'show_in_rest'      => true,
    				'sanitize_callback' => 'url' === $field['type'] ? 'esc_url_raw' : 'sanitize_text_field',
    				// 第3引数はメタを更新する対象のユーザーID。そのユーザーを編集できる人だけが更新できる。
    				'auth_callback'     => static function ( $allowed, $meta_key, $user_id ) {
    					return current_user_can( 'edit_user', $user_id );
    				},
    			)
    		);
    	}
    }
    add_action( 'init', 'curation_tools_register_profile_meta' );

    register_meta() で型・サニタイズ(=入力値を安全な形に整えること)・編集できる人を決めておくと、管理画面・REST API・WP-CLI のどこから保存しても同じルールが適用されます。URL の項目は esc_url_raw を通すため、javascript: のような値は空になります。

    📰 出典:WordPress Developer Resources「register_meta()」

    show_in_rest を true にした項目は、REST API で誰でも読めるようになります。WordPress の /wp-json/wp/v2/users/<ID> は、記事を公開しているユーザーの情報を認証なしで返すためです。そのため、ここには「公開ページに表示してよい項目」だけを登録し、電話番号や社内の連絡先などは入れないようにします。

    プロフィール画面への入力欄の追加と保存は、show_user_profile などのフックで行います。

    includes/profile-fields.php(保存処理の抜粋)

    function curation_tools_save_profile_fields( $user_id ) {
    	check_admin_referer( 'update-user_' . $user_id );
    	if ( ! current_user_can( 'edit_user', $user_id ) ) {
    		return;
    	}
    
    	foreach ( array_keys( curation_tools_profile_fields() ) as $key ) {
    		if ( isset( $_POST[ $key ] ) ) {
    			// サニタイズは register_meta の sanitize_callback が update_user_meta 時に行う。
    			update_user_meta( $user_id, $key, wp_unslash( $_POST[ $key ] ) );
    		}
    	}
    }
    add_action( 'personal_options_update', 'curation_tools_save_profile_fields' );
    add_action( 'edit_user_profile_update', 'curation_tools_save_profile_fields' );

    WordPress 本体もプロフィール画面の nonce(=フォームが正規の画面から送られたことを確認する合言葉)を確認していますが、このフックは他の処理から呼ばれる可能性もあるため、nonce と権限をここでも確認しています。入力欄の表示部分では、値をすべて esc_attr() でエスケープしています(コードは省略)。

    📰 出典:WordPress Developer Resources「show_user_profile」

    監修者を記事ごとに選べるようにする

    投稿メタを登録し、保存時に検証する

    includes/meta.php(抜粋)

    $auth = static function ( $allowed, $meta_key, $post_id ) {
    	return current_user_can( 'edit_post', $post_id );
    };
    
    register_post_meta(
    	'post',
    	'_curation_supervisor_id',
    	array(
    		'type'              => 'integer',
    		'description'       => '監修者のユーザーID(0 は監修者なし)',
    		'single'            => true,
    		'default'           => 0,
    		'show_in_rest'      => true,
    		'sanitize_callback' => 'curation_tools_sanitize_supervisor_id',
    		'auth_callback'     => $auth,
    	)
    );
    
    function curation_tools_sanitize_supervisor_id( $value ) {
    	$user_id = absint( $value );
    	if ( 0 === $user_id ) {
    		return 0;
    	}
    	$user = get_userdata( $user_id );
    	return ( $user && user_can( $user, 'edit_posts' ) ) ? $user_id : 0;
    }

    監修日(_curation_supervised_on)も同じように登録し、YYYY-MM-DD 形式の実在する日付だけを保存します。

    • キーを _ で始める:「保護されたメタ」になり、管理画面の「カスタムフィールド」欄に表示されません。監修者の ID を書き手が直接書き換えることを防ぎます。
    • 監修者として保存できるのは、投稿の編集権限を持つユーザーだけ:存在しないユーザーや購読者の ID が送られてきた場合は 0(監修者なし)にします。エディター以外の経路(REST API の直接呼び出しなど)でも同じ検証が働きます。
    • 編集できるのは、その記事を編集できる人だけ:auth_callback で edit_post の権限を確認します。

    📰 出典:WordPress Developer Resources「register_post_meta()」

    エディターに「監修」パネルを追加する

    投稿の編集画面の右側に入力欄を追加するには、PluginDocumentSettingPanel(=投稿の設定サイドバーにパネルを差し込む仕組み)を使います。

    editor/supervisor-panel.js(抜粋。import 文と、監修日の入力欄・警告の部分を省略)

    function SupervisorPanel() {
    	const postType = useSelect(
    		( select ) => select( editorStore ).getCurrentPostType(),
    		[]
    	);
    	const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );
    
    	if ( 'post' !== postType || ! meta ) {
    		return null;
    	}
    
    	const supervisorId = meta._curation_supervisor_id || 0;
    	const supervisedOn = meta._curation_supervised_on || '';
    	const candidates = window.curationToolsSupervisorCandidates || [];
    
    	return (
    		<PluginDocumentSettingPanel name="curation-supervisor" title="監修">
    			<SelectControl
    				__next40pxDefaultSize
    				__nextHasNoMarginBottom
    				label="監修者"
    				help="実際にこの記事の内容を確認した人だけを選びます。"
    				value={ String( supervisorId ) }
    				options={ [
    					{ label: '(監修者なし)', value: '0' },
    					...candidates.map( ( user ) => ( {
    						label: user.name,
    						value: String( user.id ),
    					} ) ),
    				] }
    				onChange={ ( value ) =>
    					setMeta( {
    						...meta,
    						_curation_supervisor_id: parseInt( value, 10 ) || 0,
    					} )
    				}
    			/>
    		</PluginDocumentSettingPanel>
    	);
    }
    
    registerPlugin( 'curation-supervisor', { render: SupervisorPanel } );

    📰 出典:Block Editor Handbook「PluginDocumentSettingPanel」

    監修者の候補一覧は、REST API ではなく PHP 側で用意して渡しています(includes/meta.php の curation_tools_enqueue_supervisor_panel())。REST API のユーザー一覧は、ユーザー一覧の閲覧権限を持たない編集者には「記事を公開したことがあるユーザー」しか返さないため、まだ記事を書いていない監修者が候補に出てこないからです。候補は get_users() で「投稿の編集権限を持つユーザー」に絞り、ID と表示名だけを渡します。

    このパネルはブロックではないため、第4回の npm run build の設定では自動でビルドされません。そこで、@wordpress/scripts の標準設定に1つエントリー(=ビルドの起点になるファイル)を足す webpack.config.js を置きました。

    webpack.config.js

    const defaultConfig = require( '@wordpress/scripts/config/webpack.config' );
    
    module.exports = {
    	...defaultConfig,
    	entry: {
    		...defaultConfig.entry(),
    		'supervisor-panel': './editor/supervisor-panel.js',
    	},
    };

    (ファイル冒頭の説明コメントは省略しています)

    著者ボックスを動的ブロックで表示する

    表示には、第4回と同じ動的ブロック「著者ボックス」(curation-tools/author-box)を作りました。設定は「表示する人」(記事の著者/記事の監修者)の1つだけで、中身は公開ページの表示時に PHP で組み立てます。

    blocks/author-box/render.php(前半の抜粋)

    $curation_role = ( isset( $attributes['role'] ) && 'supervisor' === $attributes['role'] ) ? 'supervisor' : 'author';
    
    // アーカイブページでも postId(一覧の先頭記事)が渡されるため、「記事ページ」か「クエリーループの中」の
    // ときだけ記事の情報として扱う。
    $curation_in_loop  = isset( $block->context['queryId'] );
    $curation_for_post = is_singular() || $curation_in_loop;
    $curation_post_id  = ( $curation_for_post && isset( $block->context['postId'] ) ) ? (int) $block->context['postId'] : 0;
    $curation_user     = null;
    
    if ( 'supervisor' === $curation_role ) {
    	$curation_user = $curation_post_id ? curation_tools_get_supervisor( $curation_post_id ) : null;
    } elseif ( $curation_post_id ) {
    	$curation_user = get_userdata( (int) get_post_field( 'post_author', $curation_post_id ) );
    } elseif ( is_author() ) {
    	$curation_user = get_queried_object();
    }
    
    if ( ! $curation_user instanceof WP_User ) {
    	return;
    }

    block.json に "usesContext": [ "postId", "postType" ] と書くと、テンプレート上の位置に応じて「今表示している記事の ID」がブロックに渡されます(ブロックコンテキスト)。これにより、同じブロックを記事テンプレートにも著者アーカイブにも置けます。

    📰 出典:Block Editor Handbook「Context」

    後半では、名前(著者アーカイブへのリンク)、肩書き、専門分野、監修日、紹介文、プロフィールURLを、値があるものだけ esc_html() / esc_url() でエスケープして出力します。監修者が設定されていない記事では、監修者の枠自体を出力しません。

    テーマ側では、著者と監修者の2つのブロックをテンプレートパーツにまとめ、3つの記事テンプレートのタグ表示の下に置きました。

    wp-content/themes/curation-child/parts/author-box.html

    <!-- wp:group {"style":{"spacing":{"margin":{"top":"var:preset|spacing|50"}}},"layout":{"type":"default"}} -->
    <div class="wp-block-group" style="margin-top:var(--wp--preset--spacing--50)">
    	<!-- wp:curation-tools/author-box /-->
    
    	<!-- wp:curation-tools/author-box {"role":"supervisor","style":{"spacing":{"margin":{"top":"var:preset|spacing|30"}}}} /-->
    </div>
    <!-- /wp:group -->

    著者アーカイブ(templates/author.html)は、第2回の特集一覧と同じ構成で、ページ上部に著者ボックスを置いています。

    プロフィール画像(アバター)は表示していません。WordPress 標準のアバターは外部サービス(Gravatar)の画像を読み込むため、使う場合はプライバシーポリシーへの記載を含めて運用で判断してください。

    動作確認の方法

    第0回・第2回の手順の後、プラグインをビルド(npm run build)してから確認しました(筆者の環境で確認済みです)。

    docker compose run --rm wpcli wp user meta update 1 curation_job_title '編集長'
    docker compose run --rm wpcli wp post meta update <記事ID> _curation_supervisor_id <監修者のユーザーID>
    curl -s http://localhost:8088/<記事のスラッグ>/ | grep -o 'aria-label="この記事[^"]*"'
    curl -s http://localhost:8088/wp-json/wp/v2/users/1
    • 記事に「この記事を書いた人」のボックスが表示され、肩書き「編集長」と紹介文が出る
    • 監修者を設定した記事でのみ「この記事の監修者」のボックスが表示され、肩書き・専門分野・監修日・プロフィールURLが出る。設定していない記事には出ない
    • /wp-json/wp/v2/users/1 は認証なしで id・name・url・description・link・slug・avatar_urls と、登録した3つのメタだけを返し、メールアドレスは含まれない(slug については「つまずきやすい点」を参照)
    • 監修者に購読者の ID や存在しないユーザーを指定しても 0(なし)として保存され、存在しない日付(2025-02-30)の監修日は保存されない
    • 寄稿者が他人の記事の監修者を REST API で変更しようとすると 403、編集者が他のユーザーのプロフィール項目を変更しようとすると 403
    • プロフィールURLに javascript: を入れると空で保存される
    • 著者アーカイブ(/author/<ユーザー名>/)が 200 で、上部に「著者プロフィール」が表示される
    • エディター(ヘッドレスブラウザで確認)で「監修」パネルが表示され、監修者を選ぶと監修日の入力欄と警告が出て、日付を入れると警告が消え、保存後に投稿メタに反映される

    つまずきやすい点・セキュリティ上の注意

    • REST API に出る項目を意識する:show_in_rest を付けたユーザーメタは公開情報になります。「管理画面で入力できる=社内だけの情報」ではない点に注意してください。
    • ログイン名に近い値が URL と REST API に出る:著者アーカイブの URL と REST API の slug には、ユーザーのスラッグが使われます。スラッグの初期値はログイン名から作られるため、ログイン名とは別の値にしておく運用が安心です。
    • 監修者のアカウント管理:監修者を WordPress のユーザーにする場合、社外の専門家にもアカウントを発行することになります。権限は最小限(寄稿者など)にし、契約終了時の扱いを決めておきます。

    発注者向けメモ:監修者表示は「監修した事実」とセットで依頼する

    著者・監修者の表示そのものは、今回のように比較的小さな実装で実現できます。難しいのは運用です。

    • 監修者を表示するのは、実際に監修した記事だけにする:名前だけを借りる「名義貸し」は、読者の信頼を大きく損ないます。監修の範囲(全文を確認したのか、専門部分だけか)と監修日を記録する運用を決めてください。
    • 表示すれば検索順位が上がる、というものではない:Google は E-E-A-T 自体をランキング要因ではないと説明しています。著者表示は読者に判断材料を渡すためのものと考えましょう。
    • 経歴の正確さと更新:肩書き・資格・所属は本人の確認を取り、変わったときに誰が更新するかを決めます。
    • 社外の監修者の個人情報:公開する項目(名前・肩書き・所属先のURLなど)について本人の同意を取り、公開しない情報はシステムにも登録しない、という線引きをしておきます。

    工数やリスクが増えるのは、監修者をユーザーではなく独自の管理画面で管理したい場合や、1記事に複数の監修者を設定したい場合、監修の依頼・承認のワークフローまでシステム化したい場合です。

    打ち合わせでは、次のように聞いてみてください。

    • 「著者・監修者のプロフィールのうち、REST API などで外部から読める項目はどれですか?」
    • 「監修者を設定していない記事では、監修者欄はどう表示されますか?(空欄ではなく、非表示になりますか)」
    • 「社外の監修者のアカウントにはどの権限を付けますか? 契約終了時の手順はありますか?」

    まとめと次回予告

    第6回では、著者・監修者のプロフィールを登録・表示する仕組みを作りました。

    • E-E-A-T は Google の品質の考え方で、Google 自身がランキングに直接影響する要因ではないと説明している
    • 人に付く情報(肩書き・専門分野)はユーザーメタ、記事ごとの情報(監修者・監修日)は投稿メタに分ける
    • register_meta() で型・サニタイズ・権限を決め、show_in_rest の項目は公開情報として扱う
    • 監修者はエディターのサイドバーから選び、保存時に「投稿の編集権限を持つユーザーか」を検証する
    • 表示は動的ブロック「著者ボックス」をテンプレートパーツに置き、監修者がいない記事では出さない

    次回は「人気記事ランキングと関連記事を小さなプラグインで作る」です。閲覧数をページキャッシュと両立する形で集計し、期間別のランキングと、タグ・特集をもとにした関連記事を表示します。

    この連載の記事一覧

    この記事は連載「WordPressで作るキュレーションメディア」の1回です。連載のほかの回は次のとおりです(連載の一覧ページ)。

    システム制作・運用・保守のお問い合わせはこちら


      よかったらシェアしてね!
      • URLをコピーしました!
      • URLをコピーしました!

      この記事を書いた人

      株式会社THIRD HERO代表取締役 朝野貴朗
      Webシステム開発を中心に、toC向けサービスサイトの運営、ツール開発などを行ってまいりました。

      コメント

      コメント一覧 (1件)

      目次