Accelerated Mobile Pages Foundations

1. Overview

In this codelab, you'll learn how to build Accelerated Mobile Pages – or AMP for short. To achieve this you will implement a simple news article web page that conforms to the AMP specifications while incorporating several typical web features commonly used on mobile news sites.

What you'll learn

  • How AMP improves the user experience of the mobile web.
  • The foundations of an AMP site.
  • AMP's limitations.
  • How AMP's web components solve common news site problems.
  • How to validate your AMP.
  • How to prepare your AMP for Google Search.

What you'll need

  • The sample code
  • Python (preferably 2.7) or the Chrome 200 OK Web Server extension
  • Chrome (or an equivalent browser that can inspect the JavaScript console)
  • Code Editor (for example Atom, Sublime, Notepad++)

2. Get the sample code

You can either download all the sample code to your computer:

...or clone the GitHub repository from the command line:

$ git clone https://github.com/googlecodelabs/accelerated-mobile-pages-foundations.git

You will download a ZIP file containing several example resources files and the starting article.html page.

Unzip the folder and navigate to the directory via the command line on your computer.

3. Run the sample page

In order to test our sample page we need to access the files from a web server. There are several ways to create a temporary local web server for the purposes of testing. For this code lab we will provide instructions for 3 options available:

  • The Google Chrome app "Web Server for Chrome" - This is the recommended approach as it is the simplest and most cross platform solution available. Note: this approach requires Google Chrome to be installed.
  • Firebase Hosting - An alternative option if you're also interested in exploring our new static asset hosting platform "Firebase Hosting". SSL-enabled by default.
  • A local HTTP Python Server - Requires access to the command-line.

Option #1: Web Server for Chrome

You can find the "Web Server for Chrome" app at this link on the Chrome Web Store.

4c1bf1095afed87a.png

After installing the Chrome App you must point the app at a particular folder via the "Choose Folder" button. For this code lab you should select the folder where you unzipped the code lab example files.

Additionally you should tick the "Automatically show index.html" option and set the port to "8000". You will need to restart the web server for these changes to take effect.

Access this URL via:

http://localhost:8000/article.html

If the above URL loads successfully you can continue to the next step.

Option #2: Firebase Hosting

If you are interested in exploring our new Firebase static web hosting you can follow the instructions available here to deploy your AMP site to a Firebase hosting URL.

Firebase Hosting is a static hosting provider that you can use to quickly deploy and host a static website and its assets; including HTML, CSS, and JavaScript files. Users benefit from reduced latency because static content is cached in a content delivery network (CDN) with points of presence (PoPs) located around the world.

Lastly, Firebase Hosting is always served via SSL so it's great for AMP and the web in general. If you're more interested in purely focusing on AMP then simply ignore this option.

Option #3: HTTP Python Server

If you don't use Chrome or you are struggling to install the Chrome extension you can also use Python from the command-line to fire up a local web server.

To run Python's built-in HTTP server from the command line simply execute the following:

python -m SimpleHTTPServer

And access this URL:

http://localhost:8000/article.html

4. Build a regular HTML page

In the downloaded zip file, you will find a file called article.html. This is the article we are creating an AMP equivalent page for.

Copy the code from the article.html sample and paste it into a new file. Save this file as article.amp.html.

Your article.amp.html file should look like the following now:

<!doctype html>
<html lang="en">
  <head>

    <title>News Article</title>

    <link href="base.css" rel="stylesheet" />

    <script type="text/javascript" src="base.js"></script>
  </head>
  <body>
    <header>
      News Site
    </header>
    <article>
      <h1>Article Name</h1>

      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam egestas tortor sapien, non tristique ligula accumsan eu.</p>
    </article>
    <img src="mountains.jpg">
  </body>
</html>

This is an intentionally simplistic page with common static news article elements: CSS, JavaScript, and an image tag.

Our AMP version of the article is just a copy of the original article right now. Let's convert it to an AMP. To begin, we will add the AMP JavaScript library file and view what errors appear when the AMP validator is turned on.

To include the AMP library, add this line to the bottom of the <head> tag:

<script async src="https://cdn.ampproject.org/v0.js"></script>

Now let's load the new article.amp.html page in our browser via the following link and open the Developer Console in Chrome via Menu > More Tools > Developer Tools:

efc352f418f35761.png

Now inspect the JavaScript output in the developer console. Make sure you have the Console tab selected:

597d53fae21a0a60.png

