baserCMS 4系でアイキャッチ画像も使って、OGPタグをいい感じで出力する

baserCMS 4系でアイキャッチ画像も使って、OGPタグをいい感じで出力する

今更ですが、登録するアイキャッチ画像は、1200px × 1200pxを推奨します。(retinaディスプレイに対応するため) Twitter、Facebookなどは、画像中央合わせで、1200px × 1200px  →  600px × 600px  →  幅600px × 高さ315px に縮小、トリミングして表示されるため、アイキャッチ画像にテキストなどをレイアウトする場合は、中央の高さ630px(表示上の中央315px範囲)範囲に収まるように配置すれば見切れません。 正方の画像を推奨するのは、特にトリミングされずそのままのアスペクト比で縮小表示されるSNS(LINEのタイムラインなど)もあるからです。 画像の説明

さて本題です。OGPタグの出力は、実のところもっとシンプルでいいような気もするけれど、せっかくbaserCMSにはコンテンツごとのアイキャッチ登録機能が備わっているのだから、コンテンツごとに個別のアイキャッチがOGP画像に出力された方が楽しいに決まってる。

と言うわけで、コンテンツ毎に登録されたアイキャッチ画像をog:imageタグに出力する、併せて<head>タグ周りのOGPタグをいい感じで出力するコードをまとめてみました。 おそらく多分に冗長的なコードになっているように思いますが。。。

ポイント

  • コンテンツ毎(固定ページ、ブログ、メールフォームなど)に登録したアイキャッチ画像をog:imageタグに出力する
  • ブログ記事の場合、記事自体にアイキャッチ画像があれば(記事内に画像があれば)優先して表示する
  • Twitter、FacebookのOGPタグは、ほぼ対応。
  • prefix属性記述の出し分け

事前準備

  • コンテンツ毎に表示させたいアイキャッチ画像が登録されていない場合に表示するデフォルト画像を以下のようにアップロードしておく。
    https://○○○.com/theme/利用中のテーマ/img/ogp/web_1200.jpg
  • コンテンツ毎に表示させたいアイキャッチ画像がある場合、事前に管理画面の各コンテンツ>設定>オプションから登録する。 画像の説明

詳細

利用中のテーマのレイアウトファイルの<head>タグ内に以下の記述を加える(あるいは、差し替え)。
レイアウトファイルをコンテンツ毎に分けている場合でも、基本は、すべて同様に記述します。

<?php //prefix属性を(HOME、固定ページ)はwebsite、ブログ記事の場合はarticleとなるよう条件分岐========== ?>
<?php if($this->BcBaser->isBlog()): ?>
    <head prefix="og: https://ogp.me/ns# fb: https://ogp.me/ns/fb# article: https://ogp.me/ns/article#">
<?php else: ?>
    <head prefix="og: https://ogp.me/ns# fb: https://ogp.me/ns/fb# website: https://ogp.me/ns/website#">
<?php endif ?>
<?php //基本のタグ出力(ページタイトル、概要、キーワードなど)========== ?>
<?php $this->BcBaser->charset() ?>
<?php $this->BcBaser->title() ?>
<?php $this->BcBaser->metaDescription() ?>
<?php $this->BcBaser->metaKeywords() ?>

