今日も8時間睡眠
888文字のブログです

【長文】WordPressでAMP対応をしたので、やったことをまとめてみる

🏅

先日「AMPについて、まじめに考えるか」と書きましたが、さっそく当サイトのAMP対応を行いました。今日はその作業内容をまとめてみます。

今日の記事は、技術的な話しかありません。

AMPとは

AMPは、Googleなどが主導する、モバイルでのサイト閲覧の高速化を目指すプロジェクトのことです。高速化は、キャッシュの仕組みやページの軽量化により実現されています。サイト作成者がAMPに対応するには、「AMP HTML」というフレームワークの仕様に従ったページを作成しないといけません。

サイトによっては、AMP対応ができない場合もあります。AMP対応時に障害になりそうなものを挙げておきます。

  • JavaScriptが使えない(ただし、後述の通り、AdSenseやGoogle Analyticsは可)
  • 外部cssも使えない(内部スタイルシートの上限は約50kb)
  • 使えないタグや使用に制約のあるタグがある

サイトの読み込みを遅くするようなものには、制約があると考えていいでしょう。

また、基本的にwp_head()wp_footer()は使わないので、動かなくなるプラグインがあるかもしれません。

なお、サイトの一部のページだけをAMPに対応させることは可能です。

ちなみに、AMP対応は、サイト訪問者にメリットはあるかもしれないけど、サイト作成者に直接のメリット(検索順位が上がるとか)はなさそうです。

WordPressにおけるAMP対応

WordPressにはAMPに対応できるプラグインがあるのですが、これを使うとどのサイトも同じデザインのAMPページになってしまい、いまいちです。

なので、ここでは、自分でテーマを修正して対応することを考えます。

AMP対応のページはキャッシュされるので、動的に内容が変わるページは対応する必要はないでしょう。AMP対応ページを作ることは可能ですが、キャッシュに反映されるかわかりません。なので、個別の投稿や固定ページには対応しますが、アーカイブページは対応不要です。コンテンツによっては、固定ページも対応不要かもしれません。

各投稿のURLの最後に?amp=1があれば、AMP対応のページが表示されるように、テーマをいじっていきます(パーマリンクはきれいなURLに変えている前提です)。各記事に、AMP非対応の通常ページと、AMP対応ページの2種類ができるということです。

single.phpだけでなく、header.phpなども修正が必要になってきます。

AMPのエラーチェック

作成したページがAMPに対応できているかどうかは、chromeでチェックできます。

AMP対応のページ(後述のAMP用JavaScriptを読み込んでおく)のURLの最後に#development=1をつけます。

これで、デベロッパーツールのConsoleを見ると、うまくいけば、AMP validation successful.と出ます。エラーが出ているときは、メッセージを読んで対応しましょう。英語ですが。

分岐

ここからテーマの修正です。

AMPかどうかによってhtmlの冒頭から書き方が変わってくるので、まずはその判別をすることが必要です。php内で次のように書きます。

$is_amp = false;
$has_amp_page = false;

if ( is_singular() && have_posts() ) {
  the_post();
  $content = str_replace( ']]>', ']]>', apply_filters( 'the_content', get_the_content() ) );

  if( strpos( $content , '<script' ) === false
        && strpos( $content , '<form' ) === false
        && strpos( $content , '<iframe' ) === false
        && strpos( $content , 'style =' ) === false
      ){
    $has_amp_page = true;
  }

  if( isset( $_GET['amp'] ) && $_GET['amp'] === '1' && $has_amp_page ){

    $is_amp = true;

    $convert_tags = array(
      '<img' => '<amp-img' ,
      '</img' => '</amp-img' ,
    );

    $content = str_replace( array_keys($convert_tags), array_values($convert_tags), $content);

  }
}

$is_ampには、AMP表示を要求されているかどうかを格納しています。URLに?amp=1がついていて、そのページがAMP対応可能かどうかで判断しています。

そのページがAMP対応可能かどうかは、コンテンツに含まれる文字で判断しています。当サイトでは、scriptタグなどを含むページはAMP対応の対象外としています。これらの文字を含んでいない場合に「AMP対応ページがある=AMP対応可能なページ」と判断しています。

序盤でthe_post()を実行し、$contentにコンテンツを格納していますが、ここで謎な処理をしています。実はget_the_content()だけでは、ショートコードなどがそのまま出てしまうので、このような処理が必要となります。テンプレートタグ/the content - WordPress Codex 日本語版 の「別の使い方」が参考になります。

これに対応して、body内のthe content()は、echo $contentに置き換えます。

後半では、コンテンツの一部を置換しています。AMPではimgタグが使えないので、AMPで使用可能なamp-imgタグに置換しています。

