かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

WordPress OGP 情報を自前で出力してみる

WordPress で OGP の情報を出力するには All in One SEO などのプラグインを使えば実現できるのですが、WordPress からしばらく離れていたこともあり WordPress 独特のプラグインGitHub にない場合も多くスター数やどれが現段階でのベストプラクティスなの判断できない・セキュリティの問題がどうなっているのか判らないという事があり素振りも兼ねて自前で実装してみたのでメモ

OGP に必要なメタタグ

<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
<title>ページのタイトル</title>
<meta property="og:site_name" content="サイト名" />
<meta property="og:title" content="ページのタイトル" />
<meta property="og:type" content="ページの種類" />
<meta property="og:url" content="ページのURL" />
<meta property="og:image" content="サムネイル画像のURL" />
<meta property="og:description" content="ページのディスクリプション" />
<meta property="fb:app_id" content="App-ID(15文字の半角数字)" /> <!-- for Facebook -->
<meta name="twitter:card" content="Twitterカードの種類" /> <!-- for Twitter -->

cf. Facebook・TwitterのOGP設定方法まとめ|ferret

仕様

  • WordPress: v6.0
  • og:title … 現在のページのタイトル
  • og:typewebsite, 投稿の場合は article にする
  • og:url … 現在のページの URL
  • og:image … 投稿、固定ページでサムネイルがあればサムネイル。なければデフォルト画像。
  • og:site_name … 固定値 (サイト名)
  • og:description … 抜粋があれば抜粋。なければ本文から生成。それもなければデフォルト値
  • fb:app_idFacebook のアプリID なので固定値
  • twitter:card … 投稿の時は summary, 固定ページの場合は summary_large_image

※ コードを見やすくするために冗長に書いています

og:title 現在のページのタイトルを取得する

ページのタイトルを return する wp_get_document_title() を使って取得する
固定値のサイト名は get_bloginfo('name')管理画面 > 一般 > サイトのタイトル に指定されている値にする

<?php // functions.php
function mt_ogp() {
  $siteName = get_bloginfo('name');
  // ページタイトル
  $title = wp_get_document_title();

$ogp = <<< EOM
<meta property="og:site_name" content="{$siteName}" />
<meta property="og:title" content="{$title}" />
EOM;
  
  echo $ogp;
}

タイトル自体のカスタマイズは pre_get_document_title のようなフィルターを使うことで head 内の title と og:title を同じにすることができる

cf.

og:type ページのタイプ

website, 投稿の場合は article にする

is_singular() は投稿ページ以外に固定ページ is_page(), 添付ファイルページ is_attachment() を含むので is_single() を使うのが良さそう

<?php // functions.php
function mt_ogp() {
  $siteName = get_bloginfo('name');
  // ページタイトル
  $title = wp_get_document_title();
  // ページタイプ
  $pageType = 'website';
  if ( is_single() ) {
    $pageType = 'article';
  }

$ogp = <<< EOM
<meta property="og:site_name" content="{$siteName}" />
<meta property="og:title" content="{$title}" />
<meta name="og:type" content="{$ogpType}">
EOM;
  
  echo $ogp;
}

og:url 現在のページの URL

WordPress の URL は global の $post などを使って取得することができるが、投稿がない場合やカテゴリーの投稿が 0 件の時 $postNULL になったり、アーカイブページの $postアーカイブに含まれる最初の投稿だったりで分岐や条件分けがかなり複雑になってしまうので $_SERVER を使って現在の URL を取得するようにした

<?php // functions.php
function mt_ogp() {
  $siteName = get_bloginfo('name');
  // ページタイトル
  $title = wp_get_document_title();
  // ページタイプ
  $pageType = 'website';
  if ( is_single() ) {
    $pageType = 'article';
  }
  // 現在の URL
  $permalink = (is_ssl() ? 'https' : 'http') . '://' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];

$ogp = <<< EOM
<meta property="og:site_name" content="{$siteName}" />
<meta property="og:title" content="{$title}" />
<meta name="og:type" content="{$ogpType}">
<meta property="og:url" content="{$permalink}" />
EOM;
  
  echo $ogp;
}

og:image

投稿、固定ページでサムネイルがあればサムネイル。なければデフォルト画像。

サムネイルを設定できるページは is_singular() (is_single() + is_page() + is_attachment()) なので、これが true の時にサムネイルの有無をチェックする
サムネイル画像の URL は wp_get_attachment_image_src($attachment_id, $size); で取得できる。デフォルトでは thumbnail が取得されるので OGP なら largefull を指定すれば良さそう

<?php // functions.php
define('OGP_IMAGE', get_home_url() . "/ogp.png");
function mt_ogp() {
  global $post;
  $siteName = get_bloginfo('name');
  // ページタイトル
  $title = wp_get_document_title();
  // ページタイプ
  $pageType = 'website';
  if ( is_single() ) {
    $pageType = 'article';
  }
  // 現在の URL
  $permalink = (is_ssl() ? 'https' : 'http') . '://' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
  // OGP Image
  $ogpImage = OGP_IMAGE;
  if ( is_singular() ) {
    $thumbnail = wp_get_attachment_image_src(
      get_post_thumbnail_id($post->ID), 'full'
    );
    $ogpImage = $thumbnail[0] ?: OGP_IMAGE;
  }

$ogp = <<< EOM
<meta property="og:site_name" content="{$siteName}" />
<meta property="og:title" content="{$title}" />
<meta name="og:type" content="{$ogpType}">
<meta property="og:url" content="{$permalink}" />
<meta property="og:image" content="{$ogpImage}" />
EOM;
  
  echo $ogp;
}