<?php
//OGP==========
//HOME、固定ページの場合
$siteName = $siteConfig["name"];
$num = 297; //サイト説明文の文字数制限(本文から297文字抜き出し)
$str = strip_tags($this->BcBaser->getDescription()); //タグ除去
$str = str_replace(array("\r\n","\n","\r"), '', $str); //改行除去
if(mb_strlen($str) >= $num) {
    $description = mb_substr($str, 0,$num-1)."…";
} else {
    $description = $str;
}
$title = $this->BcBaser->getTitle(); //ページタイトル95文字以内
$type ="website"; //(HOME、固定ページ)はwebsite、ブログ記事の場合はarticle
$url =$this->BcBaser->getUri($this->BcBaser->getHere());
$publisher = ""; //Facebookページがある場合、URLあるいはID(FacebookページのFollowボタンを表示できるようになる)
if(isset($this->request->params['Content']['eyecatch']) && $this->request->params['Content']['eyecatch']){
    $eyeCatch = $this->BcUpload->uploadImage('Content.eyecatch',
    $this->request->params['Content']['eyecatch'],
    [
        'imgsize' => '',
        'alt' => '',
        'noimage' => '',
        'output' => 'url',
        'link' => false,
    ]
    ); //固定ページのアイキャッチ画像のURLを出力
    $trim = "?";
    $eyeCatch = $this->BcBaser->getUri(substr($eyeCatch, 0, strcspn($eyeCatch, $trim))); //取得したURLのクエリー文字列(特定文字「?」以降)を除去し、URIで出力
} else {
    $eyeCatch = $this->BcBaser->getThemeUrl();
    $eyeCatch .= "img/ogp/noimage.jpg"; 
}
//ブログ記事の場合(ブログ記事のアイキャッチURIを出力)
if (!empty($post)) {
    $type ="article"; //ブログ記事なのでarticle
    $title = $this->Blog->getPostTitle($post,false)." – ".$siteConfig["formal_name"]; //ページタイトル95文字以内(サイトタイトルを含めない)
    $baseCurrentID = $this->Blog->getcurrentBlogId(); //アイキャッチ画像の保存先Urlを構成するためにブログ実体IDを取得
    $baseCurrentImgUrl = "/files/blog/" . $baseCurrentID . "/blog_posts/";
    if($this->Blog->getEyeCatch($post)) {
        $eyeCatch = $this->BcBaser->getUri( $baseCurrentImgUrl . $post["BlogPost"]["eye_catch"]);
    } else {
        if(isset($this->request->params['Content']['eyecatch']) && $this->request->params['Content']['eyecatch']){
            $eyeCatch = $this->BcUpload->uploadImage('Content.eyecatch',
                        $this->request->params['Content']['eyecatch'],
                        [
                            'imgsize' => '',
                            'alt' => '',
                            'noimage' => '',
                            'output' => 'url',
                            'link' => false,
                        ]
                        ); //固定ページのアイキャッチ画像のURLを出力
            $trim = "?";
            $eyeCatch = $this->BcBaser->getUri(substr($eyeCatch, 0, strcspn($eyeCatch, $trim))); //取得したURLのクエリー文字列(特定文字「?」以降)を除去し、URIで出力
        } else {
            $eyeCatch = $this->BcBaser->getThemeUrl();
            $eyeCatch .= "img/ogp/noimage.jpg";
        }
        }//ブログ記事にアイキャッチ画像がない場合(ブログ設定のアイキャッチ画像のURIを出力)
    } ?>
    <meta property="article:publisher" content="<?php echo $publisher; ?>">
    <meta property="og:type" content="<?php echo $type; ?>">
    <meta property="og:locale" content="ja_JP">
    <meta property="og:site_name" content="<?php echo $siteName; ?>">
    <meta property="og:title" content="<?php echo $title; ?>">
    <meta property="og:description" content="<?php echo $description; ?>">
    <meta property="og:url" content="<?php echo $url; ?>">
    <meta property="og:image" content="<?php echo $eyeCatch; ?>">
    <meta property="og:image:width" content="1200"><!-- /Retinaを意識して倍解像度 -->
    <meta property="og:image:height" content="630"><!-- /Retinaを意識して倍解像度 -->
    <meta name="twitter:card" content="summary"><!-- /Twitter使ってる場合、見せたいカードの種類 -->
    <meta name="twitter:site" content="@ユーザー名"><!-- /Twitterのユーザー名 -->

    <?php//中略。それぞれのテーマごと必要なタグが入ります(トップスライダー、js、cssの読み込み などなど)========== ?>

</head>

ブログ記事にアイキャッチ画像がない場合(記事内に画像があれば、そのURIを出力)

上記コードの「ブログ記事の場合」の記述を以下のようにすると、ブログ記事にアイキャッチ画像がない場合は、記事内の画像をアイキャッチ画像として利用します。画像なければ、デフォルト画像です。
こういうパターンもニーズはあるかもしれません。

//ブログ記事の場合(ブログ記事のアイキャッチURIを出力)
if (!empty($post)) {
    $type ="article"; //ブログ記事なのでarticle
    $title = $this->Blog->getPostTitle($post,false)." – ".$siteConfig["formal_name"]; //ページタイトル95文字以内(サイトタイトルを含めない)
    $baseCurrentID = $this->Blog->getcurrentBlogId(); //アイキャッチ画像の保存先Urlを構成するためにブログ実体IDを取得
    $baseCurrentImgUrl = "/files/blog/" . $baseCurrentID . "/blog_posts/";
    if($this->Blog->getEyeCatch($post)) {
        $eyeCatch = $this->BcBaser->getUri( $baseCurrentImgUrl . $post["BlogPost"]["eye_catch"]);
    } else if(!empty($this->Blog->getPostImg($post))) {
        //ブログ記事にアイキャッチ画像がない場合(記事内に画像があれば、そのURIを出力)
        //画像のリンクを取得する。
        $imgLink = $this->Blog->getPostImg($post);
        //IMGタグのSRCから画像URLを取り出すための正規表現
        $searchPattern = '/<img.*?src=(["\'])(.+?)\1.*?>/i';
            //正規表現とマッチするパターンを探す
            if(preg_match($searchPattern, $imgLink, $imgurl)){
                $eyeCatch = $this->BcBaser->getUri($imgurl[2]);
            }
        } else {
            $eyeCatch = $this->BcUpload->uploadImage('Content.eyecatch',
            $this->request->params['Content']['eyecatch'],
            [
                'imgsize' => '',
                'alt' => '',
                'noimage' => '/img/ogp/noimage.jpg', //theme/利用中のテーマ/img/ogp/内に配置。
                'output' => 'url',
                'link' => false,
            ]
            ); //ブログ設定のアイキャッチ画像のURLを出力
            $trim = "?";
            $eyeCatch = $this->BcBaser->getUri(substr($eyeCatch, 0, strcspn($eyeCatch, $trim))); //取得したURLのクエリー文字列(特定文字「?」以降)し、URIで出力
        } //ブログ記事にアイキャッチ画像、記事内の画像、いずれもない場合(ブログ設定のアイキャッチ画像のURIを出力)
    } ?>

本記事は、baserCMSユーザーズフォーラムに投稿した記事を再校正して作成しました。 また、コードのベースは、@mune_noriさん のOmotenashi-2テーマを参考にさせていただきました。

コメント


コメントする


qCdZIE