AMPでは使えないタグがいくつかありますが、このように代替手段が用意されている場合もあります。英語ですが、AMPで使えないタグと代替手段はここに書いてあります

ただ、代替手段があっても、置換するだけでいいとは限りません。例えば、iframeタグはamp-iframeに置き換えなさい、と書いていますが、属性をいじったりする必要があるようです。英語ですが、amp-iframeのページが参考になるでしょう。

当サイトでは、iframeタグの入っているページ(youtubeを埋め込んだページなど)は、AMP対応をあきらめました。

html冒頭3行

やっと、htmlをいじれます。まずは、doctypehtmlタグ、headタグです。

<!doctype html>
<?php if ( $is_amp ): ?>
<html amp>
<head>
<?php else: ?>
<!-- htmlタグとheadタグ -->
<?php endif; ?>

AMP対応ページでは、<html amp>と書きます。ampのところは、「AMPを意味する絵文字」でもいいようです。

その後はheadタグです。余計なものを書くとエラーが出る可能性があるので、エラーチェックをしながら書いていきましょう。

metaタグ

続いてmetaタグです。まず、headタグの直下では、charsetを指定します。

<meta charset="utf-8">

また、viewportの設定もします。

<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">

initial-scaleは必須ではないですが、あったほうがいいです。

これらのmetaタグの設定は必須です。他は、http-equiv属性が禁止ということ以外、特に制限はありません。OGPの設定などもできます。

wp_headとwp_footer

AMPでは認められたもの以外を入れるとエラーになります。wp_head()を実行すると余計なscriptや外部cssなどが入ってくるので、AMP対応ページでは実行しないようにします。

<?php if ( ! $is_amp ) { wp_head(); } ?>

ついでに、bodyの最後あたりにあるwp_footer()も実行しないようにしましょう。

<?php if ( ! $is_amp ) { wp_footer(); } ?>

ただし、wp_head()wp_footer()は、プラグインの処理で使っていることも多く、プラグインがうまく動かなくなる可能性があります。

そうなったときは、プラグインをあきらめるか、プラグインの実行タイミングを自分で修正するか、wp_head()wp_footer()の出力内容を頑張って修正するか、AMPをあきらめるか、どれかを選ぶことになると思います。

canonicalとamphtml

wp_head()を実行しないため、必要なものは自分で用意します。

<?php if ( $is_amp ): ?>
<link rel="canonical" href="<?php echo get_permalink(); ?>" />
<?php endif; ?>
<?php if ( $has_amp_page ): ?>
<link rel="amphtml" href="<?php echo get_permalink(); ?>?amp=1" />
<?php endif; ?>

前半では、AMP非対応ページを正規URLとするため、canonicalの設定をしています。これにより、AMP対応ページと非対応ページ(通常ページ)を巡回したクローラーが「二重コンテンツだ」と解釈してしまう事態を防げます。

後半は、AMP対応ページへのリンク設定です。これをしないと、クローラーがAMP対応ページを見つけられません。せっかく作ったのに気づかれないのは悲しいですね。サイトマップを送ってもいいのですが、ここで設定しておきましょう。AMP対応ページがあるときだけ追加します。

AMP用JavaScriptと決まり文句

headタグ内に、次の内容を追加します。

<?php if ( $is_amp ): ?>
<script async src="https://cdn.ampproject.org/v0.js"></script>
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<?php endif; ?>

2行目は、AMP用のJavaScriptを読み込むための記述です。

後半の長ったらしい文章も、決まり文句なので追加します。英語ですが、この決まり文句に関する説明はここにあります

両方とも必須です。

構造化データ

AMPには、構造化データが必要です。ページの内容をクローラーに伝えるためのものです。作成には少し手間がかかります。しかも、ちょこちょこ必須要素が変わっているようです。

AMP以外でも使えるので、当サイトでは個別ページなら表示するようにしています。

<?php if( $is_singular ) :?>
<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "Article",
  "mainEntityOfPage":{
    "@type":"WebPage",
    "@id":"<?php the_permalink(); ?>"
  },
  "headline": "<?php the_title();?>",
  "image": {
    "@type": "ImageObject",
    "url": "記事用の画像",
    "height": 画像の高さ,
    "width": 画像の幅
  },
  "datePublished": "<?php the_time('c') ;?>",
  "dateModified": "<?php echo max( get_the_modified_time('c'), get_the_time('c') ); ?>",
  "author": {
    "@type": "Person",
    "name": "名前"
  },
  "publisher": {
    "@type": "Organization",
    "name": "サイト名",
    "logo": {
      "@type": "ImageObject",
      "url": "<?php echo get_stylesheet_directory_uri(); ?>/logo.png",
      "width": 600,
      "height": 60
    }
  },
  "description": "<?php echo get_the_excerpt(); ?>"
}
</script>

