行き着く先はあんこ

WordPressのプラグインを使ってAMP対応するにあたっての備忘録

2017.2.15

このブログはWordPressを使って管理されているのですが、昨今のGoogleのモバイル表示の猛プッシュとブログデザインのリニューアル意欲の時期が重なったので、このブログをAMPに対応しました。

すでに多くの人がWordPressをAMPに対応する方法をまとめてくれてはいるのですが、自分なりに引っかかった部分もあったので、AMP対応するにあたっての備忘録をまとめておきます。

AMPが発表されてから1年以上経ちますが、AMPの仕様はちょくちょく変更されています。今エラーがでなくても今後エラーになる可能性もあるので注意が必要です。

スポンサーリンク

AMPとは

AMPとは、Accelerated Mobile Pages Projectのことであり、モバイル表示の高速化を目的としています。詳しいことはAMP公式サイトもしくはこのページにて。

AMP対応

WordPressをAMP対応するには大きく分けて2通りの方法があります。1つめはプラグインを使わずに置換や条件分岐でAMPに対応する方法。2つめはAutomattic製プラグイン「AMP」を使う方法です。

前者はプラグインが使えない、使いたくない状況や、出力を完全に制御したい人向けです。後者はお手軽に(お手軽ではなかった)AMP対応したい場合やテンプレートファイルをきれいに見やすくしておきたい人向けです。

自分の場合はサクッとAMP対応したかったのでプラグインを使いAMPの波に乗ることにしました。

下準備

AMPプラグイン

まずは今回使用する「AMP」プラグインについて簡単に説明します。このプラグインは導入するだけでWordPressをAMP化してくれるという非常に素晴らしいプラグインです。AMPページのURLは通常ページURLの後ろに「/amp」もしくは「/?amp=1」が追加されたものになり、これについてもプラグインが自動で行ってくれます。

ためしにこのページのURLに「/amp」を付けるとAMPページに移動します。

このようにプラグインを導入するだけでいとも簡単にAMPページを作ることができます。しかし、標準のAMPページはあまりにも殺風景なのでオリジナルデザインにカスタマイズしていきます。

カスタマイズ

「amp」フォルダを作成する

まずは現在使っているテーマディレクトリに「amp」というフォルダを作成します。さらにこの中に以下の4つのテンプレートファイルを作成します。

  1. header.php
  2. single.php
  3. footer.php
  4. style.php

「AMP」プラグインは「amp」フォルダが存在していれば、プラグインのテンプレートではなく「amp」フォルダ内のテンプレートを優先的に認識します。つまり今回作成したファイルが優先的に読み込まれるようになります。

次にこれらのファイルにコードを書いていきます。以下は必要最低限のコードです。一応これだけでも動作しますが、通常のテンプレート同様に編集してオリジナルデザインにしていきます。

header.php

<!DOCTYPE html>
<html ⚡>
    <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>

single.php

<?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'); ?>

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

/*
現在使用しているstyle.cssを流用すれば幸せになれるかも。
容量が50KB以下で!importantが使えないなど細かい制限もあるので注意が必要。
*/

ここで注意することは、<head>タグ内に

do_action( 'amp_post_template_head', $this );

</body>タグの直前で

do_action( 'amp_post_template_footer', $this );

<style amp-custom>タグ内で

do_action( 'amp_post_template_css', $this );

を記入しておくことです。

AMPページの条件分岐

テンプレートを編集するとき必要になるであろうAMPページを判別するコードです。これは「AMP」プラグインの機能のひとつで、エンドポイントで判別しています。

// AMPページの条件分岐
function is_amp() {
    $is_amp = false;

    if (function_exists('is_amp_endpoint') && is_amp_endpoint()) {
        $is_amp = true;
    }

    return $is_amp;
}

上のコードをfunctions.phpに追加します。あとはAMPページなのか判断したい場所でis_amp()を条件としてAMPページの判別が可能になります。

