先日、自作のWordpressテーマをAMP化しました。
その時に、一番苦労したのが、Wordpress本文にある「AMP仕様から外れた記述」を無理やりにでも「AMP仕様に沿った記述」に変更する処理です。
で、自分のサイトも、今回使用する「本文AMP化関数」を使用するようになってから、Google Search Consoleのエラーもなくなったので、備忘録がてら書き残しておこうと思います。
目次
投稿本文をAMP化する関数
とりあえず、投稿本文自体をAMP化するのに必要なコードは以下になります。functions.php等に貼り付けて利用します。
//AMP判別関数 //今回は、?amp=1パラメーターを使用(環境によっては変更する必要があるかも) function is_amp(){ //AMPチェック $is_amp = false; if ( empty($_GET['amp']) ) { return false; } //ampのパラメーターが1かつ投稿ページの //かつsingleページのみ$is_ampをtrueにする if(is_single() && $_GET['amp'] === '1' ){ $is_amp = true; } return $is_amp; } //AMP用にコンテンツを変換する function convert_content_to_amp_sample($the_content){ if ( !is_amp() ) { return $the_content; } //C2A0文字コード(UTF-8の半角スペース)を通常の半角スペースに置換 $the_content = str_replace('\xc2\xa0', ' ', $the_content); //style属性を取り除く $the_content = preg_replace('/ +style=["][^"]*?["]/i', '', $the_content); $the_content = preg_replace('/ +style=[\'][^\']*?[\']/i', '', $the_content); //target属性を取り除く $the_content = preg_replace('/ +target=["][^"]*?["]/i', '', $the_content); $the_content = preg_replace('/ +target=[\'][^\']*?[\']/i', '', $the_content); //onclick属性を取り除く $the_content = preg_replace('/ +onclick=["][^"]*?["]/i', '', $the_content); $the_content = preg_replace('/ +onclick=[\'][^\']*?[\']/i', '', $the_content); //FONTタグを取り除く $the_content = preg_replace('/<font[^>]+?>/i', '', $the_content); $the_content = preg_replace('/<\/font>/i', '', $the_content); //カエレバ・ヨメレバのAmazon商品画像にwidthとhightを追加する $the_content = preg_replace('/ src="http:\/\/ecx.images-amazon.com/i', ' width="75" height="75" sizes="(max-width: 75px) 75vw, 75px" src="https://images-fe.ssl-images-amazon.com', $the_content); //カエレバ・ヨメレバのAmazon商品画像にwidthとhightを追加する(SSL用) $the_content = preg_replace('/ src="https:\/\/images-fe.ssl-images-amazon.com/i', ' width="75" height="75" sizes="(max-width: 75px) 75vw, 75px" src="https://images-fe.ssl-images-amazon.com', $the_content); //カエレバ・ヨメレバの楽天商品画像にwidthとhightを追加する $the_content = preg_replace('/ src="http:\/\/thumbnail.image.rakuten.co.jp/i', ' width="75" height="75" sizes="(max-width: 75px) 75vw, 75px" src="http://thumbnail.image.rakuten.co.jp', $the_content); //カエレバ・ヨメレバのYahoo!ショッピング商品画像にwidthとhightを追加する $the_content = preg_replace('/ src="http:\/\/item.shopping.c.yimg.jp/i', ' width="75" height="75" sizes="(max-width: 75px) 75vw, 75px" src="http://item.shopping.c.yimg.jp', $the_content); //画像タグをAMP用に置換 $the_content = preg_replace('/<img/i', '<amp-img', $the_content); // Twitterをamp-twitterに置換する(埋め込みコード) $pattern = '/<blockquote class="twitter-tweet".*?>.+?<a href="https:\/\/twitter.com\/.*?\/status\/(.*?)">.+?<\/blockquote>.*?<script async src="\/\/platform.twitter.com\/widgets.js" charset="utf-8"><\/script>/is'; $append = '<p><amp-twitter width=592 height=472 layout="responsive" data-tweetid="$1"></amp-twitter></p>'; $the_content = preg_replace($pattern, $append, $the_content); // vineをamp-vineに置換する $pattern = '/<iframe[^>]+?src="https:\/\/vine.co\/v\/(.+?)\/embed\/simple".+?><\/iframe>/is'; $append = '<p><amp-vine data-vineid="$1" width="592" height="592" layout="responsive"></amp-vine></p>'; $the_content = preg_replace($pattern, $append, $the_content); // Instagramをamp-instagramに置換する $pattern = '/<blockquote class="instagram-media".+?"https:\/\/www.instagram.com\/p\/(.+?)\/".+?<\/blockquote>/is'; $append = '<p><amp-instagram layout="responsive" data-shortcode="$1" width="592" height="592" ></amp-instagram></p>'; $the_content = preg_replace($pattern, $append, $the_content); // YouTubeを置換する(埋め込みコード) $pattern = '/<iframe.+?src="https:\/\/www.youtube.com\/embed\/(.+?)(\?feature=oembed)?".*?><\/iframe>/is'; $append = '<amp-youtube layout="responsive" data-videoid="$1" width="800" height="450"></amp-youtube>'; $the_content = preg_replace($pattern, $append, $the_content); // iframeをamp-iframeに置換する $pattern = '/<iframe/i'; $append = '<amp-iframe layout="responsive"'; $the_content = preg_replace($pattern, $append, $the_content); $pattern = '/<\/iframe>/i'; $append = '</amp-iframe>'; $the_content = preg_replace($pattern, $append, $the_content); //スクリプトを除去する $pattern = '/<script.+?<\/script>/is'; $append = ''; $the_content = preg_replace($pattern, $append, $the_content); return $the_content; } add_filter('the_content','convert_content_to_amp_sample', 999999999);//なるべく後で行う
このコードをfunctions.phpに貼り付けで、投稿ページURLに「?amp=1」もしくは「&=1」を付加してブラウザで開けば、とりあえず投稿ページの本文だけはある程度AMP化された状態で出力されると思います。
参考 【WordPress】プラグイン無しでAMP(Accelerated Mobile Pages)に対応にする手順 | Creator Clip
コードを簡単に説明
以下では、先程紹介したコードについて簡単に説明したいと思います。
AMP判別関数
is_amp()関数は、AMP判別関数となっています。
//AMP判別関数 //今回は、?amp=1パラメーターを使用(環境によっては変更する必要があるかも) function is_amp(){ //AMPチェック $is_amp = false; if ( empty($_GET['amp']) ) { return false; } //ampのパラメーターが1かつ投稿ページの //かつsingleページのみ$is_ampをtrueにする if(is_single() && $_GET['amp'] === '1' ){ $is_amp = true; } return $is_amp; }
single(投稿)ページかつ、ampパラメータに1が入っているかを確認して、現在表示しているページがAMPページかどうかを判別します。
余計なHTML属性を取り除く
//style属性を取り除く $the_content = preg_replace('/ +style=["][^"]*?["]/i', '', $the_content); $the_content = preg_replace('/ +style=[\'][^\']*?[\']/i', '', $the_content); //target属性を取り除く $the_content = preg_replace('/ +target=["][^"]*?["]/i', '', $the_content); $the_content = preg_replace('/ +target=[\'][^\']*?[\']/i', '', $the_content); //onclick属性を取り除く $the_content = preg_replace('/ +onclick=["][^"]*?["]/i', '', $the_content); $the_content = preg_replace('/ +onclick=[\'][^\']*?[\']/i', '', $the_content);
上記のコード部分で、AMPで使用できないHTML属性を取り除いています。
とりあえず、現状以下の属性を除外しています。
- style
- target
- onclick
使用できないHTML要素を取り除く
//FONTタグを取り除く $the_content = preg_replace('/<font[^>]+?>/i', '', $the_content); $the_content = preg_replace('/<\/font>/i', '', $the_content);
AMPで使用できないHTML要素も取り除きます。
ヨメレバ・カエレバの画像にwidth、height属性を加える
多くのブログなどで利用されている、ヨメレバやカエレバブログパーツの商品サムネイルもできる限り表示するように置換をしました。
//カエレバ・ヨメレバのAmazon商品画像にwidthとhightを追加する $the_content = preg_replace('/ src="http:\/\/ecx.images-amazon.com/i', ' width="75" height="75" sizes="(max-width: 75px) 75vw, 75px" src="https://images-fe.ssl-images-amazon.com', $the_content); //カエレバ・ヨメレバのAmazon商品画像にwidthとhightを追加する(SSL用) $the_content = preg_replace('/ src="https:\/\/images-fe.ssl-images-amazon.com/i', ' width="75" height="75" sizes="(max-width: 75px) 75vw, 75px" src="https://images-fe.ssl-images-amazon.com', $the_content); //カエレバ・ヨメレバの楽天商品画像にwidthとhightを追加する $the_content = preg_replace('/ src="http:\/\/thumbnail.image.rakuten.co.jp/i', ' width="75" height="75" sizes="(max-width: 75px) 75vw, 75px" src="http://thumbnail.image.rakuten.co.jp', $the_content); //カエレバ・ヨメレバのYahoo!ショッピング商品画像にwidthとhightを追加する $the_content = preg_replace('/ src="http:\/\/item.shopping.c.yimg.jp/i', ' width="75" height="75" sizes="(max-width: 75px) 75vw, 75px" src="http://item.shopping.c.yimg.jp', $the_content);
上記コードでは、imgに対してAMPで必要なwidth、heightを付け加えています(ヨメレバやカエレバの出力タグにはサイズ属性がないので)。
ただし、商品のサムネイル画像は、縦長か横長画像なのか等のサイズ情報はありません。なので、サイズ情報は縦75px、横75px一律にしています。
ちなみに、こういったブログパーツなどは、前述のstyle属性を取り除く処理によって、インラインスタイルも取り除かれて表示が崩れると思います。
そういった場合は、ブログパーツのクラスに対して、以下のようなスタイルを指定してやる必要があるかもしれません。
/************************************ ** カエレバ・ヨメレバ ************************************/ .booklink-box, .kaerebalink-box, .pochireba { border: medium double #ccc; border-radius: 5px; font-size: small; margin: 20px auto; overflow: hidden; padding: 25px 25px 18px; } .kaerebalink-image, .booklink-image{ width: 85px; float: left; margin-top: 4px; } .kaerebalink-link1 amp-img{ display: none; } .booklink-name, .kaerebalink-name { font-size: 16px; line-height: 1.3em; } .kaerebalink-powered-date, .booklink-powered-date{ font-size: small; } .kaerebalink-link1 div, .booklink-link2 div { background: #ffffff linear-gradient(to bottom, #ffffff 5%, #f6f6f6 100%) repeat scroll 0 0; border: 1px solid #ddd; border-radius: 6px; box-sizing: border-box; cursor: pointer; display: inline-block; float: left; font-size: 12px; font-weight: 800; margin: 7px auto; padding: 10px 1px; text-align: center; text-decoration: none; text-shadow: 1px 1px 1px #dcdcdc; width: 100%; } .kaerebalink-link1 div:hover, .booklink-link2 div:hover { background: #f6f6f6 linear-gradient(to bottom, #f6f6f6 5%, #ffffff 100%) repeat scroll 0 0; } .kaerebalink-link1 div a, .booklink-link2 div a{ text-decoration: none; } .booklink-footer { clear: left; } .shoplinkamazon a { color: #ff9901; } .shoplinkrakuten a { color: #c20004; } .shoplinkkindle a { color: #007dcd; } .shoplinkkakakucom a { color: #314995; } .shoplinkyahoo a { color: #7b0099; } .shoplinkseven a { color: #000; } .shoplinkehon a { color: #0086cd; } .shoplinkkino a { color: #004097; } .shoplinkjun a { color: #1c2c5e; } .shoplinktoshokan a { color: #27b5e9; } .shoplinkpsstore a { color: #003791; } /************************************ ** BabyLink ************************************/ .babylink-box{ overflow: hidden; font-size: small; zoom: 1; margin: 1em 0; text-align: left; border: medium double #ccc; border-radius: 4px; padding: 10px; } .babylink-image{ float: left; margin: 0px 15px 10px 0px; width: 75px; height: 75px; text-align: center; } .babylink-image img{ border-top: medium none; border-right: medium none; border-bottom: medium none; border-left: medium none; } .babylink-info{ overflow: hidden; zoom: 1; line-height: 120%; } .babylink-title{ margin-bottom: 2px; line-height: 120%; } .babylink-manufacturer{ margin-bottom: 5px; } .babylink-description{ margin-top: 7px; }
画像タグをAMP用に置換
//画像タグをAMP用に置換 $the_content = preg_replace('/<img/i', '<amp-img', $the_content);
上記コードは、imgタグをamp-imgタグに置換しています。
SNS埋め込みコードをAMP用に置換
// Twitterをamp-twitterに置換する(埋め込みコード) $pattern = '/<blockquote class="twitter-tweet".*?>.+?<a href="https:\/\/twitter.com\/.*?\/status\/(.*?)">.+?<\/blockquote>.*?<script async src="\/\/platform.twitter.com\/widgets.js" charset="utf-8"><\/script>/is'; $append = '<p><amp-twitter width=592 height=472 layout="responsive" data-tweetid="$1"></amp-twitter></p>'; $the_content = preg_replace($pattern, $append, $the_content); // vineをamp-vineに置換する $pattern = '/<iframe[^>]+?src="https:\/\/vine.co\/v\/(.+?)\/embed\/simple".+?><\/iframe>/is'; $append = '<p><amp-vine data-vineid="$1" width="592" height="592" layout="responsive"></amp-vine></p>'; $the_content = preg_replace($pattern, $append, $the_content); // Instagramをamp-instagramに置換する $pattern = '/<blockquote class="instagram-media".+?"https:\/\/www.instagram.com\/p\/(.+?)\/".+?<\/blockquote>/is'; $append = '<p><amp-instagram layout="responsive" data-shortcode="$1" width="592" height="592" ></amp-instagram></p>'; $the_content = preg_replace($pattern, $append, $the_content); // YouTubeを置換する(埋め込みコード) $pattern = '/<iframe.+?src="https:\/\/www.youtube.com\/embed\/(.+?)(\?feature=oembed)?".*?><\/iframe>/is'; $append = '<amp-youtube layout="responsive" data-videoid="$1" width="800" height="450"></amp-youtube>'; $the_content = preg_replace($pattern, $append, $the_content); // iframeをamp-iframeに置換する $pattern = '/<iframe/i'; $append = '<amp-iframe layout="responsive"'; $the_content = preg_replace($pattern, $append, $the_content); $pattern = '/<\/iframe>/i'; $append = '</amp-iframe>'; $the_content = preg_replace($pattern, $append, $the_content);
各種SNSサービスの埋め込みコードをAMP用に置換しています。
ちなみに、各種SNSサービスの埋め込みコードを実際に表示させるためには、ヘッダーで以下のスクリプトが読み込まれている必要があります。
<script custom-element="amp-twitter" src="https://cdn.ampproject.org/v0/amp-twitter-0.1.js" async></script> <script async custom-element="amp-vine" src="https://cdn.ampproject.org/v0/amp-vine-0.1.js"></script> <script custom-element="amp-instagram" src="https://cdn.ampproject.org/v0/amp-instagram-0.1.js" async></script> <script async custom-element="amp-youtube" src="https://cdn.ampproject.org/v0/amp-youtube-0.1.js"></script>
その他にも、表示させたいSNS埋め込みがあれば、その都度対応させる必要があるかもしれません(AMPの方で対応していないと利用できませんが)。
余計なスクリプト呼び出しを取り除く
//スクリプトを除去する $pattern = '/<script.+?<\/script>/is'; $append = ''; $the_content = preg_replace($pattern, $append, $the_content);
最後に、余計なスクリプト呼び出し(scriptタグ)を本文からすべて取り除いています。
まとめ
今回の「投稿本文をAMP化するコード」は、まだ完璧ではないかもしれません。
ただ、Wordpressで投稿本文をAMP化するするための、ある程度の目安にはなるかと思います。
今回の関数は、かなり、正規表現を使って置換をしているので比較的重い処理になるかと思います。けれど、しっかりとAMP化された暁には、AMPページが、AMP CDNにキャッシュされて置かれ、そこから表示されると思うので、あまり気にする必要もないのかなと。
記事を拝見しました。
非常に勉強になりました。
ただ、私のようなプログラム知識の浅い者には、投稿本文のみをAMP化するとどうなるのかがイメージできないので、そのあたりお伺いできますでしょうか。
投稿ページ(記事ページ)のみがAMP化されて、そのほかのページ(トップページ、固定ページ、カテゴリページなど)は通常通りになり、スマホでのGoogle検索結果でも投稿ページのみがAMPとしてインデックスされるのでしょうか?
それとも、スマホでのGoogle検索の結果でもあくまで通常通りインデックスされ、実際の表示でも本文のみがAMP化されて表示速度が早く、それ以外のリンクやコンテンツは通常通りの表示になるのでしょうか?
上記の観点から、投稿本文のみをAMP化するとどうなるのか教えて頂けますと幸いでございます。