You should see this log appearing:

Powered by AMP ⚡ HTML

Now to enable the AMP validator add this fragment identifier to your URL:

#development=1

For example:

http://localhost:8000/article.amp.html#development=1

You may need to manually refresh the page in your browser. You can manually refresh a page in your browser by pressing this button:

3cc0680e695b804d.png

You should receive several validation errors:

Screen Shot 2016-05-03 at 10.09.51 AM.png

Even though AMP stands for Accelerated Mobile Pages, it can be used to build responsive pages that render well on all screen sizes. For more information, check the Responsive Web Design section of the Google Developers website.

To simulate mobile device experience in the Chrome Developer Tools. Click the mobile phone device icon here:

46d475a36472b495.png

Now select a mobile device (for example a "Pixel 2") from this menu:

f65e7b38557a5807.png

You should see a mobile simulated resolution in your browser such as this:

7da6c754afb2adca.png

Now we're ready to get to work! Let's step through the validation errors one by one and address how they relate to AMP.

5. Resolve validation errors

Charset required

We will begin by fixing the following error:

The mandatory tag 'meta charset=utf-8' is missing or incorrect.

For correct displaying of text, AMP requires that the charset for the page is set. It also must be the first child of the head tag. The reason for this is to avoid re-interpreting content that was added before the meta charset tag.

Add the following code as the first line of the head tag:

<meta charset="utf-8" />  

Save the file, reload the page and check that this error is not showing anymore.

Every AMP document is required to have a link referencing the canonical page. So, let's add the link to our original article.

Go ahead and add the following code below the <meta charset="utf-8" /> tag:

<link rel="canonical" href="/article.html">

Now, restart your webserver if needed and reload the page. Although there are still plenty of errors to fix, the "AMP files are required to have a <link rel=canonical> tag" error is not there anymore.

AMP attribute required

AMP requires an attribute on the root HTML element of a page to declare the page as an AMP document:

The mandatory attribute '⚡' is missing in tag 'html ⚡ for top-level html'
The mandatory tag 'html ⚡ for top-level html' is missing or incorrect.

This is resolved simply by adding the ⚡ attribute to the <html> tag as so:

<!doctype html>
<html ⚡ lang="en">
  <head>
...

Now, go ahead, reload the page and check that both errors are gone.

Viewport required

Next we will tackle the following error:

The mandatory tag 'meta name=viewport' is missing or incorrect.

AMP requires the definition of a width and minimum-scale for the viewport. These values must be defined as device-width and 1, respectively. The viewport is a common tag included in the <head> of an HTML page.

This is best rectified with the following HTML snippet being added to the <head> tag. Add the following meta tag:

<!doctype html>
<html ⚡ lang="en">
  <head>
    <meta charset="utf-8" />

    <link rel="canonical" href="/article.html">

    <!-- The following is the meta tag and viewport information we must add to the page: -->
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">

...

These are the only valid values for width and minimum-scale in AMP. Defining initial-scale is not mandatory but it's a common inclusion in mobile web development and recommended. You can read more about the viewport and responsive design here.

As before, reload the page and check if the error has disappeared.

External stylesheets

The following error is related to our use of stylesheets:

The attribute 'href' in tag 'link rel=stylesheet for fonts' is set to the invalid value 'base.css'.

Specifically this is complaining about the following stylesheet link tag in our <head> tag:

<link href="base.css" rel="stylesheet" />

The problem is that this is an external stylesheet reference. In AMP, to keep the load times of documents as fast as possible developers are not allowed to include external stylesheets. Instead all stylesheet rules must be included inline in the AMP document.

Therefore, remove the link tag in the <head> and replace it with an inline tag such as the following:

<style amp-custom>

body {
  width: auto;
  margin: 0;
  padding: 0;
}

...

</style>

The contents of the style tag should be directly copied from the base.css file in your project directory. The amp-custom attribute on the style tag is mandatory.

Once again, reload the page and check if the stylesheets error has disappeared.

Third-Party JavaScript

While stylesheets can be reworked relatively easily with AMP via inlining, the same is not true for JavaScript.

The tag 'script' is disallowed except in specific forms.

In AMP, user generated scripts are not allowed. Scripts in AMP are only allowed if they follow two major requirements::

  • All JavaScript must be asynchronous, i.e. include the async attribute in the script tag.
  • Only the AMP library and AMP components can be included.

This effectively rules out the use of all third-party JavaScript. There is one exception – third-party JavaScript may be used in iframes.