if (is_amp()) {
    // AMPページの場合
} else {
    // 通常ページの場合
}

本文の置換

ここまで、編集したオリジナルのテンプレートを読み込ませ、スタイルシートで見た目の調整が終了しました。これにてAMP対応終わり、と思っていたのですが、確認をしていると思い通りに表示できていない部分があったので、その部分を調整していきます。

「AMP」プラグインだけで完全にAMP化するのはまだ早いようです。

AMPの本文フック

個別記事のメインコンテンツを置換するためのフックです。AMPページでのみ動作します。以下で紹介する本文置換に関するコードを以下の関数my_amp_custom_main_contentに追加してfunctions.phpに記入します。

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 ) {
    // ここに下で紹介する置換に関するコードを追加していく
    return $content;
}

禁止要素を削除

AMPではHTML要素の一部が使用禁止になっています。仮に禁止要素が混ざっているとエラーが発生しAMP対応ができません。以下ではAMPで使用が禁止されている要素の代表的なものを削除します。

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

埋め込み要素のAMP化

「AMP」プラグインはTwitterやYouTubeなどの埋め込み要素もAMP化してくれます。しかし、自分の環境ではTwitterの置換ができておらず、YouTubeに関しては幅が100vw固定?で左右にマージンを取っていたため画面に入り切らないといった問題が発生しました。

これに対処するために、自分でAMP専用タグに置換します。

// 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);

Twitterの埋め込みは通常の埋め込みと動画の埋め込み?の2種類を確認したので、どちらにも対応できるようにします。YouTubeの置換に関しても全ての埋め込みコードに対応できるはずです。

また、AMPページでTwitterやYouTubeの埋め込みを動作させるには専用のJavaScriptをhead内で読み込む必要があります。実は2017年始めにAMPの仕様が変更され制約が強くなりました。詳しくは以下の「専用JavaScriptの読み込み」にて。

画像のAMP化

imgタグも専用のamp-imgタグに置換する必要があります。アスペクト比を保ちながらレスポンシブ表示するためにlayout属性responsiveも指定します。

// 画像にサイズ(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);

基本的にAMPの要素はwidthとhightを指定している必要がありますが、amp-imgも例外ではありません。しかしこのブログでは一部の画像のwidthとheightを指定していなかったため、置換と同時にwidthとheightを追加しています。すでにwidthとheightが書かれているのであれば上のコードはamp-img置換の部分のみで問題ありません。

以上で本文の置換は終了です。このような感じで本文内の使用禁止タグを削除したり、AMP専用タグに置換したりしていきます。上記のコードのみ追加しても確実にAMP化できるわけではありませんので、適宜コードを追加・修正して各々の環境に合わせる必要はあります。

専用JavaScriptの読み込み

本文を置換するときに軽くふれましたが、AMPページでYouTubeやTwitterなどの埋め込み要素を使うには専用のJavaScriptをhead内で読み込む必要があります。以下のコードはfunctions.phpに追加。

// 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';
    }
    // 全てのページで使うことが分かっている
    $data['amp_component_scripts']['amp-carousel'] = 'https://cdn.ampproject.org/v0/amp-carousel-0.1.js';
    $data['amp_component_scripts']['amp-ad'] = 'https://cdn.ampproject.org/v0/amp-ad-0.1.js';
    
    return $data;
}

本文にamp-youtubeが存在すれば自動でYouTube専用JavaScriptが読み込まれます。逆に存在しなければ読み込まれません。Twitterも同様です。また、全てのページで使われることが分かっているならば、amp-carouselやamp-adの様に記入することで常に読み込まれるようになります。

AnalyticsのAMP化

AMPプラグインはAnalyticsにも対応しているので簡単にAnalyticsを導入できます。以下のコードをfunctions.phpに追加します。これでAMPページでもページビューが取得できるようになります。トラッキングIDは自分のものに変えることも忘れずに。

