Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

本当はお遊びで「ゴジラがどのゴジラか分類してみた」「ゴジラの出没地を予測してみた」というネタを書こうとしていました。@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とは

HTMLをAMP化する

AMP HTMLページの作成

AMP > Tutorials > Create Your AMP HTML Pageにサンプルがあります。ので、まるっと拝借。

<!-- 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つあります。

開発環境で確認できる&手軽な、開発者コンソールでの確認or拡張機能が良さそうな気がしています。
上記以外にも、Google Search Consoleを利用する方法もあるようです。

参考:使いやすく新登場、Web版「AMPテストツール」活用法
ドキュメント:AMP > Guides > validate AMP Pages

また、(手遅れ感がありますが)AMPのエラーページに表示される「Debug original page.」からデバッグすることもできます。
amp_valid_error.png
(エラーページはこんな悲しい画面が…)

CSS

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

<!-- 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することで利用できるようです。

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

Railsだとこのような方法も:RailsアプリのAMP対応をSassで快適に

そのほか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

フォント

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

1.linkタグ

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

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

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

2.font-face

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

<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

HTMLタグ

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

imgタグ

<img><amp-img>へ変換します。

  • 変換
    width,height(,layout)を指定する
<img src="hoge.jpg"><amp-img src="hoge.jpg" width="264" height="96"></amp-img>

amp-imgタグでは画像サイズの指定が必須になります。
「いい感じ」に表示させようとするとちょっと考えてしまうところですが、下記記事が参考になりました。
参考:サイズのわからない画像のAMP対応
ドキュメント:AMP > Guides > Include images & Video

iframe

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

  • <head>内で読み込むライブラリ
<script async custom-element="amp-iframe" src="https://cdn.ampproject.org/v0/amp-iframe-0.1.js"></script>
  • 変換
    sandboxlayout を追加
<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

iframe(case. YouTube)

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

  • <head>内で読み込むライブラリ
<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を追加
    frameborderallowfullscreenは使えないので削除(もしくはdata-param-frameborderなどにする)
<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

属性

  • onclickonmouseoverなど、on〜系の属性は利用できない
  • (タグによって)name属性、style属性は利用できない

などなど

SNSボタン

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

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

  • <head>内で読み込むライブラリ
<script async custom-element="amp-social-share" src="https://cdn.ampproject.org/v0/amp-social-share-0.1.js"></script>
  • 設定
<!-- 一番シンプルな形 -->
<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

埋め込みタグ

Twitter

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

  • <head>内で読み込むライブラリ
<script async custom-element="amp-twitter" src="https://cdn.ampproject.org/v0/amp-twitter-0.1.js"></script>
  • 変換
    埋め込みタグの中にあるツイート日に ツイート詳細のリンク があるので、そこからツイートIDを取得して amp-twitterタグ の data-tweetid属性 に設定する
    scriptタグは利用できないので、削除する
<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

Instagram

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

  • <head>内で読み込むライブラリ
<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タグは利用できないので、削除する
<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

Facebook

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

  • <head>内で読み込むライブラリ
<script async custom-element="amp-facebook" src="https://cdn.ampproject.org/v0/amp-facebook-0.1.js"></script>
  • 変換
    埋め込みのiframeに 動画のリンク があるので、そこからURLを取得して amp-facebookタグ の data-href属性 に設定する
<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

GA計測

GAの場合

GAタグを直接埋めて、トリガーを記述していきます。

  • <head>内で読み込むライブラリ
<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+ソーシャルイベント+クリックイベントを計測する場合

<!-- 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 ページにアナリティクスを追加する

GTMを利用する場合

おなじみGoogleタグマネージャ
GTMでコンテナを作成する際に、「コンテナの使用場所」でAMPを選択することで、AMPでもGTMを利用できるようになります。
スクリーンショット_2016-12-17_2_09_07.png

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

<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. ページビュートラッキング
スクリーンショット 2016-12-17 11.43.17.png

まとめ

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

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

s-mori
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした