Jetpack OGPとTwitterカードタグのカスタマイズ

OGPとは

OGP(The Open Graph Protocol)とは、HTMLのhead 内にサイト情報や記事の概要、イメージ画像等を記述するメタタグの規格のことです

Open Graph protocol
The Open Graph protocol enables any web page to become a rich object in a social graph.

共通のルールに従って記述してあればコンピュータでそのデータを処理できるので Facebook, Twitter, Google+ 等で広く利用されています

WordPressなどのブログ等で記事を書いた時にOGPタグをつけていれば、ツイートやいいねボタンで拡散された時に記事概要やイメージ画像を自分の意図どうりに伝えることが可能となります

※OGPが設定されていないとSNSで拡散するときに自分の意図と異なる概要やイメージが使われる場合があります

最近では、検索上位へ表示されるようにSEO(Serch Engine Optimization)対策を行うだけでなく、SMO(Social Media Optimization)が重要視されています

印象的な画像イメージを設定してあれば、シェアされやすくなり記事を読んでもらえる機会が増えますので必須です (^^)

WordPressでOGPを設定するには

WordPressでOGPを出力するのはプラグインを使うのが簡単です

検索すると様々なプラグインがありますが、Jetpackプラグインを使用しているなら既にOGPを出力しているかもしれません

JetPackプラグインでパブリサイズ共有や共有を有効にすれば自動的に出力されます

※Jetpack を使用していて他のOGPを出力するプラグインを導入するとOGPが2重に出力され正常に機能しない場合があるので注意です

Jetpack の OGP は評判が良くない?

JetpackとOGPを検索するとOGPタグの2重出力等のトラブル等もいろいろあるようで、JetPack のOGP出力を止める方法やプラグインを使わずにテーマの function.php へOGP出力用のコードを貼るだけという記事がたくさん見つかります

JetPack のOGPってそんなにダメなのでしょうか?

おそらくイメージ画像や抜粋がうまく設定されない場合があるときに、誤解された部分もあるのかなと思っています

とてもよく使われているプラグインなので、無効化せずに積極的に使ってもよいと思います

但し、実際に出力されるOGPを見るとちょっと気になる部分もあったので JetPack の OGP 出力と Twitter card 出力タグをカスタマイズしてみました (^^)

<!-- Jetpack Open Graph Tags -->
<meta property="og:type" content="article" />
<meta property="og:title" content="Blog card" />
<meta property="og:url" content="http://xxxxxxxx.jp/test/archives/20141224/blog-card/" />
<meta property="og:description" content="ブログカードテスト OGP データが見つからない場合は title を取得してリンクを作成 ちなみにブックマー&hellip;" />
<meta property="article:published_time" content="2014-12-24T06:15:09+00:00" />
<meta property="article:modified_time" content="2014-12-24T06:19:07+00:00" />
<meta property="article:author" content="http://xxxxxxxx.jp/test/archives/author/admin/" />
<meta property="og:site_name" content="テストサイト" />
<meta property="og:image" content="https://s0.wp.com/i/blank.jpg" />
<meta name="twitter:site" content="@jetpack" />
<meta name="twitter:card" content="summary" />

OGPで気になったポイント

  • og:description
  • article:author
  • og:image

description ですが、ここは記事作成時に 抜粋 を記述していないと意図どおりに出力されない場合がありますので、きちんと抜粋を記述すればOKです

author は、1人で管理しているサイトのブログだと管理者アカウントが出力されてしまう場合があるので出力しない設定を設けたいと思います。但し、パブリサイズ共有で Facebookアカウントと連携している場合は、article:author タグに連携している Facebookアカウントが設定されるので出力することをお勧めします

image は、アイキャッチを設定していないと何が設定されるかわかりません。記事内の複数画像やギャラリーがあると4つまでの画像が登録されます。また、何も画像がない場合は、s0.wp.com/i/blank.jpg というブランク画像がセットされます

Imageのカスタマイズとしては

  • アイキャッチ未設定時は Celtispack プラグインの代替サムネイル機能を使って画像を設定
  • 設定する画像は1枚のみとして、メディア設定のサムネイルの大サイズの画像を優先設定
  • 画像がない投稿記事では image のタグは生成しない

OGPタグの出力について以上のカスタマイズを行いました

