行き着く先はあんこ

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

スポンサーリンク

このブログは 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 の要素はwidthhightを指定している必要がありますが、amp-imgも例外ではありません。しかしこのブログでは一部の画像の width と height を指定していなかったため、置換と同時にwidthheightを追加しています。すでにwidthheightが書かれているのであれば上のコードは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-carouselamp-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 フォントは以下に限られます。

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 の読み込み方法を変更

その他関数の微調整

スポンサーリンク

スポンサーリンク