// AMP Analytics
add_filter( 'amp_post_template_analytics', 'xyz_amp_add_custom_analytics' );
function xyz_amp_add_custom_analytics( $analytics ) {
    if (!is_array($analytics)) {
        $analytics = array();
    }
    
    // https://developers.google.com/analytics/devguides/collection/amp-analytics/
    $analytics['xyz-googleanalytics'] = array(
        'type' => 'googleanalytics',
        'attributes' => array(),
        'config_data' => array(
            'vars' => array(
                'account' => "UA-XXXXXXXX-X" // トラッキングコード
            ),
            'triggers' => array(
                'trackPageview' => array(
                    'on' => 'visible',
                    'request' => 'pageview',
                ),
            ),
        ),
    );

    return $analytics;
}

Analyticsも専用のJavaScriptを読み込む必要がありますが、amp_post_template_analyticsフックで以下のコードを勝手に追加してくれるので特になにもしません。

<script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script>

AdsenseのAMP化

AdsenseもAMPに対応していますが、他と同様にhead内で専用JavaScriptを読み込んでいる必要があります。上記の「専用JavaScriptの読み込み」my_amp_post_custom_add_script関数で読み込ませておきます。

Adsenseを表示するコードは次のようになります。

<amp-ad width=300 height=250
      type="adsense"
      data-ad-client="ca-pub-XXXXXXXXXXXXXXXX"
      data-ad-slot="XXXXXXXXXX">
 </amp-ad>

Adsense以外は使ってないのでその他の広告について検証はできてませんが、CriteoやYahooJPなどもAMPに対応しているようです。

Webフォント

制限の多いAMPですが意外にもWebフォントが使えます。通常のHTMLと同じくhead内にlinkタグを追加して使いますが、今回はプラグインのフックにより追加します。functions.phpに追加。

// AMP webフォントを追加
add_action( 'amp_post_template_data', 'my_amp_post_custom_add_fonts');
function my_amp_post_custom_add_fonts($data) {
    //デフォルトのMerriweatherを削除
    $data['font_urls'] = array(
        'Josefin' => 'https://fonts.googleapis.com/css?family=Josefin+Sans',
        'FontAwesome' => 'https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css',
        // 使いたいフォントの名前とurlをここに追加
    );
    
    return $data;
}

ここではGoogle Fontsの「Josefin」とFont Awesomeを追加します。デフォルトで「Merriweather」が読み込まれますが、今回は削除しています。

また、2016年10月現在では使用可能なWebフォントは以下に限られます。

  • Typography.com:
    https://cloud.typography.com
  • Fonts.com:
    https://fast.fonts.net
  • Google Fonts:
    https://fonts.googleapis.com
  • Font Awesome:
    https://maxcdn.bootstrapcdn.com

Google FontsとFont Awesomeが使えるのは嬉しいところ。

その他

以下は個人的に気になったカスタマイズです。

AMPページのURL

AMPページのエンドポイントの変更です。

add_filter( 'amp_query_var' , 'xyz_amp_change_endpoint' );
function xyz_amp_change_endpoint( $amp_endpoint ) {
    return 'foo';
}

デフォルトの「/amp」から「/foo」に変わります。

ページタイトル変更

デフォルトではAMPページのタイトルは「ページタイトル – サイトタイトル」ですが、「ページタイトル」のみに変更します。

// AMPページのタイトルカスタマイズ
add_action( 'amp_post_template_data', 'my_amp_post_custom_title');
function my_amp_post_custom_title($data) {
    $data['document_title'] = $data['post']->post_title;
    
    return $data;
}

descriptionの追加

プラグインでは表示されないようなので自前でdescriptionを追加します。必須要素ではないので、なくてもエラーはでません。

// AMP descriptioの追加
add_filter( 'amp_post_template_metadata', 'xyz_amp_modify_json_metadata', 10, 2 );
function xyz_amp_modify_json_metadata($metadata, $post) {
    $metadata['description'] = get_the_excerpt();

    return $metadata;
}