ダウンロード

この Jetpack のOGP出力をカスタマイズするプログラムを使いたい方、コードに興味がある方は、WordPress Plugin : Celtispack ページからダウンロードすることが出来ます

次はOGPを設定した後に合わせて設定しておきたい Twitter カードについてです

Twitterカードとは

Twitter で画像イメージ等を表示するには Twitter カードの申請が必要です

Twitterカードに関しては下記参照

Twitterカード
Twitterカードを使用すると、写真や動画などのリッチメディアをツイートに添付してウェブサイトへのトラフィックを促進できます。ウェブページに数行のHTMLを追加するだけで、そのコンテンツへのリンクが含まれるツイートにカードが追加されるようになり、そのツイートを投稿したユーザーのすべてのフォロワーにカードが表示されます。

申請しないと Twitter カード情報のメタタグが出力されていても使われません
申請は、使用するカードタイプ毎に必要なので注意です

申請自体は簡単にできるので忘れずに申請しましょう (^^)

その前に twitter メタタグを意図どおりに出力する必要があります

Jetpack の Twitterカードで気になったポイント

  • twitter:site
  • twitter:card

site が @jetpack になっていますが、ここはWordPress 設定の 共有 Twitter サイトタグ にサイトドメイン保有者の Twitter ユーザー名を入力すればきちんと設定されるようになります

card は、通常 summary タイプが設定されますが、画像サイズが 280×150 以上で投稿タイプが画像だと photo タイプが使われ、それ以外の投稿タイプでは summary_large_image タイプとなります。また、複数画像イメージがあると gallery タイプが用いられるようで、どのカードタイプが設定されるのか条件判断が複雑でわかりづらくなっています

ここをもう少しシンプルに 2タイプに限定するようカスタマイズしました

  • 通常は summary カードタイプ
  • 投稿フォーマットが 画像かギャラリーの場合及び添付ファイル画像の場合のみ summary card with large image カードタイプ

従って投稿フォーマットに標準フォーマットしか使っていない場合には、基本的には添付ファイル画像ページ以外は全て summary card となります

画像がメインの記事で summary card with large image にしたい場合は、投稿フォーマットを画像やギャラリーに設定して下さい

その他

twitter:creator タグが出力が確認出来ていません

Jetpack のプログラムを読んでいくとパブリサイズ共有で Twitte アカウントと連携しているアカウントを記事公開時に同時にツイートしたタイミングで creator データとして保存されるようなのですが、何故か作成されていません プログラムを読み間違えているかも (^_^;)

OGPカスタマイズ出力の確認

ここまででおおよそOGPとTwitterカードについて解かったと思いますが、Celtispack ver1.2.0 をインストールして Jetpack OGP Extended 機能を有効にしてみましょう

試しに、author 情報の出力を止め、代替サムネイル機能を有効にします

ギャラリーページのOGP出力を見てみます

<!-- Jetpack Open Graph Tags customized by Celtispack -->
<meta property="og:type" content="article" />
<meta property="og:title" content="Celtis-one テーマでのギャラリーデモ" />
<meta property="og:url" content="http://celtislab.net/archives/20140108/celtis-one-gallery-demo/" />
<meta property="og:description" content="Celtis-oneテーマでギャラリーを使用した時にどんな感じになるかを紹介しています
JetPackのタイルギャラリーとカルーセルを使うといい感じのギャラリーサイトを作成することが出来ます..." />
<meta property="article:published_time" content="2014-01-08T10:17:57+00:00" />
<meta property="article:modified_time" content="2014-11-18T01:47:21+00:00" />
<meta property="og:site_name" content="セルティスラボ" />
<meta property="og:image" content="http://celtislab.net/wp-content/uploads/PAP_0012-960x720.jpg" />
<meta name="twitter:site" content="@eno_celtislab" />
<meta name="twitter:image:src" content="http://celtislab.net/wp-content/uploads/PAP_0012-960x720.jpg?w=640" />
<meta name="twitter:card" content="summary_large_image" />

意図したとおりにOGP,Twitterカードのメタタグが出力されているようです (^^)

Twitterカードの申請

実際に登録する手順等は下記記事で軽妙な文言で紹介されているのが参考になります (^^)