Try opening the external base.js file. What do you see? The file should be empty of any JavaScript code and only include a comment of information such as this:

/*

This external JavaScript file is intentionally empty.

Its purpose is merely to demonstrate the AMP validation error related to the use of external JavaScript files.

*/

Considering this external JavaScript file is not a functional component of our website we can safely remove the reference entirely.

Remove the following external JavaScript reference from your document:

<script type="text/javascript" src="base.js"></script>

Now reload the page and check that the script error has disappeared.

The AMP CSS boilerplate

The mandatory tag 'noscript enclosure for boilerplate' is missing or incorrect.
The mandatory tag 'head > style : boilerplate' is missing or incorrect.
The mandatory tag 'noscript > style : boilerplate' is missing or incorrect.

The next errors refer to two missing tags in the <head> tag. Every AMP document requires these tags to be included:

<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>

Add the above code snippet to the bottom of the <head> tag of your document.

The first tag makes the contents of the page invisible until the AMP JavaScript library updates the body tag to be visible again once the page's content is ready to render. AMP does this to prevent content of the page to appear that has not yet been styled. This ensures that the user experience feels truly instant as the page's content appears all at once and everything above the fold is rendered together. The second tag reverts this logic if JavaScript is disabled in the browser.

The amp-img tag

The tag 'img' may only appear as a descendant of tag 'noscript'. Did you mean 'amp-img'?

AMP has a web component specifically designed to replace the image tag, called amp-img:

<amp-img src="mountains.jpg"></amp-img>

Try including the above amp-img tag and run the validator again. You should receive several new errors:

AMP-IMG# Layout not supported for: container
The implied layout 'CONTAINER' is not supported by tag 'amp-img'.

Why did amp-img trigger another error? Because amp-img is not a direct substitute of the traditional HTML img tag. There are additional requirements when using amp-img.

Layout System

This error is telling us that amp-img does not support the layout type ‘container'. One of the most important concepts in AMP's design is its focus on reducing the amount of DOM reflow required to render its web pages.

To reduce DOM reflow AMP includes a layout system for ensuring the layout of the page is as rigid as possible as early as possible in the lifecycle of downloading and rendering the page.

The layout system allows for elements on a page to be positioned and scaled in a variety of ways – fixed dimensions, responsive design, fixed height and more.

a6149f5043618189.png

In our case the layout system inferred our layout type for the amp-img as the container type. However, the container type is for elements which contain children elements and is incompatible with the amp-img tag which is the reason for this error.

Why was the container type inferred? Because we did not specify a height attribute for the amp-img tag. In HTML, reflow can be reduced by always specifying a fixed width and height for elements on a page. In AMP, it is recommended to define the width and height for amp-img elements as this allows AMP to understand the aspect ratio of the element.

Set the width and height as follows:

<amp-img src="mountains.jpg" width="266" height="150"></amp-img>

Refresh the page and check the validator - you should no longer see any errors! However, the image doesn't look so great as it is awkwardly positioned on the page. It would be great if we could scale the image to responsively stretch and fit the page no matter the screen size.

a7f2a768e9da1a25.png

Surprisingly, defining the width and height does not restrict the element to an entirely fixed size. The AMP layout system can position and scale the element in a variety of ways by knowing its aspect ratio - the layout attribute informs AMP of how you want the element positioned and scaled.

By setting the layout attribute to responsive we can achieve this:

<amp-img src="mountains.jpg" layout="responsive" width="266" height="150"></amp-img>

Voila! Our image is in the correct aspect ratio and responsively fills the width of the screen.

de0cbbe31eacbbb1.png

Success!

Now your AMP document should look something along the lines of this:

<!doctype html>
<html ⚡ lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">    

    <link rel="canonical" href="/article.html">
    <link rel="shortcut icon" href="amp_favicon.png">

    <title>News Article</title>

    <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>
    <style amp-custom>
      body {
        width: auto;
        margin: 0;
        padding: 0;
      }

      header {
        background: Tomato;
        color: white;
        font-size: 2em;
        text-align: center;
      }

      h1 {
        margin: 0;
        padding: 0.5em;
        background: white;
        box-shadow: 0px 3px 5px grey;
      }

      p {
        padding: 0.5em;
        margin: 0.5em;
      }
    </style>
    <script async src="https://cdn.ampproject.org/v0.js"></script>  
  </head>
  <body>
    <header>
      News Site
    </header>
    <article>
      <h1>Article Name</h1>

      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam egestas tortor sapien, non tristique ligula accumsan eu.</p>

      <amp-img src="mountains.jpg" layout="responsive" width="266" height="150"></amp-img>
    </article>
  </body>