cf. WordPress アップロードした画像を width, height 属性無しで取得したい - かもメモ

og:description ディスクリプション

抜粋があれば抜粋。なければ本文から生成。それもなければデフォルト値

抜粋は global オブジェクトの $post から $post->post_excerpt, 本文は $post->post_content で取得できる。本文の場合はタグの除去を行う必要がある
アーカイブページや 404 ページ、検索結果などはデフォルト値を返すようにする

<?php // functions.php
define("OGP_IMAGE", get_home_url() . "/ogp.png");
define("DESCRIPTION", "デフォルトのディスクリプション");
// $post から description を返す関数
function get_my_descriptiom_by_post($post, $limit = 140, $more = '...') {
  $summary = $post->post_excerpt;
  if ( empty($summary) ) {
    $content = apply_filters('the_content', $post->post_content);
    // タグの除去
    $summary = strip_tags($content);
    $summary = str_replace(array("\r\n","\n","\r"), ''
  }

  if ( empty($summary) ) { return NULL; }

  $description = wp_trim_words($summary, $limit, $more);
  return $description; 
}

function mt_ogp() {
  global $post;
  $siteName = get_bloginfo('name');
  // ページタイトル
  $title = wp_get_document_title();
  // ページタイプ
  $pageType = 'website';
  if ( is_single() ) {
    $pageType = 'article';
  }
  // 現在の URL
  $permalink = (is_ssl() ? 'https' : 'http') . '://' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
  // OGP Image
  $ogpImage = OGP_IMAGE;
  if ( is_singular() ) {
    $thumbnail = wp_get_attachment_image_src(
      get_post_thumbnail_id($post->ID), 'full'
    );
    $ogpImage = $thumbnail[0] ?: OGP_IMAGE;
  }
  // description
  $description = DESCRIPTION;
  if ( is_singular() ) {
    $description = get_my_descriptiom_by_post($post);
  }
  if ( empty($description) || empty($post) || is_404() ) {
    $description = DESCRIPTION;  
  }

$ogp = <<< EOM
<meta property="og:site_name" content="{$siteName}" />
<meta property="og:title" content="{$title}" />
<meta name="og:type" content="{$ogpType}">
<meta property="og:url" content="{$permalink}" />
<meta property="og:image" content="{$ogpImage}" />
<meta property="og:description" content="{$description}" />
EOM;
  
  echo $ogp;
}

Facebook fb:app_id, Twitter twitter:card 用の設定

fb:app_idFacebook で取得するアプリの ID なので固定値を使えば OK twitter:card は 投稿の時は summary, 固定ページの場合は summary_large_image にする

<?php // functions.php
define("OGP_IMAGE", get_home_url() . "/ogp.png");
define("DESCRIPTION", "デフォルトのディスクリプション");
define("FACEBOOK_APP_ID", "APP ID");
// 略
function mt_ogp() {
  global $post;
  $siteName = get_bloginfo('name');
  // ページタイトル
  $title = wp_get_document_title();
  // ページタイプ
  $pageType = 'website';
  if ( is_single() ) {
    $pageType = 'article';
  }
  // 現在の URL
  $permalink = (is_ssl() ? 'https' : 'http') . '://' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
  // OGP Image
  $ogpImage = OGP_IMAGE;
  if ( is_singular() ) {
    $thumbnail = wp_get_attachment_image_src(
      get_post_thumbnail_id($post->ID), 'full'
    );
    $ogpImage = $thumbnail[0] ?: OGP_IMAGE;
  }
  // description
  $description = DESCRIPTION;
  if ( is_singular() ) {
    $description = get_my_descriptiom_by_post($post);
  }
  if ( empty($description) || empty($post) || is_404() ) {
    $description = DESCRIPTION;  
  }
  // Facebook App ID
  $fbAppID =  FACEBOOK_APP_ID;
  // Twitter card
  $cardType = 'summary_large_image';
  if ( is_single() ) {
    $cardType = 'summary';
  }

$ogp = <<< EOM
<meta property="og:site_name" content="{$siteName}" />
<meta property="og:title" content="{$title}" />
<meta name="og:type" content="{$ogpType}">
<meta property="og:url" content="{$permalink}" />
<meta property="og:image" content="{$ogpImage}" />
<meta property="og:description" content="{$description}" />
<meta property="fb:app_id" content={$fbAppID} />
<meta name="twitter:card" content="{$cardType}" />
EOM;
  
  echo $ogp;
}

cf.

所管

なんとなくいい感じに OGP のメタタグを出力できるようになりました!
WordPress の全部を functions.php にマージして実行する仕組みにいまいち慣れない…


[参考]

おじP… ネタ切れ…