Twitter Cardsの種類を変更し、ついでにアナリティクスを確認する
少し前からこのブログ、さりげなく「Twitter Cards」に対応していました。Twitter CardsとはTwitterでURL付きの記事を投稿したとき、&

今回申請するのは2タイプ

Summary card と summary card with large image です

Twitterにログインして下記サイトを開きます

https://cards-dev.twitter.com/validator

まずは summary card から

1.Summary card タイプとなる投稿記事のURLを入力

TwitterCard_申請1

自分の思っているとおりに表示されていれば申請

そうでなければ、OGPやTwitterカードのメタタグを再確認しましょう

他のプラグインと干渉しているかもしれません

2.Request Approval をクリックして申請

TwitterCard_申請2

*印の項目にサイト情報を入力して request Approval をクリック

Mark my cards as containing sensitive content は通常はチェックなし

不適切な内容の画像や動画に関する設定のようです

Media settings and best practices

What are Tweet media settings?

Your Tweet media settings allow you to label your media for the appropriate viewers, and select whose media will display on your Twitter homepage.&n

 3.承認保留中

TwitterCard_申請3

申請がまだ承認されていないことを表しています
3分程待ってから再度 preview card をクリックします

 4.申請終了

TwitterCard_申請4

承認されたようです (^^)

続けて summary card with large image の申請します

summary card with large image カードタイプにしているので条件にあう画像やギャラリー投稿タイプのページを入れてみます

TwitterCard_申請5

以下同様に申請作業を進めます

以上で2つのカードタイプが使えるようになりました

※JetPack 標準状態だと photo card や gallery card も使用しているので、代替サムネイル機能を有効にしていない場合はそれの追加登録も!

 

その他

facebookについて

私自身は facebook を利用していないのですが、Jetpack3.3 のOGP では、fd:admin メタタグはホームページ/フロントページでしか出力されていないようです

投稿ページは、パブリサイズ共有でFacebookに連携していると、公開と同時に連携しているFacebookアカウントで投稿され、そのアカウントが OGPの article:author タグに設定されるようです

投稿ページの article:author にFacebookアカウントが設定されていれば、fd:admin がなくてもいいのかどうか今ひとつわからないのですが、何か問題があるようなら別途 fd:admin タグを出力させる必要があるかも知れません

何分にも Facebook 利用していないもので m(__)m

問題ある、問題なかった等、コメントをいただけると嬉しいです (^^)

 

プログラムについて

今回カスタマイズしたプログラムについても少し紹介します

Jetpack の OGPを無効化するプログラムとして下記のようなコードが知られています

add_filter( 'jetpack_enable_open_graph', '__return_false', 99);

無効化ではなくカスタマイズしたい場合は、__return_false でなくここにフィルターフックする関数を設定すればOKです

Jetpackでの元の処理は function.opengraph.php ファイルの jetpack_og_tags() 関数に記述されているので、これをコピーしてカスタマイズする関数を作成していきます

元のコードを少し修正するだけなので、それほど難しくはありません