</html>

Refresh the page and look at the console output. You should be greeted with the following message:

AMP validation successful.

F****requently Asked Questions

6. Canonical URLs, Metadata & Search

Part of the new AMP initiative is the highlighting of valid AMP documents in the Google search results interface as part of a new carousel interface. This interface provides a better user experience to people searching for articles on the web. For this experience to be the best it can be, the pages included must meet certain criteria beyond passing the AMP validator.

This step provides an overview of the full requirements.

Linking Canonical Pages and AMP Documents

AMP aims to make the web faster and, even though the project was more focused on static content on it's early days, the addition of components like amp-bind, make it a good fit for a wide variety of sites, such as news publishers, e-commerces, travel websites, blogs and others.

However, It's important to understand the full scope of how AMP should sit inside a website's structure. Even though AMP can be used to build whole websites, many publishers prefer to use it as with the paired approach, where AMP documents are generated as an accompaniment to the regular HTML articles that a publisher would host on their website.

7152b1ef38f00f36.png

Canonical linking in regular HTML pages is a common technique for declaring which page should be considered the preferred page when multiple pages include the same content. Since AMP documents can be generated to be available alongside the traditional article pages of a website we should treat the traditional HTML pages as the "canonical" pages.

We already took the first step to achieve this in our AMP document by including a link tag in the <head> back to the canonical page:

<link rel="canonical" href="/article.html">

The next step is to link the canonical article to the AMP page. This is achieved by including a <link rel="amphtml"> tag to the <head> section of the canonical article.

Add the following code into the <head> section of the article.html file:

<link rel="amphtml" href="/article.amp.html">

The following diagram illustrates the directions of link tags:

a880b625c10ffd84.png

It's necessary to setup this bidirectional linking in order for the Google search crawler to understand the relationship between our regular HTML canonical document and our AMP document. If no links were provided then it wouldn't necessarily be clear to the crawler as to which articles are the "AMP versions" of the regular HTML documents. By explicitly providing these links we ensure there is no ambiguity!

Schema.org Search Engine Metadata

Another requirement for AMP documents to appear in the new carousel interface is adherence to the Search Engine Metadata specification of Schema.org. This metadata is included in the <head> tag of your documents via an application/ld+json type script tag.

Add the following code to the bottom of the <head> section of your AMP document:

<script type="application/ld+json">
{
 "@context": "http://schema.org",
 "@type": "NewsArticle",
 "mainEntityOfPage":{
   "@type":"WebPage",
   "@id":"https://example.com/my-article.html"
 },
 "headline": "My First AMP Article",
 "image": {
   "@type": "ImageObject",
   "url": "https://example.com/article_thumbnail1.jpg",
   "height": 800,
   "width": 800
 },
 "datePublished": "2015-02-05T08:00:00+08:00",
 "dateModified": "2015-02-05T09:20:00+08:00",
 "author": {
   "@type": "Person",
   "name": "John Doe"
 },
 "publisher": {
   "@type": "Organization",
   "name": "⚡ AMP Times",
   "logo": {
     "@type": "ImageObject",
     "url": "https://example.com/amptimes_logo.jpg",
     "width": 600,
     "height": 60
   }
 },
 "description": "My first experience in an AMPlified world"
}
</script>

Reload the page in the browser and double check that no AMP Validation errors were introduced.

Now, open the Structured Data Validation Tool in a new browser window and click "Test my markup". Then select the "Code Snippet" tab, copy the full source code from your AMP page and paste it into text editor panel of the validation tool, and click on "Run Test":

901b629036e0cd62.png

You should see something like this on the page:

ae8e16aff196e5a7.png

The key requirements for appearing in the new Google Search carousel for AMP powered news articles are the following:

  1. Make sure your AMP document validates.
  2. Reference your AMP document from your traditional HTML page via the <link> tag and vice versa.
  3. Include the Search Engine Metadata tag above.

Read more information on page discovery.

7. Congratulations!

You've finished the code lab and successfully explored many of the fundamental concepts of AMP documents.

Hopefully you have not only understood how these concepts and features can be implemented in an AMP document but also understand why AMP has been designed the way it has.

The following are some additional topics and links you might want to explore to amplify your skills even further!