<p>To revitalize this valuable post and expand a bit on what the accepted answer covers:</p>

<p>I've done this using the same template (with conditionals).</p>

<p>Since you're going to have to handle all of your routes manually anyways, I've set up a controller (in a plugin) to give me a little more control over what data these pages get.</p>

<p>By wrapping the renderTemplate method in my own, I'm adding context that can be used in templates to control how things are output.</p>

<pre><code>private function renderAmp($template, array $variables = array()){
        craft()-&gt;config-&gt;set('amp','');
        if($variables['amp'] == 'amp'){
            craft()-&gt;config-&gt;set('devMode',0);
            craft()-&gt;config-&gt;set('siteUrl',craft()-&gt;config-&gt;get('siteUrl').'/amp/');
            craft()-&gt;config-&gt;set('amp','/amp');
        }

        $this-&gt;renderTemplate($template, $variables);
    }
</code></pre>

<p>I use that config to generate a URL for entries that can be used globally. It sits in my plugin's service and looks something like this:</p>

<pre><code>public function getEntryUrl($entry){
        $channel = craft()-&gt;sections-&gt;getSectionById($entry-&gt;sectionId);
        $date = str_replace('-', '/', $entry-&gt;postDate);
        $slug = $entry-&gt;slug;

        $url = implode('/',
            array(
                craft()-&gt;config-&gt;get('amp'),
                $channel,
                $date,
                $slug
            )
        );

        return strtolower($url);
    }
</code></pre>

<p>And for completion's sake, my routes &amp; some useful stuff from my templates. Also, note -- I chose to prefix my slugs with amp instead of adding it to the end. Mostly preference, I guess.</p>

<p>Routes: </p>

<pre><code>// Primary
$routes = array(

    // News
    '(?P&lt;channel&gt;news)/(?P&lt;year&gt;\d{4})/(?P&lt;month&gt;\d{2})/(?P&lt;day&gt;\d{2})/(?P&lt;slug&gt;.*)/?$' =&gt; array('action' =&gt; 'pluginName/newsEntry'),
    '(?P&lt;channel&gt;news)/?$' =&gt; array('action' =&gt; 'pluginName/newsAll'),

    // Home
    '(?P&lt;slug&gt;.*)?/?$' =&gt; array('action' =&gt; 'pluginName/home'),

);

// Amp
$routes = array_combine(
    array_map(function($k){
        $pre = '^(?P&lt;amp&gt;amp)?/?';
        return $pre.$k;
    }, array_keys($routes)),
    $routes
);

return $routes;
</code></pre>

<p>Templates:</p>

<pre><code>{% if amp is empty %}

    {% set htmlTag = 'xmlns="http://www.w3.org/1999/xhtml" lang="en-US"' %}

    {% set head %}
        &lt;link rel="canonical" href="/{{ matches[0] }}"&gt;
        &lt;link rel="amphtml" href="/amp/{{ matches[0] }}"&gt;
        &lt;link rel="stylesheet" href="/css/main.css"&gt;
    {% endset %}

    {% set scripts %}
        &lt;script type="text/javascript" src="/js/main.js"&gt;&lt;/script&gt;
    {% endset %}

{% else %}

    {% set htmlTag = 'amp' %}

    {% set head %}
        &lt;link rel="canonical" href="/{{ matches[0]|slice(4) }}"&gt;
        &lt;meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"&gt;

        &lt;style amp-boilerplate&gt;&lt;/style&gt;

        &lt;script async src="https://cdn.ampproject.org/v0.js"&gt;&lt;/script&gt;

        &lt;style amp-custom&gt;
            {{ source('html/css/amp.css')|raw }}
        &lt;/style&gt;

        &lt;link href='https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css' rel='stylesheet' type='text/css'&gt;
    {% endset %}

    {% set scripts = '' %}

{% endif %}

// To output an entry's proper URL in a template:
craft.pluginName.getEntryUrl(entry)
</code></pre>

CC BY-SA 3.0
2016-07-05T21:35:05.787Z
2016-07-05T21:35:05.787Z
Jonny Asmar
<p>I wrote the <a href="https://github.com/nystudio107/seomatic" rel="nofollow noreferrer">SEOmatic plugin</a> -- AMP is really just a name for some best practices for web development that speed things up on mobile.  There isn't anything terribly special about it, I do most of what they list in their spec for websites already.</p>