適宜、内容は変えてください。

当サイトでは、以前は構造化データを使うためにmicrodataで書いていたのですが、上の対応をmicrodataでやるのが面倒になったこともあって、JSON-LDを使うようにしました。

画像が必須なのですが、これを用意するのがやっかいです。公式サイトを見ると、各記事ごとに横幅696ピクセル以上の画像を用意しろってなってるんですよね。ねぇよ、そんなもん。

ということで、当サイトでは、同じ画像を使いまわしています。そのうち怒られちゃうかもしれません。構造化データは今後もメンテが必要でしょう。普通はアイキャッチ画像を使います。

なお、構造化データのチェックは、Google Search Consoleでできます。

css

AMPでは、外部cssを読み込めません。なので、内部スタイルシートで書きます。次のようにamp-customをつけます。

<style amp-custom>
/* cssの内容 */
</style>

ちなみに、50000バイトを超えたらエラーになります。

当サイトでは、AMPと非AMPの両方に共通するcssをhtml内に書き、通常ページだけに設定したいcssを外部ファイルとして読み込む、という書き方をしています。

<style <?php if ( $is_amp ) echo "amp-custom"; ?>>
/* cssの内容 */
</style>

<?php if ( ! $is_amp ): ?>
<link rel="stylesheet" type="text/css" href="<?php bloginfo('stylesheet_url'); ?>" />
<?php endif; ?>

なお、インライン属性のstyleは使えません。!importantも使えません。

他のタグ

headタグ内は、ここまでに出てきたもの以外、ほとんど使えません。JavaScriptはダメ。外部cssもダメです。linkタグも制約があります。制約内容はここにあります

上のリンク先には、body内で使うタグについても説明されています。代替タグが用意されているケースもありますが、必須属性があったり、ライブラリを読み込む必要があったりするので、対応は面倒です。このあたりを探索しないといけません。

タグの制約により、ページ内のパーツも一部削る必要があります。例えば、ブログ内の検索やコメントは、forminputが使えないので削る必要があるでしょう。

また、ページがキャッシュされることから、動的に作成する要素も省いたほうがよさそうです。例えば、当サイトでは、各記事の下側に、数記事のタイトルをランダムに表示していますが、AMP対応ページでは非表示にしています。また、サイドバーの内容も大幅に削りました。

Google Analytics

Google AnalyticsはAMPに対応しています。

導入するには、まずheadタグ内の、AMP用のJavaScriptの「前」に、次を追加します。

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

続いて、次の内容をbodyタグ内に入れます。headではありません。

<amp-analytics type="googleanalytics" id="analytics1">
<script type="application/json">
{
  "vars": {
    "account": "UA-XXXXX-Y"
  },
  "triggers": {
    "trackPageview": {
      "on": "visible",
      "request": "pageview"
    }
  }
}
</script>
</amp-analytics>

idはデバッグなどで使用するらしいです。accountには、実際のトラッキングIDを入れます。通常使用しているプロパティとは別のものを用意することが推奨されています。

英語ですが、次の公式ページで詳しく説明されています。
Adding Analytics to your AMP pages

AdSense

広告は、amp-adタグを使います。多くの広告がAMPに対応していて、AdSenseも対応しています。

AdSenseの記載例の通りに書きます。

<amp-ad width=300 height=200
    type="adsense"
    data-ad-client="ca-pub-XXXXX"
    data-ad-slot="XXXXX">
</amp-ad>

XXXXXには、実際の数字を記入します。

参考サイト

AMPへの対応は、だいたいこれでOKでしょう。制約が多くて大変です。仕様が変わる可能性もあるので、今後もメンテが必要でしょう。

最後に、参考サイトを紹介します。本文中のものとダブってるのもあります。

【公式サイト】
What Is AMP?
AMPに関するドキュメント

GitHub - ampproject/amphtml
AMP HTMLに関するGitHub(htmlのサンプルなどもある)

Articles
構造化データについて

Adding Analytics to your AMP pages
AMP対応ページにGoogle Analyticsを導入する方法

AdSense
AMP対応ページにAdSenseを導入する方法

【日本語の解説サイト】
【WordPress】プラグイン無しでAMP(Accelerated Mobile Pages)に対応にする手順 | Creator Clip
全体的な説明

AMPの対応方法まとめ (作成途中)
こちらも全体的な説明

AMP (Accelerated Mobile Pages) HTML を出力するようにしてみたけど面倒くさかった話 | WWW WATCH
Movable TypeをAMP対応した人の記事

(8729文字)

バックリンク