確認作業

最後にAMPに対応できているか確認します。

ChromeのディベロッパーツールでAMPの確認

確認したいAMPページのURLに「#development=1」を付けると、Chromeのディベロッパーツールの「Console」タブにてエラー内容が確認できます。「AMP validation successful.」と表示されていればAMP対応できています。

またSearch ConsoleやGoogleが新たに公開したサイト「AMPテスト」からもAMPの状況を確認できます。

AMPテストサイトで確認

ここでエラーが発生していれば、AMPドキュメント片手にエラー内容とにらめっこです。

さいごに

「AMP」プラグインを使えばサクッとAMP対応できる予定だったのですが、ある程度デザインを編集したため想像以上に手間がかかりました。

このブログに適応させるためにここでまとめた以外にもいくつか工程を経ているので、プラグインを使わない方法とまではいきませんがそれなにり労力が必要でした。もちろん初期の殺風景なデザインでよければワンクリックで対応できるのですが……。

2016年10月21日、日本でもモバイル検索結果にAMPラベルの表示を開始するとGoogle Japan Blogにて発表がありました。AMP対応の時期はもうすでに来ているのかもしれませんね。

参考記事

更新内容:
2017年1月12日
JavaScriptの読み込み方法を変更
その他関数の微調整

スポンサーリンク

スポンサーリンク

コメント

  1. 匿名

    2016.12.10 04:31

    このページを求めてました。
    ベリーサンキューです。

    • かずら(管理人)

      2016.12.11 05:59

      イエーイ!

  2. 匿名

    2016.12.19 02:02

    ワードプレスプラグイン「AMP」を導入し、プラグイン→「AMP」の直接編集でsingle.phpの部分に

    を追加してみましたが、埋め込みツイッターコードがツイッターカードとしてうまく表示されません。

    // Twitterをamp-twitterに置換する(埋め込みコード)
    $pattern = ‘/<blockquote cl ~

    これらのコードはどのファイルに書けばいいのでしょうか?

    • かずら(管理人)

      2016.12.20 19:08

      このページにある置換に関するコードは、メインコンテンツフックであるmy_amp_custom_main_content関数の中に記入することを想定しています。

      また、my_amp_custom_main_contentなどはsingle.phpに追加しても使えるのですが、個人的にはfunctions.phpに追加することをオススメします。

      • 匿名

        2016.12.21 06:36

        よ~~~~~やくAMPページで埋め込みTwitterをちゃんと表示することができました
        ここ10日間ほどさまよってました
        ありがとうございました

  3. 匿名

    2016.12.23 02:04

    重ねて質問ですが、 echo get_the_post_thumbnailで取得される画像はAMP化できないでしょうか?
    それ以外のことは完璧にうまくいったのですが、ショートコードによる画像表示のタグがタグに切り替わらないです。
    現状では画像なしのカテゴリ記事表示でAMPページを運用しています。

    • かずら(管理人)

      2016.12.24 12:38

      get_the_post_thumbnail()を使うのであれば、

      $thumb = get_the_post_thumbnail();
      $thumb = preg_replace('/<img([^>]+?)\/?>/iu', '<amp-img layout=”responsive”$1></amp-img>', $thumb);
      echo $thumb;

      でAMPに対応した画像が表示できます。

      • 匿名

        2017.01.05 14:08

        ありがとうございました。
        それにしてもなんてお詳しいんでしょうか!

        • かずら(管理人)

          2017.01.06 00:20

          Web関連は趣味でやっているので、自分も毎日が分からないことばかりです。ただそれを楽しんでる自分もいたりします。

          AMP化お疲れ様です!

  4. 2017.02.02 08:47

    […] 参考:WordPressのプラグインを使ってAMP対応するにあたっての備忘録 […]

コメントを残す