【Wordpress】プラグイン無しでAMP（Accelerated Mobile Pages）対応してみた。

2016年2月25日よりGoogleが開始したAMP(Accelerated Mobile Pages)プロジェクト。
巷では「アクセス速度が速くなる」「SEOに効果があるのでは？」と話が広まっていますが、今回はその概要と、実際Wordpressサイトに適用させる場合の手順をまとめます。

# そもそもAMPって何？
AMPとは、Accelerated Mobile Pageの頭文字をとったもので、スマホ用Webサイトの表示を高速化する技術です。AMP対応サイトを用意することにより、Webサイトの情報がGoogle（他にもTwitter等）にキャッシュされ、ユーザーがアクセスした際にはGoogle側のキャッシュサーバの情報を閲覧するため、表示速度が圧倒的に早くなるといった仕組みです。

# SEOに効果があるの？
Googleからの発表によると、「今のところ、スマホサイトをAMP化しても、検索順位には影響ない」とされています。しかし、Google検索結果にカルーセル表示され、これまでなかなかSEO上位にあがってこなかったサイトが表示されたり、ページ速度が改善されてCVRに好影響を及ぼしたりと、よい効果が得られると考えられます。対応しておいて損はないでしょう。

# Wordpressのプラグインで対応した場合
では具体的にどのようにAMPサイトを作成するのでしょうか？Wordpressサイトをお持ちの方は、まず真っ先にプラグインを導入することを思い浮かべると思いますが、プラグインを使用した場合、元のサイトからデザインが大幅に崩れたり、AMPサイトとして正常に認識されなかったりと、問題が多々存在しているのが実情です。

# プラグイン無しでAMP対応してみた
AMP対応前のサイトからデザインを崩さずに対応する、確実に全ページをAMP対応する場合は、Wordpressのテーマを修正してAMP対応することをお勧めします。今回は「WpTHK」というテーマを適用しているサイトで試しましたが、Wordpressデフォルトテーマの「Twenty Sixteen」や、人気テーマの「STINGER」でも基本的な対応方法は同じです。

## 前提条件
現状のサイトにクエリパラメータ（GETパラメータ）で「?amp=1」と付与することによりAMPページを自動的に表示させる仕組みとします。
クエリパラメータはSEOに不利ではないか？という声も聞こえますが、[GoogleのJohn Mueller氏の発言](http://webmasters.stackexchange.com/questions/60833/google-is-changing-my-urls-in-search-results-joomla3-bug/60838#60838)を見ると、「Googleの観点から言えば、不要なURLの書き換えを行うより、パラメータ化されたきれいなURLを使用するのが一般的です。」と発言されている通り、変にURL操作はしない方が良いという判断で、この形をとることとします。

>Just wanted to add that from Google's point of view, the clean, parameterized URL is generally preferred to any unnecessary URL-rewriting. If you want a nice-looking URL-line in search, use breadcrumb markup instead. – John Mueller 
>>Googleの観点から言えば、不要なURLの書き換えを行うより、パラメータ化されたきれいなURLを使用するのが一般的です。 – John Mueller 

## 対応１　クエリパラメータ取得
```php
$isAmp = (wp_is_mobile() && isset($_GET['amp']) && $_GET['amp'] == 1) ? true : false;
```
<head>内に上記ソースを追記し、スマホからのアクセスの場合、クエリパラメータにamp=1と入力された場合にAMPサイトを表示させるようにします。

## 対応２　htmlタグの書き換え
```php
<?php if ($isAmp): ?>
<html amp>
<?php else: ?>
<html>
<?php endif; ?>
```
htmlタグを$isAmp変数の値に応じて振り分けます。AMPサイトの場合はhtml ampとします。

## 対応３ canonicalの付与
```php
<?php if ($isAmp): ?>
<link rel="canonical" href="<?php echo get_permalink() ?>" />
<?php endif; ?>
```
AMPサイトの場合は<head>タグ内にcanonicalの設定が必須となります。All In One SEO Packプラグインが適用され、canonical設定がONになっている場合はこちらは不要となります。

## 対応４ AMP専用JSの読み込み
```php
<?php if($isAmp): ?>
    <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>
    <script async src="https://cdn.ampproject.org/v0.js"></script>
<?php endif; ?>
```
<head>タグ内にてAMP専用のJSを読み込みます。こちらの記述がないとAMPサイトとして認識されないので注意してください。

## 対応５ Google Analytics対応
```php
<?php if ($isAmp): ?>
<script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script>
<?php endif; ?>

<?php if ($isAmp): ?>
<amp-analytics type="googleanalytics" id="analytics1">
<script type="application/json">
{
  "vars": {
    "account": "UA-XXXXXXXX-Y"
  },
  "triggers": {
    "trackPageview": {
      "on": "visible",
      "request": "pageview"
    }
  }
}
</script>
</amp-analytics>
<?php else: ?>
<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-XXXXXXXX-Y', 'auto');
  ga('send', 'pageview');

</script>
<?php endif; ?>
```
Google Analyticsでの計測を行う場合は、通常のタグが使用できませんので、AMP専用のタグに書き換える必要があります。

### [はまりポイント]js記述位置を間違えるとAMPエラーが出てしまう。
**amp-analytics-0.1.jsを読んでいるscriptタグは必ずhead内に記載**する点です。これを行っておかないとAMPエラーになってしまいます。

### [はまりポイント]AMP対応のGoogle Analyticsのタグが表示されない。
AMP専用のAnalyticsタグが表示されるように振り分けているはずなのに、通常のタグが表示されてしまうという現象が発生していましたが、原因は「All in One SEO Pack」の設定にある「GoogleアナリティクスID：」にUA-XXXXXXXX-Yの記載があったことが原因でした。
ここに記載があると、header.php内にAnalyticsタグの記述をしても、プラグイン側で書き換えられてしまうようです。


## 対応6 AMP専用cssを作成する
AMP専用のcssファイルを作成します。（今回はstyle.amp.cssというファイル名にします。）
AMPでは以下のcss要素が禁止されています。style.amp.cssファイルの内容を適宜書き換えましょう。

|AMP内での主な制約|
|:--:|
|@charset禁止|
|@import禁止|
|!important禁止|
|ユニバーサルセレクタ（*)禁止|
|:not()セレクタ禁止|
|cssのサイズは50kbまで|

