Integrating Google AMP into an eZ Publish site
By: Ernesto Buenrostro | October 13, 2017 | eZ Publish development tips, User experience, and Web solutions
Accelerated Mobile Pages (AMP) is Google's technology designed to create fast mobile pages. AMP allows developers to take advantage of fast rendering and improved performance. Here's a look at how it can be integrated into an existing eZ Publish website.
How AMP works
For a technical overview of how AMP works with your CMS, see my previous post about how a proper multi-channel CMS approach makes Facebook Instant Articles and Google AMP easier.
AMP includes a number of specific rules. For example:
- Custom JavaScript can't be used on an AMP page. (There are some exceptions.) The AMP framework provides a set of JS components you can use on your pages
- Your CSS and HTML need to live on the same page
Create a new pagelayout
To create an AMP page you'll first need to create a new pagelayout. This is necessary because the HTML that you're going to use is a bit different from standard HTML.
To do this, edit the file "settings/override/layout.ini.append.php" and add the following settings:
<?php /* #?ini charset="utf-8"? ... [amphtml] PageLayout=pagelayout_amp_html.tpl UseAccessPass=false ... */ ?>
This will create a new URL pattern /layout/set/amphtml/<article_path> that can present all of your existing pages in the new AMP layout. The setting UseAccessPass needs to be set to false so that eZ will not prepend /layout/set/amphtml to links generated through this layout.
Now, you'll need to add the template code for the new layout. Create the following file: "extension/site/design/site/templates/pagelayout_amp_html.tpl" and add the following:
<!DOCTYPE html> {def $pagedata = ezpagedata() } {if is_unset( $persistent_variable )} {def $persistent_variable = $pagedata.persistent_variable} {/if} <html ⚡ lang="{$site.http_equiv.Content-language|wash()}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> {if is_set( $persistent_variable.canonical_link )} <link rel="canonical" href="{$persistent_variable.canonical_link}" /> {/if} {literal} <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> {/literal} </head> <body> ... <div class="content-container"> {$module_result.content} </div> ... </body> </html>
There are several important points to pay attention to in the code above:
- You need to include the character ⚡ or the "amp" attribute in the HTML tag
- You need to set the canonical URL for the page
- The CSS stylesheet is added inline because you can't load external CSS files
Now you'll need to create the overrides for the content types that you are going to display in the AMP format. You might decide to only support the AMP format for certain content types.
To create the override for article pages, add a new entry to the "override.ini.append.php" file for your public siteaccess.
[amphtml_article] Source=node/view/full.tpl MatchFile=amp_html/full/article.tpl Subdir=templates Match[class_identifier]=article Match[layout]=amphtml
The AMP HTML for the article template will look something like this:
<article id="content_article"> <div class="banner"> <amp-img layout="fixed" class="bleed" src="{$node.data_map.image.content.original.url|ezroot('no')}" width="{$node.data_map.image.content.original.width}" height="{$node.data_map.image.content.original.height}" alt="{$node.data_map.image.content.alternative_text|wash()}"> </amp-img> </div> <div> {attribute_view_gui attribute=$node.data_map.body} </div> </article>
Most of the AMP tags are regular HTML tags and can be used unchanged, but some of them are forbidden or limited in some way. Here is a comprehensive list of existing AMP custom tags and limitations.
In this example, we are using the <amp-img> tag to display an image. Using the regular <img> tag will make your AMP page invalid.
Also, you'll need to add overrides for elements used in the rich text editor, such as embedded images.
[amphtml_embed_image] Source=content/view/embed.tpl MatchFile=amp_html/embed/image.tpl Subdir=templates Match[layout]=amphtml Match[class_identifier]=image
AMP limitations
There are a few limitations to watch for on some of the AMP components.
For example, only one "amp-sidebar" component per page is allowed. Websites generally use this to display the main menu triggered by a burger button. In some cases, there is a need to display more than one sidebar, and because JavaScript is disallowed, you might need to use CSS combined with some HTML elements such as checkboxes. Remember that the :checked CSS pseudo-class can be used to change applied styles according to whether the checkbox is checked.
Making AMP pages discoverable
You'll want to let the world know that there is an AMP version of your site's pages. Using an "amphtml" meta tag, you can specify the AMP URL for a particular page. This way, when Google crawls your normal website, it will know which pages support AMP and at what URLs.
First, we need to pass the article's AMP URL to the pagelayout. To do this, set a persistent variable in regular, full view article template.
... {ezpagedata_set( 'amphtml_url', concat( '/'|ezurl( 'no', 'full' ), '/layout/set/amphtml', $node.url_alias|ezurl( 'no' ), '/' ) )} ...
In the general pagelayout (typically at a path such as "extension/site/design/site/templates/pagelayout.tpl"), add the following code:
<!DOCTYPE html> <html lang="{$site.http_equiv.Content-language|wash()}"> <head> ... {if is_set( $persistent_variable.amphtml_url )} <link rel="amphtml" href="{$persistent_variable.amphtml_url}" /> {/if} ...
The AMP pages will then be offered in some mobile search results:
For more information about the AMP project, visit the official AMP documentation page.