一部分ですがこんな感じです

    //Jetpack の jetpack_og_tags() 置き換え関数
    //※ jetpack_og_tags() が動作しないよう false でリターンすること
    function og_tags() {
        
        $og_output = "\n<!-- Jetpack Open Graph Tags customized by Celtispack -->\n";
        
        $tags = array();

        $image_width        = absint( apply_filters( 'jetpack_open_graph_image_width', 200 ) );
        $image_height       = absint( apply_filters( 'jetpack_open_graph_image_height', 200 ) );
        $description_length = 197;

        if ( is_home() || is_front_page() ) {
            $site_type              = get_option( 'open_graph_protocol_site_type' );
            $tags['og:type']        = ! empty( $site_type ) ? $site_type : 'website';
            $tags['og:title']       = get_bloginfo( 'name' );
            $tags['og:description'] = get_bloginfo( 'description' );

            $front_page_id = get_option( 'page_for_posts' );
            if ( $front_page_id && is_home() )
                $tags['og:url'] = get_permalink( $front_page_id );
            else
                $tags['og:url'] = home_url( '/' );

            // Associate a blog's root path with one or more Facebook accounts
            $facebook_admins = get_option( 'facebook_admins' );
            if ( ! empty( $facebook_admins ) )
                $tags['fb:admins'] = $facebook_admins;

        } else if ( is_author() ) {
            if(empty($this->options['og_author_off'])){
                $tags['og:type'] = 'profile';

                $author = get_queried_object();

                $tags['og:title']           = $author->display_name;
                if ( ! empty( $author->user_url ) ) {
                    $tags['og:url']     = $author->user_url;
                } else {
                    $tags['og:url']     = get_author_posts_url( $author->ID );
                }
                $tags['og:description']     = $author->description;
                $tags['profile:first_name'] = get_the_author_meta( 'first_name', $author->ID );
                $tags['profile:last_name']  = get_the_author_meta( 'last_name', $author->ID );
            }
        } else if ( is_singular() ) {
            global $post;
            $data = $post; // so that we don't accidentally explode the global

            $tags['og:type']        = 'article';
            $tags['og:title']       = empty( $data->post_title ) ? ' ' : wp_kses( $data->post_title, array() ) ;
            $tags['og:url']         = get_permalink( $data->ID );
            if ( !post_password_required() )
                $tags['og:description'] = ! empty( $data->post_excerpt ) ? preg_replace( '@https?://[\S]+@', '', strip_shortcodes( wp_kses( $data->post_excerpt, array() ) ) ): wp_trim_words( preg_replace( '@https?://[\S]+@', '', strip_shortcodes( wp_kses( $data->post_content, array() ) ) ) );
            if ( empty( $tags['og:description'] ) )
                $tags['og:description'] = __('Visit the post for more.', 'jetpack');
            $tags['article:published_time'] = date( 'c', strtotime( $data->post_date_gmt ) );
            $tags['article:modified_time'] = date( 'c', strtotime( $data->post_modified_gmt ) );
            //管理者名が出力されてしまう場合もあるので著者情報は出力しない条件を設ける (^^)
            if(empty($this->options['og_author_off'])){
                if ( post_type_supports( get_post_type( $data ), 'author' ) && isset( $data->post_author ) ) {
                    $publicize_facebook_user = get_post_meta( $data->ID, '_publicize_facebook_user', true );
                    if ( ! empty( $publicize_facebook_user ) ) {
                        $tags['article:author'] = esc_url( $publicize_facebook_user );
                    } else {
                        $tags['article:author'] = get_author_posts_url( $data->post_author );
                    }
                }
            }
        }

        // Allow plugins to inject additional template-specific open graph tags
        $tags = apply_filters( 'jetpack_open_graph_base_tags', $tags, compact( 'image_width', 'image_height' ) );

        if ( empty( $tags ) )
            return false;

        $tags['og:site_name'] = get_bloginfo( 'name' );

        if ( !post_password_required() ) {
            //イメージ取得に Celtispack 代替サムネイル処理を使用する(要 Thumbnail optimize 代替サムネイル機能の有効化)
            if(!empty($this->options['og_altthumb'])){
                if ( is_singular() ) {
                    $image = null;
                    if ( is_attachment() ) {
                        if ( $post->post_mime_type == 'image/jpeg'  || $post->post_mime_type == 'image/png' || $post->post_mime_type == 'image/gif' ) {
                            $imagesrc = wp_get_attachment_image_src($post->ID, 'large');
                            if(!empty($imagesrc[0]))
                                $image = esc_url($imagesrc[0]);
                        }
                    }
                    else { //代替サムネイルを有効にしたいので wp_get_attachment_image_src でなく get_the_post_thumbnail を使用
                        $thumbnail = get_the_post_thumbnail($post->ID, 'large', array() );
                        if(!empty($thumbnail)) {
                            preg_match('#<img.+?src=[\'\"](https?://.+?)(\.png|\.gif|\.jpe|\.jpeg|\.jpg)#', $thumbnail, $match);
                            if(!empty($match[2]))
                                $image = esc_url($match[1].$match[2]);
                        }
                    }
                    //画像がない場合は og:image は設定しない 
                    if(!empty($image)) {
                        $tags['og:image'] = $image;
                    }
                }
                elseif ( is_home() || is_front_page() ) {
                    $simage = '';
                    // First fall back, blavatar
                    if ( function_exists( 'blavatar_domain' ) ) {
                        $blavatar_domain = blavatar_domain( site_url() );
                        if ( blavatar_exists( $blavatar_domain ) )
                            $simage[] = blavatar_url( $blavatar_domain, 'img', $width );
                    }
                    // Second fall back, Site Logo
                    if ( empty( $simage ) && ( function_exists( 'jetpack_has_site_logo' ) && jetpack_has_site_logo() ) ) {
                        $simage[] = jetpack_get_site_logo( 'url' );
                    }
                    // Third fall back, Site Icon
                    if ( empty( $simage ) && ( function_exists( 'jetpack_has_site_icon' ) && jetpack_has_site_icon() ) ) {
                        $simage[] = jetpack_site_icon_url( null, '512' );
                    }
                    // WebClip icon
                    if ( empty( $simage ) && !empty($this->options['webclipicon'] ) ) {
                        $simage[] = esc_url( $this->options[ 'webclipicon' ]);
                    }
                    if ( !empty( $simage )){
                        $tags['og:image'] = $simage[0];
                    }
                }
            }
            else {
                //Jetpack オリジナルだときちんとアイキャッチを指定していれば問題ないが 
                //wp_get_attachment_image_src 使用で代替サムネイル取得できずに記事中の複数画像が設定される場合あり
                $tags['og:image']     = $this->og_get_image( $image_width, $image_height );
            }
        }

        // Facebook whines if you give it an empty title
        if ( empty( $tags['og:title'] ) )
            $tags['og:title'] = __( '(no title)', 'jetpack' );

        // Shorten the description if it's too long
        if ( isset( $tags['og:description'] ) ) {
            $tags['og:description'] = strlen( $tags['og:description'] ) > $description_length ? mb_substr( $tags['og:description'], 0, $description_length ) . '...' : $tags['og:description'];
        }

        // Add any additional tags here, or modify what we've come up with
        //Twitter Card 等の追加のタグを処理する為のフィルター 参照 class.jetpack-twitter-card.php 
        $tags = apply_filters( 'jetpack_open_graph_tags', $tags, compact( 'image_width', 'image_height' ) );

        // secure_urls need to go right after each og:image to work properly so we will abstract them here
        $secure = $tags['og:image:secure_url'] = ( empty( $tags['og:image:secure_url'] ) ) ? '' : $tags['og:image:secure_url'];
        unset( $tags['og:image:secure_url'] );
        $secure_image_num = 0;

        foreach ( (array) $tags as $tag_property => $tag_content ) {
            // to accommodate multiple images
            $tag_content = (array) $tag_content;
            $tag_content = array_unique( $tag_content );

            foreach ( $tag_content as $tag_content_single ) {
                if ( empty( $tag_content_single ) )
                    continue; // Don't ever output empty tags
                $og_tag = sprintf( '<meta property="%s" content="%s" />', esc_attr( $tag_property ), esc_attr( $tag_content_single ) );
                $og_output .= apply_filters( 'jetpack_open_graph_output', $og_tag );
                $og_output .= "\n";

                if ( 'og:image' == $tag_property ) {
                    if ( is_array( $secure ) && !empty( $secure[$secure_image_num] ) ) {
                        $og_tag = sprintf( '<meta property="og:image:secure_url" content="%s" />', esc_url( $secure[ $secure_image_num ] ) );
                        $og_output .= apply_filters( 'jetpack_open_graph_output', $og_tag );
                        $og_output .= "\n";
                    } else if ( !is_array( $secure ) && !empty( $secure ) ) {
                        $og_tag = sprintf( '<meta property="og:image:secure_url" content="%s" />', esc_url( $secure ) );
                        $og_output .= apply_filters( 'jetpack_open_graph_output', $og_tag );
                        $og_output .= "\n";
                    }
                    $secure_image_num++;
                }
            }
        }
        echo $og_output;
        return false;
    }

また、同様に Twitteカードの処理部分もカスタマイズすればOKです

全体のコードを見たい方は、 celtispacl/module/ogp-tags/ogp-tags.php を参照して下さい

 

以上

JetpackのOGPをカスタマイズするプログラムを紹介しました

まだ不具合等があるかもしれませんが、よろしければ試してみてください (^^)

 


まとめ記事紹介

search star user home refresh tag chevron-left chevron-right exclamation-triangle calendar comment folder thumb-tack navicon angle-double-up angle-double-down angle-up angle-down quote-left googleplus facebook instagram twitter rss