Blog

WordPressをAMP対応

2018.07.19
Yuko Hashimoto
Yuko Hashimoto デザイナー

ここ数年は7月に必ず皮膚炎で病院に駆け込む橋本です。もう限界です。
みなさま、熱中症にも夏バテにも暑さにまつわる諸症状全般にお気をつけください。
私はマスクと腹巻が手放せません。

…それはともかく、
先日のリニューアルでクオックスのサイトもAMPに対応しました。
WordPressに「AMP」というプラグインを適用させることで対応したのですが、初期設定では寂しい見た目を結構いじったので、その覚え書きです。

AMPとは

AMP = Accelerated Mobile Pages Project。
モバイル向けの高速表示用HTMLのこと。HTMLをGoogleにキャッシュし読み込み時間を大幅に削減する仕組みだそうです。
詳しくは公式サイトをご覧ください。
AMPプロジェクト(公式サイト)

AMPサイトでは多くの制限があります。

リッチなサイトにはきつい感じですが、テキストベースの記事を高速に表示するためのものなので仕方ないっぽい。

プラグイン入れてみた

その名もずばり「AMP」というプラグインを入れてみました。
AMP – WordPress Plugins

通常ページURLの末尾に「/amp」をつけるだけでAMPに変換したページを表示してくれます。
しかし初期設定のテンプレートが非常に寂しい。左が初期設定、右がデザインを元のページに近づけるよう手を入れたものです。

これはいけない。

テンプレートを作る

こちらのサイトを参考にカスタマイズを行いました。
WordPressのプラグインを使ってAMP⚡対応するにあたっての備忘録

テンプレートのファイルを用意

上記サイトからのコピペになります。

  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
    <?php do_action( 'amp_post_template_head', $this ); ?>
    <style amp-custom>
      <?php
        $this->load_parts( array( 'style' ) );
        do_action( 'amp_post_template_css', $this );
      ?>
    </style>
  </head>
  <body>
    <?php
      // 「amp」フォルダ内の「header.php」を読み込む
      include ( TEMPLATEPATH . '/amp/header.php');
    ?>
    <main>
      <article>
        <?php echo $this->get( 'post_amp_content' ); //個別投稿の本文を表示する ?>
      </article>
    </main>
    <?php
      // 「amp」フォルダー内の「footer.php」を読み込む
      include ( TEMPLATEPATH . '/amp/footer.php');
    ?>
    <?php do_action( 'amp_post_template_footer', $this ); ?>
    <footer>
      <p>&copy; <?php echo date( 'Y' ); ?> <?php bloginfo( 'name' ); ?></p>
    </footer>
  </body>
</html>

style.phpは元のデザインに使っているCSSをそのまま使えば良さそうですが、AMPに使用できるスタイルシートの制限が

となっているので、なるべく余分な部分を減らした上で、こちらを使って少し圧縮しました。
PHP Function to Minify HTML, CSS and JavaScript – GitHub

php-html-css-js-minifier.phpをstyle.phpを同じフォルダに置いて、style.phpに適用します。

<?php
  include 'php-html-css-js-minifier.php';
  ob_start();
?>

/* スタイルシートの中身 */

<?php
  $content = minify_css( ob_get_clean() );
  echo $content;
?>

