【AMP】記事系コンテンツで使いそうなAMP対応のメモ

本当はお遊びで**「ゴジラがどのゴジラか分類してみた」「ゴジラの出没地を予測してみた」**というネタを書こうとしていました。@s-moriです。
ミレニアムシリーズが好きです。


今年から本格稼働していたAMPですが、徐々にAMP化されたページの露出が増えてきています。
そんな中、AMPの仕様を理解していなかったためにバリデーションエラーが発生しまくっていたという現実にぶつかり大ダメージを受けたので、自戒の念を込めて簡単にまとめておこうかと思います。
AMPのタグ等、対応全部まとめると超大作になってしまうので、**AMP対応の基本＋記事系コンテンツで使いそうなSNSボタン、埋め込みwidget系、GA系**に絞っています。

そもそもの「AMPとは」という部分は公式より引用。
> AMP HTML は、パフォーマンスを保証するための制約が設けられた HTML で、 通常の HTML より優れたリッチ コンテンツを作成できる拡張機能が備わっています。 そして AMP HTML ページのレンダリングを高速化するのが、AMP JS ライブラリです。 Google AMP Cache は（必要に応じて）AMP HTML ページを配信します。
[AMPとは](https://www.ampproject.org/learn/about-amp/)

# HTMLをAMP化する
## AMP HTMLページの作成
[AMP > Tutorials > Create Your AMP HTML Page](https://www.ampproject.org/docs/get_started/create/basic_markup)にサンプルがあります。ので、まるっと拝借。

```html
<!-- DOCTYPE宣言 -->
<!doctype html>
<!-- <html amp>でAMPページということを示す -->
<html amp lang="en">
  <head>
    <!-- headタグの最初の子要素で文字コードを指定 -->
    <meta charset="utf-8">
    <title>Hello, AMPs</title>
    <!-- canonicalで表示しているAMPページの元となるHTMLページのURLを指定。なければ自身のURLを指定 -->
    <link rel="canonical" href="http://example.ampproject.org/article-metadata.html" />
    <!-- 表示領域の設定 -->
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
    <!-- schema.orgの構造化マークアップ -->
    <script type="application/ld+json">
      {
        "@context": "http://schema.org",
        "@type": "NewsArticle",
        "headline": "Open-source framework for publishing content",
        "datePublished": "2015-10-07T12:02:41Z",
        "image": [
          "logo.jpg"
        ]
      }
    </script>
    <!-- ampのstyle -->
    <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>
    <!-- headタグの最後の要素に設定。AMP JSライブラリの読み込み -->
    <script async src="https://cdn.ampproject.org/v0.js"></script>
  </head>
  <body>
    <h1>Welcome to the mobile web</h1>
  </body>
</html>
```

下記項目は必須のようです。

- DOCTYPE宣言の**`<!doctype html>`**
- AMP記事と示す**`<html amp>`**
- 文字コードの**`<meta charset="utf-8">`**
- 何もしないと重複コンテンツと見なされる場合もあるので、元記事を示すcanonical設定の**`<link rel="canonical">`**
- レスポンシブにするために表示領域を設定する**`<meta name="viewport">`**
- AMPで指定されているstyleの**`<style amp-boilerplate>`**
- AMP JSライブラリの**`<script async src="https://cdn.ampproject.org/v0.js"></script>`**

構造化マークアップについては、スマホのGoogle検索結果に表示されるトップニュースへ配信する場合などは必要になります。

また、AMP記事でコメントアウトは利用できないので、上記コードをそのままコピペするとエラーになります :frowning:

## validationチェック
AMPのバリデーションチェック方法は4つあります。

- AMP対応ページのURLに**#development=1**をつけてアクセスし、開発者コンソールを確認する
- [Webインタフェース](https://validator.ampproject.org/)の利用
- Chrome拡張機能の「[AMP Validator](https://chrome.google.com/webstore/detail/amp-validator/nmoffdblmcmgeicmolmhobpoocbbmknc)」を利用
- [コマンドラインツール](https://www.npmjs.com/package/amphtml-validator)を利用

開発環境で確認できる&手軽な、開発者コンソールでの確認or拡張機能が良さそうな気がしています。
上記以外にも、[Google Search Console](https://support.google.com/webmasters/answer/4559176?hl=ja)を利用する方法もあるようです。

参考：[使いやすく新登場、Web版「AMPテストツール」活用法](https://seopack.jp/seoblog/20160623-amp-web-tools/)
ドキュメント：[AMP > Guides > validate AMP Pages](https://www.ampproject.org/docs/guides/validate)

また、（手遅れ感がありますが）AMPのエラーページに表示される「**Debug original page.**」からデバッグすることもできます。
![amp_valid_error.png](https://qiita-image-store.s3.amazonaws.com/0/42253/ad35c93d-b6c8-0698-230a-41f2015f7940.png)
（エラーページはこんな悲しい画面が…）

## CSS
CSSは通常の`<style>`でなく`<style amp-custom>`の中に記述します。
**`<style amp-custom>`が使えるのはファイル内に1回のみ。**

```html
<!-- ex. <style amp-custom> -->
<head>
  <meta charset="utf-8">
  ...省略...
  <style amp-custom>
    a {
      color: #333;
      font-size: 14px;
    }
    a:hover {
      opacity: .8;
    }
  </style>
  ...省略...
</head>
```
また、`<link rel="stylesheet">`は特定のフォントを利用するとき以外は使えないので、**基本的には外部のCSSファイルを読み込めません。**
sassなど、プリプロセッサを利用する場合は下記のように`<style amp-custom>`内にincludeすることで利用できるようです。

```html
<style amp-custom>
  {% include "/assets/css/main.min.css" %}
</style>
```

Railsだとこのような方法も：[RailsアプリのAMP対応をSassで快適に](http://qiita.com/niba1122/items/0a91673f7a21726fa05e)

### そのほかCSSの制約（よく使いそうなところ）

| 要素 | 制約 | ex                            |
|------------+---------+----------------------|
| `!important` | 使えない |:heavy_multiplication_x: `img{ width: 100% !important; }`|
| 擬似クラス | `amp-`から始まらないタグには使える| :heavy_multiplication_x: `amp-img:hover{ opacity: .8; }` |
|            |                             | :o: `img:hover{ opacity: .8; }` |
| `behavior`, `-moz-binding` | セキュリティ的な理由で使えない | |
| `-amp-`や`i-amp`から始まるクラス/ID | AMPの予約語等として使われているので設定できない | |
など。ほかにもあります。
ドキュメント：[AMP > Guides > Styling&Layout > Supported CSS](https://www.ampproject.org/docs/guides/responsive/style_pages)

### フォント
外部のフォントを利用する方法は2つあります。
1. `<link>`タグを利用する
2. `@font-face`を利用する

#### 1.linkタグ
`<link>`タグを利用する場合は普段Webフォントを利用するときと同じイメージ。

```html
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Tangerine">
```

ただし、利用できるフォントに制限があり、現時点では下記のみ対応しています（この制限があるので外部CSSが利用できない）

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

#### 2.font-face
`@font-face`を利用する場合は制限はないようです。

```html
<style amp-custom>
  @font-face {
    font-family: "Bitstream Vera Serif Bold";
    src: url("https://somedomain.org/VeraSeBd.ttf");
  }

  body {
    font-family: "Bitstream Vera Serif Bold", serif;
  }
</style>
```

ドキュメント：[AMP > Guides > Styling&Layout > Custom fonts](https://www.ampproject.org/docs/guides/responsive/custom_fonts)

## HTMLタグ
`p`タグや`a`タグなど、HTMLタグそのまま利用できるものもありますが、いくつかのHTMLタグはAMP用のタグに変換する必要があります。

### imgタグ
`<img>`は`<amp-img>`へ変換します。

- 変換  
width,height(,layout)を指定する  

```html
<img src="hoge.jpg">
↓
<amp-img src="hoge.jpg" width="264" height="96"></amp-img>
```

`amp-img`タグでは画像サイズの指定が必須になります。
「いい感じ」に表示させようとするとちょっと考えてしまうところですが、下記記事が参考になりました。
参考：[サイズのわからない画像のAMP対応](http://qiita.com/narikei/items/50c0c805846c0bd69423)
ドキュメント：[AMP > Guides > Include images & Video](https://www.ampproject.org/docs/guides/amp_replacements)

### iframe
GoogleMapの埋め込みなど、`<iframe>`は`<amp-iframe>`へ変換します。

- `<head>`内で読み込むライブラリ

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

- 変換  
`sandbox`、`layout` を追加

```html
<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3159.4501403248655!2d140.36441641531366!3d37.63861997978452!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x5f8a9ef672ca6aa3%3A0xc13457f76f17515b!2z5p2x5YyX44K144OV44Kh44Oq44OR44O844Kv!5e0!3m2!1sja!2sjp!4v1481616609367" width="600" height="450" frameborder="0" style="border:0" allowfullscreen></iframe>
↓
<!-- srcが長いので改行 -->
<amp-iframe
  src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3159.4501403248655!2d140.36441641531366!3d37.63861997978452!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x5f8a9ef672ca6aa3%3A0xc13457f76f17515b!2z5p2x5YyX44K144OV44Kh44Oq44OR44O844Kv!5e0!3m2!1sja!2sjp!4v1481616609367"
  width="600"
  height="450"
  sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox"
  layout="responsive"
  frameborder="0"
></amp-iframe>
```

ドキュメント：[AMP > Guides > Include Iframes](https://www.ampproject.org/docs/guides/iframes)

### iframe(case. YouTube)
YouTubeの埋め込みiframeの場合は、`<amp-youtube>`があるのでそちらに変換

- `<head>`内で読み込むライブラリ

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

- 変換  
iframeのsrcに **動画のリンク** があるので、そこから動画IDを取得して **amp-youtubeタグ の data-videoid属性** に設定する 
`layout`を追加  
`frameborder`、`allowfullscreen`は使えないので削除（もしくは`data-param-frameborder`などにする）

```html
<iframe width="560" height="315" src="https://www.youtube.com/embed/YOUTUBE_VIDEO_ID" frameborder="0" allowfullscreen></iframe>
↓
<amp-youtube data-videoid="YOUTUBE_VIDEO_ID" layout="responsive" width="560" height="315"></amp-youtube>
```

ドキュメント：[AMP > Reference > Components/Tags > amp-youtube](https://www.ampproject.org/docs/reference/components/amp-youtube)

### 属性
- `onclick`や`onmouseover`など、`on〜`系の属性は利用できない
- （タグによって）`name`属性、style属性は利用できない

などなど

## SNSボタン
SNSボタンはすべて[amp-social-share](https://www.ampproject.org/docs/reference/components/amp-social-share)タグになります。
AMP側であらかじめ設定されているサービスは、`type`属性でサービス(twitterやfacebookなど)を指定するだけで利用できます。
`type`属性で指定できないものは、`data-share-endpoint`属性にURLを設定することで利用できるようになるようです。

Twitterの`data-via`など、シェア時に渡す属性があれば`data-param-via`など、`data-param-xxx`の形で記述することができます。

- `<head>`内で読み込むライブラリ

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

- 設定

```html
<!-- 一番シンプルな形 -->
<amp-social-share type="twitter"></amp-social-share>
<!-- ツイートフォームに「＠hogeさんから」をつける場合 -->
<amp-social-share type="twitter" data-param-via="hoge"></amp-social-share>
<!-- タイトルを指定する場合（デフォルトはページタイトル -->
<amp-social-share type="twitter" data-param-text="title sample"></amp-social-share>

<!-- facbeookシェアの場合はapp_idが必要 -->
<amp-social-share type="facebook" data-param-app_id="xxxxx">

<!-- LINEなどtypeに用意されていないもの -->
<amp-social-share type="line" data-share-endpoint="https://line.me/ti/p/xxxxx'>LINE</amp-social-share>
```

今のところ

- twitter
- facebook
- pinterest
- linkedin
- gplus
- tumblr
- email

のみ`type`属性の指定で設置できます。

ドキュメント：[AMP > Reference > Components/Tags > amp-social-share](https://www.ampproject.org/docs/reference/components/amp-social-share)

### 埋め込みタグ
#### Twitter
Twitterの埋め込みツイートは`<amp-twitter>`に変換

- `<head>`内で読み込むライブラリ

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

- 変換  
埋め込みタグの中にあるツイート日に **ツイート詳細のリンク** があるので、そこからツイートIDを取得して **amp-twitterタグ の data-tweetid属性** に設定する  
`script`タグは利用できないので、削除する

```html
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">月日は百代の過客にして、行かふ年も又旅人也。</p>松尾芭蕉 (＠matshuo_basho) <a href="https://twitter.com/matshuo_basho/status/TWEET_ID">2016年12月13日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
↓
<amp-twitter data-tweetid="TWEET_ID" width="100" height="100" layout="responsive"></amp-twitter>
```

ドキュメント：[AMP > Referernce > Components/Tags > amp-twitter](https://www.ampproject.org/docs/reference/components/amp-twitter)

#### Instagram
Instagramの埋め込みは`<amp-instagram>`に変換

- `<head>`内で読み込むライブラリ

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

- 変換  
埋め込みHTMLの中にある「hogeが投稿した写真」というテキストに**ポストURLのリンク**があるので、そこからポストIDを取得して **amp-instagramタグ の data-shortcode属性** に設定  
`script`タグは利用できないので、削除する

```html
<blockquote class="instagram-media" data-instgrm-version="7" style=" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><div style="padding:8px;"> <div style=" background:#F8F8F8; line-height:0; margin-top:40px; padding:50.0% 0; text-align:center; width:100%;"> <div style=" background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAYYAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;"></div></div><p style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px;"><a href="https://www.instagram.com/p/POST_ID/" style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; font-style:normal;" target="_blank">@hogeが投稿した写真</a> - <time style=" font-family:Arial,sans-serif; font-size:14px; line-height:17px;" datetime="2015-09-20T01:40:12+00:00">2015 9月 19 6:40午後 PDT</time></p></div></blockquote>
<script async defer src="//platform.instagram.com/en_US/embeds.js"></script>
↓
<amp-instagram data-shortcode='POST_ID' width='1' height='1' layout='responsive'></amp-instagram>
```

ドキュメント：[AMP > Reference > Components/Tags > amp-instagram](https://www.ampproject.org/docs/reference/components/amp-instagram)

#### Facebook
facebookの埋め込み投稿は`<amp-facebook>`に変換

- `<head>`内で読み込むライブラリ

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

- 変換  
埋め込みのiframeに **動画のリンク** があるので、そこからURLを取得して **amp-facebookタグ の data-href属性** に設定する

```html
<iframe src="https://www.facebook.com/plugins/post.php?href=https%3A%2F%2Fwww.facebook.com%matsuo_basho%2Fposts%xxxxxxx&width=500&show_text=true&appId=xxxxxxxxxxx&height=553" width="500" height="553" style="border:none;overflow:hidden" scrolling="no" frameborder="0" allowTransparency="true"></iframe>
↓
<amp-facebook width=486 height=657 layout="responsive" data-href="https://www.facebook.com/matsuo_basho/posts/xxxxxxx"></amp-facebook>
```

ドキュメント：[AMP > Reference > Components/Tags > amp-facebook](https://www.ampproject.org/docs/reference/components/amp-facebook)

## GA計測
### GAの場合
GAタグを直接埋めて、トリガーを記述していきます。

- `<head>`内で読み込むライブラリ

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

ページの本文にGAのトラッキング設定を追加するので、`<body>`の下あたりに`<amp-analytics>`を追加します。
`type`属性は`googleanalytics`で、


- pageview: ページ トラッキング用
- event: イベント トラッキング用
- social: ソーシャル トラッキング用

ex. pageview+ソーシャルイベント+クリックイベントを計測する場合

```html
<!-- pageviewを計測する場合 -->
<amp-analytics type="googleanalytics" id="analytics1">
  <script type="application/json">
    {
      // 計測するGAアカウントID
      "vars": {
        "account": "UA-XXXXX-X"
      },
      // 計測するもののトリガーの設定
      "triggers": {
        // pageviewの計測
        "trackPageview": {
          "on": "visible",
          "request": "pageview",
          "vars": {
            "title": "奥の細道"
          }
        },
        // ソーシャルイベントの計測
        "trackClickOnTwitterLink": {
          "on": "click",
          "selector": "#twitter",
          "request": "social",
          "vars": {
            "socialNetwork": "twitter",
            "socialAction": "ツイート",
            "socialTarget": "/hosomichi.html"
          }
        },
        // クリックイベントの計測
        "trackClickToSaruminoLink" : {
        "on": "click",
        "selector": "#to_sarumino",
        "request": "event",
        "vars": {
          "eventCategory": "序文",
          "eventAction": "リンククリック"
        }
      }
    }
  </script>
</amp-analytics>
```

参考：[Googleアナリティクス > AMP ページにアナリティクスを追加する](https://developers.google.com/analytics/devguides/collection/amp-analytics/)

### GTMを利用する場合
おなじみ[Googleタグマネージャ](https://tagmanager.google.com/)
GTMでコンテナを作成する際に、「コンテナの使用場所」で**AMP**を選択することで、AMPでもGTMを利用できるようになります。
<img width="1127" alt="スクリーンショット_2016-12-17_2_09_07.png" src="https://qiita-image-store.s3.amazonaws.com/0/42253/726b5954-186a-06b9-250f-e0f34e5d3d81.png">

AMP用のコンテナを作成したら、「Googleタグマネージャのインストール」に記述されている指示に従って`amp-analytics`タグを設定します。

```html
<head>
  ...省略...
  <!-- AMP Analytics -->
  <script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script>
</head>
<body>
  <!-- Google Tag Manager -->
  <amp-analytics config="https://www.googletagmanager.com/amp.json?id=GTM-XXXXXXX&gtm.url=SOURCE_URL" data-credentials="include"></amp-analytics>
</body>
```

うっかりコンテナの種類がウェブのタグを使うとエラーでやられます。

以降は普通にGTMを使う感覚でページビューやイベント送信、ソーシャル等のトラッキング設定を行えます。
ex. ページビュートラッキング
<img width="1112" alt="スクリーンショット 2016-12-17 11.43.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/42253/c1586b6a-7abc-d7f7-941c-8697da2cb4b6.png">


# まとめ
AMPページでエラーが大量発生していたときは「これは…アカン…:scream:」となっていましたが、無事エラー解消ができて一安心しています。今年も年を越せそうです。
ただ、タグの変換が発生するので、上がってくる記事に予期せぬタグがあったとしてもうまくエラー回避＆柔軟に対応できるようにしておきたいなぁと、こっそり思いました。

補足：
[AMP BY EXAMPLE](https://ampbyexample.com/)という、実装例が掲載されているところもあるので、困ったときにチラッと覗くと幸せになれました。