Forest header image

Symfony Finland
Random things on PHP, Symfony and web development

How to implement AMP (Accelerated Mobile Pages) on the eZ Platform CMS

Accelerated Mobile Pages is an initiative from Google to speed up mobile browsing. AMP is an open standard based on HTML. It enforces performance by limiting functionality and includes remote caching.

Given Google's continuing dominance search both publishers and CMS vendors need to take AMP into account. In this article you'll learn the basics of how to implement AMP with eZ Platform CMS and Symfony.

Today most new websites and web applications are built using responsive design techniques where a single page adapts to different screens. AMP is partly a return to the world where you have a separate mobile optimised page. So first of all you'll need to understand that going forward with AMP, you'll need to maintain two sets of URLs and templates for your content.

With this approach the first thought is obviously SEO and the detrimental results publishing duplicate content can have on search engine visibility. AMP pages are by design secondary to the primary versions of the content. You should not spend too much time thinking about technical SEO as many techniques such as having keyword filled pretty URLs simply don't matter in the AMP context.

Linking between the two published versions is done using Meta tags in the head of the documents. Linking from an AMP document is identical to using canonical meta tag to point to the main location of your published content, but linking to an AMP document uses a new amphtml meta tag which is currently only followed by GoogleBot.

As an open standard AMP could be picked up by other notable engines like Baidu, Bing and Yandex in the near future. But for now AMP is technically a Google only enhancement, which is being rolled out in mobile search interfaces to provide integrated content views to visitors.

That was a quick introduction to AMP, but there's quite a bit of details to take into account when working with common web elements like ads, media and analytics. This is all well documented on the project site and one should at least skim the documentation before beginning implementing.

Publishing content with AMP in eZ Platform

With the introductions out of the way let's take a look at how to implement AMP in eZ Platform (and Symfony based eZ Publish 5.4 sites will work just as well). If you are a Symfony developer not familiar with eZ Platform, I suggest you read the article: What eZ Platform adds to Symfony

The implementation is done using the bits and pieces offered by the Symfony Framework and the eZ Content repository functionality. First of all we'll need to create a route and a controller to publish content underneath. For this you will use standard Symfony Framework structure by creating a new controller in your application using annotations to define a path and the name of your object:

With this in place you have a simple route that will be ran when a request is made to http://mysite.com/ez-amp/13370. We use the Object ID instead of a Location ID in this case because we want to publish the content and it's location in the content structure is irrelevant.

Now using the eZ Platform content repository API we will gather all the required information required to render the content on an AMP page and push forward with rendering a template:

The above code simply tries to fetch an object with the given ID. If a content object is not found with that ID, this will throw an exception which will result in a standard 404 page. Otherwise the code will move forward and try to render a template named dynamically according to the Object type that is returned. Now let's suppose that we succesfully requested an article that moves forward to rendering.

For the AMP case we will ignore all the default template matching that eZ Platform provides and create a completely new set of templates, amp/article.html.twig and amp/pagelayout.html.twig. In the main template we simply render the fields we wanted to, in the example case the template is very simple:

In real implementations your mileage will vary depending on the complexity of your content types and their presentation, but in general the main templates will likely be quite simple. For the backbone of our pagelayout template we extended the standard AMP platform using regular Twig and eZ Platform template functions:

We fill a number of meta data fields with real data, add some basic styles and a header to give it some personality. What's notable here is that since we are still in the context of a regular eZ Platform template, we can render canonical links and other resources like the homepage just as we would in our regular templates.

What we are naturally still lacking is any reference to the AMP version of the page on the site, but this we will do in the main pagelayout template. In there we will print the meta tag pointing to the AMP version of the page to let crawlers know about the special version that we have available:

With this rather simple setup I was able to create AMP versions of content within the eZ Content repository without too much code duplication or complicated hacks. The example here does not generate valid AMP for all cases, as one would need to set image templates to use the AMP specific format and so on.

A polished version of the above code will be published as a bundle that will allow enabling publishing AMP compatible pages for eZ Platform and eZ Publish. This will follow in the upcoming months as I finalise the code and look into the necessary steps of publishing it correctly on Composer.

UPDATE: A general purpose Symfony bundle packaged AMP extension has been made available via Composer for users of eZ Platform: eZ AMP Bundle - eZ Platform Bundle that provides Accelerated Mobile Pages (AMP) support

More info about AMP:


Written by Jani Tarvainen on Saturday August 27, 2016
Permalink - Tags: cms, amp, ezplatform

« Symfony Bundle Spotlight: EasyLogHandler, eZ Migration Bundle, Netgen Layouts and Sylius - Symfony & staying relevant: React.js rendering, GraphQL and Neo4j OGM »