また、ページ内にインライン(style=”color:#000;”みたいな形)でスタイルシートを書くのも禁止されています。
ページ上部でアイキャッチ画像をstyle=”background-image…と直接指定していたので、header.php内でクラスにしてしまいます。
記事ごとにカスタムCSSを設定していたり、AMP用のAnalyticsやAdsenseの設定もあるので、まとめるとこんな感じ。

<!DOCTYPE html>
<html &#x26a1;>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
    <?php do_action( 'amp_post_template_head', $this ); ?>
    
    <?php if( get_option( "qox_analytics" ) ){ ?> // 設定画面でAnalytics設定しているとき
    <script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script> <?php } ?>

    <?php if( get_option( "qox_adsenseAmp" ) ){ ?>// 設定画面でAdsense設定しているとき
    <script async custom-element="amp-ad" src="https://cdn.ampproject.org/v0/amp-ad-0.1.js"></script> <?php } ?>
    
    <style amp-custom>
      <?php $this->load_parts( array( 'style' ) );
      do_action( 'amp_post_template_css', $this );

      // カスタムCSSの内容
      if ( is_page() || is_single() ) {
        if ( have_posts() ) : while ( have_posts() ) : the_post();
          echo get_post_meta(get_the_ID(), '_custom_css', true);
        endwhile; endif;
        rewind_posts();
      }
      
      // アイキャッチ
      if ( has_post_thumbnail() ) {
        $image_id = get_post_thumbnail_id ();
        $image_url = wp_get_attachment_image_src ($image_id, true);
        echo ' .header{ background-image:url("' . $image_url[0] . '");}';
        echo ' .a_wrapper .image_wrapper .image{ background-image:url("' . $image_url[0] . '");}';
      } else {
        echo ' .header{ background-image:url("' . get_template_directory_uri() . '/images/featured.png");}';
        echo ' .a_wrapper .image_wrapper .image{ background-image:url("' . get_template_directory_uri() . '/images/featured.png");}'; 
      } ?>
      </style>
      
      <!-- FontAwesome -->
      <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
      
    </head>
    <body>
      <?php if( get_option( "qox_analytics" ) ){ ?>
      <amp-analytics type="googleanalytics" id="analytics1">
      <script type="application/json">
      // Analyticsの設定
      </script>
      </amp-analytics>
    <?php } ?>

AdsenseやAnalyticsはテンプレートに慣れない管理者でも変更できるよう、会社情報とまとめて設定する画面を作っているので、そちらに設定があれば表示するようにしています。

AMPページでは外部ファイルの読み込みはできませんが、AMP公式に指定されたカスタムフォントは読み込んで使用できます。
カスタム フォントの追加-AMP
2018年7月時点で使用できるのはこれだけですが…。

禁止要素、埋め込み要素、画像サイズの指定

AMP内で使用できない要素を削除し、画像にwidthとheightを加えます。こちらも前出のサイトのコピペです。

add_action( 'pre_amp_render_post', 'xyz_amp_add_custom_actions' );

function xyz_amp_add_custom_actions() {
  add_filter( 'the_content', 'my_amp_custom_main_content' );
}

function my_amp_custom_main_content ( $content ) {

  // いろいろ削除
  $content = preg_replace(array(
    '/<script[^<]*?<\/script>/iu', // scriptを削除
    '/style="[^"]*?"/iu', // styleを削除
    '/border="[^"]*?"/iu', // borderを削除
    '/target="[^"]*?"/iu', // targetを削除
    '/onclick="[^"]*?"/iu', // onclickを削除
    '/scale="[^"]*?"/iu' // scaleを削除
  ), '', $content);

  // 画像にサイズ(widthとheight)を追加
  $pattern = '/<img [^>]*?src="(https?:\/\/[^"]+?)"[^>]*?>/iu';
  preg_match_all($pattern, $content, $imgs);

  foreach ( $imgs[0] as $i => $img ) {
    if ( false !== strpos( $img, 'width=' ) && false !== strpos( $img, 'height=' ) ) {
      continue;
    }
    $img_url = $imgs[1][$i]; // 画像url
    $img_size = @getimagesize( $img_url ); // 画像サイズを取得
    if ( false === $img_size ) {
      continue;
    }
    $replaced_img = str_replace( '<img ', '<img ' . $img_size[3] . ' ', $imgs[0][$i] );
    $content = str_replace( $img, $replaced_img, $content );
  }

  // imgタグをamp-imgタグに置換
  $pattern = '/<img ([^>]+?)\/?>/i';
  $replacement = '<amp-img layout="responsive" $1></amp-img>';
  $content = preg_replace($pattern, $replacement, $content);

  // Twitterをamp-twitterに置換する(埋め込みコード)
  $pattern = '/<blockquote class="twitter-(tweet|video)".*?>.+?<a href="https:\/\/twitter.com\/.*?\/status\/(.*?)">.+?<\/blockquote>/iu';
  $replacement = '<amp-twitter width=592 height=472 layout="responsive" data-tweetid="$2"></amp-twitter>';
  $content = preg_replace($pattern, $replacement, $content);

  // YouTubeをamp-youtubeに置換する(埋め込みコード)
  $pattern = '/<iframe[^>]+?youtube\.com\/embed\/(.+?)(\?[^>]+?)?"[^<]+?<\/iframe>/iu';
  $replacement = '<amp-youtube layout="responsive" data-videoid="$1" width="560" height="315"></amp-youtube>';
  $content = preg_replace($pattern, $replacement, $content);

  // ついでにiframeも置換する
  $pattern = '/<iframe ([^<]+?)<\/iframe>/iu';
  $replacement = '<amp-iframe layout="responsive" $1</amp-iframe>';
  $content = preg_replace($pattern, $replacement, $content);

  return $content;
}

// AMPのscriptを制御
add_action( 'amp_post_template_data', 'my_amp_post_custom_add_script');
function my_amp_post_custom_add_script($data) {
  $content = $data['post_amp_content'];

  // YouTube
  if (preg_match('/<amp-youtube[^<]*?<\/amp-youtube>/iu', $content)) {
    $data['amp_component_scripts']['amp-youtube'] = 'https://cdn.ampproject.org/v0/amp-youtube-0.1.js';
  }

  // Twitter
  if (preg_match('/<amp-twitter[^<]*?<\/amp-twitter>/iu', $content)) {
    $data['amp_component_scripts']['amp-twitter'] = 'https://cdn.ampproject.org/v0/amp-twitter-0.1.js';
  }

  // iframe
  if (preg_match('/<amp-iframe[^<]*?<\/amp-iframe>/iu', $content)) {
    $data['amp_component_scripts']['amp-iframe'] = 'https://cdn.ampproject.org/v0/amp-iframe-0.1.js';
  }
  
  return $data;
}

仕上がり

AMP化されたページはURLの末尾に「/amp」をつけると見ることができます。
この記事のAMP版はこちらです。
http://qox.jp/blog/wordpress-amp/amp/

参考サイト

AMPプロジェクト(公式サイト)
WordPressのプラグインを使ってAMP⚡対応するにあたっての備忘録
WordPressをマジメにAMP(Accelerated Mobile Pages)対応させた話 #AMPlify
AMP – WordPress Plugins
PHP Function to Minify HTML, CSS and JavaScript – GitHub