## 対応7 専用cssをfile_get_contentsにて読み込む
```php
<?php if($isAmp): ?>
<style amp-custom>
<?php 
echo file_get_contents(get_stylesheet_directory_uri() . ‘/style.amp.css');
?>
</style>
<?php endif; ?>
```
AMPでは基本的にlinkタグを使用することができません。cssを読み込む際は、file_get_contentsを使ってampのソースを直接html内に記述する形が一番楽です。

## 対応８ wp_head()、wp_footer()をコールしない
```php
<?php if(!$isAmp): ?>
    wp_head();
<?php endif; ?>
 
<?php if(!$isAmp): ?>
    wp_footer();
<?php endif; ?>
```
wp_head()、wp_footer()をコールしてしまうと、そこで余分なjsファイルが出力されてしまうので、AMPサイトの場合はコールされないようにします。

## 対応９ その他JSがコールされる箇所を除外
使用しているテーマ次第ですが、JSが出力されてしまう関数がコールされている可能性があるので、上記対応８同様コールされないようにします。

## 対応１０ ソーシャルボタンの対応
```php
// twitter
<?php if ($isAmp): ?>
  <amp-social-share type="twitter" width="44" height="32"></amp-social-share>
<?php else: ?> 
  通常のソーシャルボタン処理
<?php endif; ?>
```
AMPはソーシャルボタン表示専用のタグが存在しますのでこちらも振り分けが必要となります。
利用可能なソーシャルボタンは以下の通りとなります。

* Twitter
* Facebook
* Google+
* pinterest
* linkedin

## 対応１１　the_contentのレンダリング
```php
		if ($isAmp):
			// imgの置き換え
			$protocol = empty($_SERVER["HTTPS"]) ? 'http://' : 'https://'; // http://
			$host = $_SERVER['HTTP_HOST']; // cly7796.net
			$content = apply_filters( 'the_content', get_the_content() );
			$content = str_replace( ']]>', ']]&gt;', $content );

			// img要素すべて持ってくる
    			$patternAtr = '/<img(.*?)>/i';
			preg_match_all($patternAtr, $content, $imgMatches);

			// 設定
			$targetWidth = 320;
			$patternSrc = '/src="(.*?)"/i';

			foreach ($imgMatches[1] as $value) {
				// class属性はいらないから消す
				$value2 = preg_replace('/class="(.*)"/i', '', $value);

				// imgのsrcを持ってくる
				preg_match($patternSrc, $value, $srcval);

				// 画像のサイズを取得
				list($width, $height, $type, $attr) = getimagesize($protocol.$host.$srcval[1]);

				// 高さを調整
				$targetHeight = round($targetWidth / $width * $height);

				// 置き換え後の文字列
				$append = '<amp-img src="' . $srcval[1] . '" layout="fixed" width="' . $targetWidth . '" height="' . $targetHeight. '"';

				// 変数内をエスケープ
				$srcval = preg_replace('/\//', '\\/', $srcval);
				$srcval = preg_replace('/\./', '\\.', $srcval);

				// 置き換え前の文字列
				$patternLast = '/<img src="' . $srcval[1] . '"/i';

				$content = preg_replace($patternLast, $append, $content);
			}

			// onclickを削除
			$content = preg_replace('/onclick="(.*?)"/i', '', $content);

			// styleを削除
			$content = preg_replace('/style="(.*?)"/i', '', $content);

			echo $content;
		else:
			the_content(); // 本文
		endif;
```
ここが一番のキーポイントですが、投稿記事や固定ページを出力している箇所をレンダリングします。page.phpやsingle.phpに記載されている、the_content()の部分を上記のように書き換えます。

ここでは以下の処理を行っています。

* imgタグをamp-imgタグに変更
* imgタグのwidth、heightを設定
* onClickを削除
* style属性を削除

### [こだわりポイント]amp-imgタグのheight設定
amp-imgタグには基本的にheight属性が必要ですが、記事内（又は固定ページ内）では省略されることが多いと思います。そこで、オリジナルの画像サイズを取得し、heightを自動的に付与する形にしています。

# まとめ
いかがでしたでしょうか。2016年2月にGoogleからAMP対応が発表されて以来、対応サイトが増えてきました。Googleからの発表によるとまだSEOに効果はないといわれていますが、モバイルファーストが推奨されている中、AMPは今後重要な技術であり、各サイト対応が必須になってくる流れになると思われます。

Wordpressでサイトを運営されている方はプラグインで対応することもできますが、AMPサイトであってもデザイン面を妥協したくない方は、是非プラグイン無しでAMP化することをお勧めします。