<p>The "meta tags" that they want you to add are just some JSON-LD, which you can easily add on your own, or via SEOmatic's <code>renderJSONLD</code> function.</p>

<p>As for implementing AMP, you might find this helpful: <a href="https://nystudio107.com/blog/google-amp-should-you-care" rel="nofollow noreferrer">Google AMP: Should You Care?</a></p>

CC BY-SA 3.0
2016-03-11T16:22:11.677Z
AMP is a little more than just some best practices for mobile. It actually is a subset of HTML5 using custom tags like [``amp-img``](https://www.smashingmagazine.com/2016/02/everything-about-google-accelerated-mobile-pages/#amp-html-tags) so can it can control loading. Your plugin is helpful though!
RitterKnight
CC BY-SA 3.0
2017-12-23T00:06:17.093Z
Yes, AMP is DEFINITELY more than just methodologies. It's a very comprehensive library and as @RitterKnight mentioned a subset of HTML/CSS (and JavaScript/CSS; yes there are restrictions): https://www.ampproject.org/docs/reference/components

It also requires things like limiting your CSS & injecting it directly onto the page, which is - at best - debatably a best-practice unless you're operating in a cached environment like AMP.
Jonny Asmar
CC BY-SA 3.0
2017-12-31T18:39:46.187Z
Well, what I meant was that the things that make AMP fast are methodologies that you can implement yourself without AMP. AMP just enforces them, and provides functionality as you mentioned to make it easier to do.
andrew.welch
CC BY-SA 3.0
2016-03-11T01:50:06.953Z
2016-12-04T17:28:03.527Z
2016-12-04T17:28:03.527Z
andrew.welch
<p>You're asking kind of a loaded question but as far as Craft is concerned, you're in a good position to spit out exactly what you need as far as markup and styles go. AMP is more or less just a small subset of HTML.</p>
<p>When compared to something like WordPress, Craft is going to give you all the tools necessary to spit out an AMP page just by virtue of it doesn't dictate layout and styling nor include any extra fluff. And it provides easy routing features to make it easy to make different &quot;versions&quot;.</p>
<h1>Different Versions / Different Routes</h1>
<p>Depending on how your site is setup, you'll want <a href="http://www.sitepoint.com/an-introduction-to-googles-accelerated-mobile-pages-amp/" rel="noreferrer">different versions</a> of your content—one regular and one for AMP... not unlike the old <code>m</code> dot sites. (Taking it back to the old school WAP era I guess...)</p>
<p>Let's say you have a section called <code>News</code>.  If your entries URL Format looks like: <code>http://site/news/slug/</code>, you might want to have the AMP version look like <code>http://site/news/slug/amp</code>.</p>
<p>One way to do that in Craft is to setup a route. You can do that in Settings -&gt; Routes -&gt; New Route.</p>
<p><a href="https://i.sstatic.net/KRdUt.png" rel="noreferrer"><img src="https://i.sstatic.net/KRdUt.png" alt="enter image description here" /></a></p>
<p>That will load the <code>_amp.html</code> template inside a <code>news</code> folder. You'll have to do a little extra work to tell Craft where to pull the entry from since routes only load templates by default. Since we used the <code>slug</code> variable in our routes, we can use that to grab the entry from the news section and also set the <code>entry</code> variable.</p>
<pre><code>{% extends &quot;_layoutamp&quot; %}

{% set entry = craft.entries.section('news').slug(slug)[0] %}

{% block content %}
  ... rest of your content
{% endblock %}
</code></pre>
<p>The AMP docs start with a <a href="https://www.ampproject.org/docs/get_started/create/basic_markup.html" rel="noreferrer">simple skeleton</a>. I used <code>{% extends &quot;_layoutamp&quot; %}</code> in our <code>_amp</code> template so we need to make a  ``_layoutamp.html&quot; file to match inside Craft's templates folder.</p>
<pre><code>   {# _layoutamp.html #}
    &lt;!doctype html&gt;
    &lt;html amp lang=&quot;en&quot;&gt;
      &lt;head&gt;
        &lt;meta charset=&quot;utf-8&quot;&gt;
        &lt;title&gt;{{entry.title}}&lt;/title&gt;
        &lt;link rel=&quot;canonical&quot; href=&quot;{{entry.url}}&quot; /&gt;
        &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width,minimum-scale=1,initial-scale=1&quot;&gt;
        &lt;script type=&quot;application/ld+json&quot;&gt;
          {
            &quot;@context&quot;: &quot;http://schema.org&quot;,
            &quot;@type&quot;: &quot;NewsArticle&quot;,
            &quot;headline&quot;: &quot;{{entry.title}}&quot;,
            &quot;datePublished&quot;: &quot;{{entry.dateCreated.iso8601()}}&quot;,
            &quot;image&quot;: [
              &quot;logo.jpg&quot;
            ]
          }
        &lt;/script&gt;
&lt;style amp-boilerplate&gt;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}}&lt;/style&gt;&lt;noscript&gt;&lt;style amp-boilerplate&gt;body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}&lt;/style&gt;&lt;/noscript&gt;
        &lt;script async src=&quot;https://cdn.ampproject.org/v0.js&quot;&gt;&lt;/script&gt;
      &lt;/head&gt;
      &lt;body&gt;
        {% block content %}
           {# brings in the content from the _amp.html content block #}
        {% endblock %}
      &lt;/body&gt;
    &lt;/html&gt;
</code></pre>
<p>AMP <a href="https://www.ampproject.org/docs/get_started/create/basic_markup.html" rel="noreferrer">recommends</a> some metadata near the top, in the form of JSON. Easy enough to spit out the required fields in Twig.</p>
<h1>&quot;Linking&quot; to an AMP page</h1>
<p>You'll notice a <code>&lt;link rel=&quot;canonical&quot; href=&quot;{{entry.url}}&quot;&gt;</code> in that file as well to tell Google your main version is here.</p>
<p>On your &quot;normal&quot; page, you'll want to add a reference to the AMP page too. (I also like to set the <a href="https://yoast.com/rel-canonical/" rel="noreferrer">canonical</a> version as well for good measure.</p>
<pre><code>&lt;link rel=&quot;canonical&quot; href=&quot;{{entry.url}}&quot;&gt;
&lt;link rel=&quot;amphtml&quot; href=&quot;{{entry.url}}/amp&quot;&gt;
</code></pre>
<p>That will tell Google the AMP version is at the URL.</p>
<h1>Anything else?</h1>
<p>Pretty much the rest is up to you. AMP is pretty easy to setup but you still need to use their <a href="https://www.smashingmagazine.com/2016/02/everything-about-google-accelerated-mobile-pages/#amp-html-tags" rel="noreferrer">custom tags</a>.</p>
<p>Most notably, things like images and videos need to use custom tags like <code>amp-img</code> and <code>amp-video</code>, so the AMP runtime can intercept the loading of those assets and handle them.</p>
<p>Will be interesting to see how this affects page rank moving forward. Google confirmed it's <a href="http://searchengineland.com/google-amp-not-yet-a-search-ranking-signal-243498" rel="noreferrer">not a ranking signal</a> (yet) but that doesn't mean it won't be in the future.</p>

CC BY-SA 3.0
2015-12-15T11:55:25.687Z
Thank you for the awesomely detailed response. Will try my best to implement this!
RDMD
CC BY-SA 3.0
2015-12-15T16:17:16.873Z
Let me know how it works out. I'm actually going through the process of rebuilding our own site, you gave me a push to check it out so thanks for the reminder.
RitterKnight
CC BY-SA 3.0
2015-12-16T06:26:58.430Z
Sure thing! Will do. I think to make this easier, existing SEO plugins available for Craft could work toward include this within their scope for both Facebook Instant Articles & for Google AMP.
RDMD
CC BY-SA 3.0
2016-03-11T16:22:32.613Z
Updated my answer a bit; they've changed the default boilerplate since.
RitterKnight
CC BY-SA 4.0
2021-01-14T17:34:29.683Z
I love that stackexchange has people like you @RitterKnight. Thanks for this awesome answer!
Bryce
CC BY-SA 4.0
2021-01-14T23:24:16.933Z
@Bryce Glad you found it useful!
RitterKnight
CC BY-SA 3.0
2015-12-14T19:10:11.990Z
2016-03-11T16:18:22.693Z
2020-06-17T08:56:27.903Z
RitterKnight
<p>Does anyone have any thoughts on automating the implementation Google's new AMP article markup?</p>

<p><a href="https://www.ampproject.org/docs/get_started/create/basic_markup.html">https://www.ampproject.org/docs/get_started/create/basic_markup.html</a></p>

<p>Also see:
<a href="http://venturebeat.com/2015/12/09/google-will-start-sending-search-traffic-to-fast-loading-amp-news-articles-in-february-2016/">Google will start sending search traffic to fast-loading AMP news articles in February 2016</a> </p>

<p>Thanks!</p>

<templating><seo>
Approaching Google AMP
# Approaching Google AMP

(Asked by: username_0 on 2015-12-14)

Does anyone have any thoughts on automating the implementation Google's new AMP article markup?

<https://www.ampproject.org/docs/get_started/create/basic_markup.html>

Also see:
[Google will start sending search traffic to fast-loading AMP news articles in February 2016](http://venturebeat.com/2015/12/09/google-will-start-sending-search-traffic-to-fast-loading-amp-news-articles-in-february-2016/)

Thanks!

**Tags:** templating, seo


---

## 3 answers

### Answer by username_3 on 2015-12-14. Score: 15 | Accepted answer

You're asking kind of a loaded question but as far as Craft is concerned, you're in a good position to spit out exactly what you need as far as markup and styles go. AMP is more or less just a small subset of HTML.
When compared to something like WordPress, Craft is going to give you all the tools necessary to spit out an AMP page just by virtue of it doesn't dictate layout and styling nor include any extra fluff. And it provides easy routing features to make it easy to make different "versions".
Different Versions / Different Routes
Depending on how your site is setup, you'll want different versions of your content—one regular and one for AMP... not unlike the old m dot sites. (Taking it back to the old school WAP era I guess...)
Let's say you have a section called News.  If your entries URL Format looks like: http://site/news/slug/, you might want to have the AMP version look like http://site/news/slug/amp.
One way to do that in Craft is to setup a route. You can do that in Settings -> Routes -> New Route.

That will load the _amp.html template inside a news folder. You'll have to do a little extra work to tell Craft where to pull the entry from since routes only load templates by default. Since we used the slug variable in our routes, we can use that to grab the entry from the news section and also set the entry variable.
{% extends "_layoutamp" %}

{% set entry = craft.entries.section('news').slug(slug)[0] %}

{% block content %}
  ... rest of your content
{% endblock %}

The AMP docs start with a simple skeleton. I used {% extends "_layoutamp" %} in our _amp template so we need to make a  ``_layoutamp.html" file to match inside Craft's templates folder.
   {# _layoutamp.html #}
    
    
      
        
        {{entry.title}}
        
        
        

        
      
      
        {% block content %}
           {# brings in the content from the _amp.html content block #}
        {% endblock %}
      
    

AMP recommends some metadata near the top, in the form of JSON. Easy enough to spit out the required fields in Twig.
"Linking" to an AMP page
You'll notice a  in that file as well to tell Google your main version is here.
On your "normal" page, you'll want to add a reference to the AMP page too. (I also like to set the canonical version as well for good measure.



That will tell Google the AMP version is at the URL.
Anything else?
Pretty much the rest is up to you. AMP is pretty easy to setup but you still need to use their custom tags.
Most notably, things like images and videos need to use custom tags like amp-img and amp-video, so the AMP runtime can intercept the loading of those assets and handle them.
Will be interesting to see how this affects page rank moving forward. Google confirmed it's not a ranking signal (yet) but that doesn't mean it won't be in the future.

> **Comments:**
> **username_0**: Thank you for the awesomely detailed response. Will try my best to implement this!  
> **username_3**: Let me know how it works out. I'm actually going through the process of rebuilding our own site, you gave me a push to check it out so thanks for the reminder.  
> **username_0**: Sure thing! Will do. I think to make this easier, existing SEO plugins available for Craft could work toward include this within their scope for both Facebook Instant Articles & for Google AMP.  
> **username_3**: Updated my answer a bit; they've changed the default boilerplate since.  
> **username_4**: I love that stackexchange has people like you @username_3. Thanks for this awesome answer!  
> **username_3**: @username_4 Glad you found it useful!  

---

### Answer by username_1 on 2016-07-05. Score: 3

To revitalize this valuable post and expand a bit on what the accepted answer covers:
I've done this using the same template (with conditionals).
Since you're going to have to handle all of your routes manually anyways, I've set up a controller (in a plugin) to give me a little more control over what data these pages get.
By wrapping the renderTemplate method in my own, I'm adding context that can be used in templates to control how things are output.
private function renderAmp($template, array $variables = array()){
        craft()->config->set('amp','');
        if($variables['amp'] == 'amp'){
            craft()->config->set('devMode',0);
            craft()->config->set('siteUrl',craft()->config->get('siteUrl').'/amp/');
            craft()->config->set('amp','/amp');
        }

        $this->renderTemplate($template, $variables);
    }

I use that config to generate a URL for entries that can be used globally. It sits in my plugin's service and looks something like this:
public function getEntryUrl($entry){
        $channel = craft()->sections->getSectionById($entry->sectionId);
        $date = str_replace('-', '/', $entry->postDate);
        $slug = $entry->slug;

        $url = implode('/',
            array(
                craft()->config->get('amp'),
                $channel,
                $date,
                $slug
            )
        );

        return strtolower($url);
    }

And for completion's sake, my routes & some useful stuff from my templates. Also, note -- I chose to prefix my slugs with amp instead of adding it to the end. Mostly preference, I guess.
Routes: 
// Primary
$routes = array(

    // News
    '(?Pnews)/(?P\d{4})/(?P\d{2})/(?P\d{2})/(?P.*)/?$' => array('action' => 'pluginName/newsEntry'),
    '(?Pnews)/?$' => array('action' => 'pluginName/newsAll'),

    // Home
    '(?P.*)?/?$' => array('action' => 'pluginName/home'),

);

// Amp
$routes = array_combine(
    array_map(function($k){
        $pre = '^(?Pamp)?/?';
        return $pre.$k;
    }, array_keys($routes)),
    $routes
);

return $routes;

Templates:
{% if amp is empty %}

    {% set htmlTag = 'xmlns="http://www.w3.org/1999/xhtml" lang="en-US"' %}

    {% set head %}
        
        
        
    {% endset %}

    {% set scripts %}
        
    {% endset %}

{% else %}

    {% set htmlTag = 'amp' %}

    {% set head %}
        
        

        

        

        

        
    {% endset %}

    {% set scripts = '' %}

{% endif %}

// To output an entry's proper URL in a template:
craft.pluginName.getEntryUrl(entry)


---

### Answer by username_2 on 2016-03-11. Score: 3

I wrote the [SEOmatic plugin](https://github.com/nystudio107/seomatic) -- AMP is really just a name for some best practices for web development that speed things up on mobile. There isn't anything terribly special about it, I do most of what they list in their spec for websites already.

The "meta tags" that they want you to add are just some JSON-LD, which you can easily add on your own, or via SEOmatic's `renderJSONLD` function.

As for implementing AMP, you might find this helpful: [Google AMP: Should You Care?](https://nystudio107.com/blog/google-amp-should-you-care)

> **Comments:**
> **username_3**: AMP is a little more than just some best practices for mobile. It actually is a subset of HTML5 using custom tags like [``amp-img``](https://www.smashingmagazine.com/2016/02/everything-about-google-accelerated-mobile-pages/#amp-html-tags) so can it can control loading. Your plugin is helpful though!  
> **username_1**: Yes, AMP is DEFINITELY more than just methodologies. It's a very comprehensive library and as @username_3 mentioned a subset of HTML/CSS (and JavaScript/CSS; yes there are restrictions): https://www.ampproject.org/docs/reference/components  It also requires things like limiting your CSS & injecting it directly onto the page, which is - at best - debatably a best-practice unless you're operating in a cached environment like AMP.  
> **username_2**: Well, what I meant was that the things that make AMP fast are methodologies that you can implement yourself without AMP. AMP just enforces them, and provides functionality as you mentioned to make it easier to do.  

---

