AMP in WordPress, the WordPress Way

TL;Dr

This post summarizes a recent talk Jeanny Haliman and myself gave at AMP Conf, 2019:  Enabling first-class AMP experiences on WordPress is one of the ways the AMP Project aims to bring a user-first experience to websites and content on the web. The Official AMP Plugin for WordPress (WordPress.org, Github) integrates AMP content creation seamlessly with standard WordPress content creation workflows. In this talk we describe in detail how the AMP plugin for WordPress works, how to take advantage of it, and showcase some salient success stories of WordPress sites using the plugin in the wild.

Content Management Systems

WordPress is a Content Management System (CMS), which means that it is a software platform that adds layers of abstraction on top of the web to facilitate the creation, management, and publishing of content on the web. It is certainly one of the largest players in the CMS space, with about 33% of the whole web being powered by WordPress sites today.

Building AMP-first WordPress sites on CMS platforms such as WordPress encompasses a spectrum between a fully manual process, where we as developers do all the work, and a fully automatic process, where the platform, with a combination of core functionality and extensions does all the work for us.

The reality of what is feasible today is a balance point somewhere in this spectrum, where a large part of the process can be automated, and there is a part of the process that requires developer intervention. The exact location of this point, is determined by the status of the ecosystem in terms of AMP compatibility, and therefore, as the WordPress ecosystem evolves, the location of that balance point moves towards maximizing automation and minimizing developer interventionThe key enabling technology influencing AMP compatibility in the WordPress ecosystem is the official AMP plugin for WordPress (WordPress.org, Github).

The Official AMP Plugin for WordPress

The Official AMP plugin is an extension to the WordPress platform, which plays three main roles:

  1. It automates large parts of the process, by integrating into the standard content creation mechanisms of WordPress
  2. It provides tools and guidance to support developers on the parts that need to be done manually, and
  3. It acts as a monitor and enforcer to maintain AMP compatibility as sites evolve.

To fulfill these roles the plugin implements four main areas of functionality:

  1. AMP Validator Integration: The plugin internalizes the AMP specification, effectively becoming a WordPress-centric AMP validator
  2. WordPress template rendering integration: In WordPress there are several ways to create content elements, such as embeds, shortcodes, widgets, and blocks which are triggered during what is called Template Rendering. The AMP plugin hooks into these standard content generation mechanisms and generates AMP-compatible content elements instead
  3. Output buffer post-processing: There are parts of the code that WordPress generates that could be also generated in terms of AMP components, but the conversion cannot be done during template rendering. To deal with these cases, the plugin captures the results of the template rendering phase into an output buffer, parses it into a DOM document and performs a set of processing and conversion tasks:
  4. Content Serving: After these processing phases, we end up with generated content that may or may not be AMP valid. Depending on the outcome, the plugin triggers different serving strategies, aimed at minimizing the likelihood of releasing invalid AMP content to the wild

All this functionality is part of the assisted generation capabilities of the plugin; we don’t have to worry about them and we can focus instead on the parts of the process that require developer intervention.

Building AMP-First WordPress Sites

In WordPress, the look and feel of a site is controlled by a collection of template files, which when combined together, form what is called the theme of the site. The AMP plugin can be configured to interact with the theme of a site in three different ways:

Native Mode

In native mode, the plugin essentially integrates AMP as the framework for your WordPress site. It reuses the theme’s templates and styles to render AMP responses. This means that your site is AMP-first and your canonical URLs are AMP!

Depending on the theme and plugins being used, a varying level of development work may be needed. The AMP plugin helps us by doing most of the work automatically, and this part corresponds to the minimum developer intervention needed to reach full AMP compatibility.

There may be cases where it is not possible to get all the components for a given content type to be AMP compatible at a given time. In these cases, you can either opt out of AMP of those content types or you can leverage the plugin Transitional Mode.

Transitional Mode

In transitional mode  (formerly called Paired mode)  the plugin also reuses the active theme’s templates, but it renders AMP and non-AMP responses. Although there are two versions of the content, your site’s theme is used in both cases, and you as a developer have control of what is generated for either case.

This mode is called transitional because it is intended to provide you with a migration path, to progressively expand the AMP compatibility of your content, until you can switch easily to native mode.

There are cases where we may want to provide an AMP experience to our users, but don’t have the resources to carry out the development work needed for the native of transitional modes. In these cases, we can take advantage of the plugin Reader Mode.

Reader Mode

In Reader Mode  (formerly called Reader mode), the plugin generates AMP content using separate simplified templates that are neat and light but may not match the design of the underlying theme of your site. This mode is useful for providing basic AMP experiences, but we don’t actually recommended it because transitioning to AMP-first experiences in WordPress is getting easier and easier.

Now that we understand the different template modes let’s go over the development workflow for building AMP-first sites in WordPress.

Development Workflow

The workflow for developing AMP-first sites in WordPress encompasses three main tasks:

  1. Identify: The first part of the workflow is identifying any validation errors being triggered by components of our site
  2. Contextualize: The second part is Contextualizing those errors, to understand where the offending code or markup elements are coming from; which component of the site injected it?
  3. AMPify: And finally we must AMPify the offending components so that the validation errors can be removed without losing visual or functional parity

The AMP plugin does all the work on identifying and contextualizing validation errors. And it also does quite a bit of the work needed on the AMPification part, by automatically generating AMP-compatible components, or automatically removing offending components (with user consent).

Identifying Errors

This screenshot gives you a glimpse of content creation and editing in WordPress. In the WordPress editor, everything is a block. The blue rectangle here is a Custom HTML block we added to our content. And in that block a piece of code is added which violates AMP rules.

When we update the post, the plugin flags the error, in the context of the block, as well as a clear warning notice on top that alerts about problems in this particular content as well as in other parts of the site.

Contextualizing the error in this case is easy since we have it in front of us. But in WordPress, code can be generated in a variety of ways and keeping track of the sources of specific errors is one of the most difficult parts of AMP development in a CMS such as WordPress. The good news is that the plugin does all the work needed to contextualize errors.

Contextualizing Errors

The plugin hooks its functionality into the content generation mechanisms of WordPress and annotates the generated markup with HTML comments. When a validation error is encountered, the plugin walks the DOM tree back to determine from the HTML comments the source of the error and other contextual information. Each URLs affected by a given validation error is associated with  the same validation error object.

Once the plugin has identified and contextualized existing errors, the question is what to do about them?

Plugin Actions

The plugin can be configured to do one of two things:

  • If configured to do automatic sanitization, the plugin removes the offending markup causing a given validation error, making the associated URL valid AMP. This does not mean the plugin is fixing the corresponding functionality or visual aspects of the site that might be affected because of removing the offending markup.
  • If configured to do manual sanitization, the plugin does not remove any offending markup, letting the associated page remain as not valid AMP. This does not mean that invalid AMP will be served, as the plugin will ensure that is not the case.

But the ultimate decision about what to do with identified errors is taken by the developer.

Developer Actions

As a developer, you can decide to either:

  • Accept the plugin action, effectively saying “it is ok to remove that invalid markup from my AMP pages” because it is either not really needed, or because you have an AMP valid solution, or
  • Reject the plugin action,  effectively saying “that particular markup element cannot be removed”, because it is key for the experience of my site, and I don’t have an AMP-valid solution for it yet

AMP Plugin Compatibility Tool

The plugin exposes these capabilities via a compatibility tool that puts at the fingertips of  developers all the information gathered on the identification and contextualization of errors. In a nutshell, the compatibility tool exposes:

  • Details about the markup causing the error
  • The source of each error: the theme, a specific plugin, or core
  • The type of error it is: CSS? HTML? JS?
  • And provides the UI for developers to take the action of accepting or rejecting the corresponding sanitization action taken by the plugin

Making a Theme AMP Compatible

At this point you should have a good sense of the capabilities of the plugin and the elements of the workflow for developing AMP-first sites in WordPress. Let’s go now over a simple but real-world example of making a theme AMP compatible.

As we mentioned before, depending on the characteristics of your theme, the level of work required to achieve this would vary. But although this example is not too complex, it will give you a clear sense of the workflow you should follow for making your theme AMP-first.

Starting Point

We start with a theme has been tested and it has functional fallbacks so that it works well when JavaScript is disabled in the browser.

In our example we start with the Twenty Thirteen Core theme, which is a classic, simple WordPress theme, with a site identity section, a hamburger menu, search bar, some content embeds such as YouTube and Twitter, widgets, and features like that. To test this example yourself, get a brand new WordPress install, install the AMP plugin for WordPress, and the Twenty Thirteen Core theme.

Activate the Plugin

The first step is to activate the AMP plugin in our admin screen and configure the plugin to operate in Transitional mode to progressively make the theme AMP-compatible and once we get to full AMP compatibility we can switch to Native mode. We configure it also to not remove automatically any offending markup, because we want to analyze each validation error to understand it and fix it.

Once we Save the configuration, we can see the plugin telling us that there are some validation issues we need to investigate and fix.

The next step is to take a look at the content of our site and see where the validation errors are coming from.

Analyzing a Post

We pick a specific post. Since the plugin is configured in transitional mode, we land on the non-AMP version of the post, which has the functionality we get from the 2013 theme.

We have access to the AMP version of the post from the Admin bar, and when we try to go to the AMP version, the plugin tells us the AMP version is not valid.

We can then go to the compatibility tool to see the errors and all their contextual information. There you can see the errors in red, which means the plugin did not remove the offending markup elements. Notice as well on the right sidebar, that AMP is disabled for this post, which means AMP content will not be served.

We will not dive into analyzing the errors now for the sake of time and space, but we can get you a summary of what is happening. If we look at the source and type columns in the compatibility tool, we see that there are:

  • Two CSS errors having to do with viewport at rules (see CSS error type), introduced by the theme itself.  These CSS errors are easy to fix because the viewport @-rules are actually not needed and can safely be removed.
  • Four JS errors caused by scripts being loaded by WordPress core (e.g. JQuery library, and some other scripts). This scripts inserted by the core platform are usually related to dependencies for scripts introduced by our theme.
  • Two JS errors caused by scripts belonging to the theme itself; these are probably important since they must have functionality specific to this theme

The next step is to isolate the errors, by letting the plugin remove the offending elements, and then look in detail at our theme to see what visual or functional disparities exist, if any.

Isolating Errors

To isolate the effect of individual errors, we mark all errors as “Accepted”, which tells the plugin to remove the offending elements. And then we use the preview functionality, which allows to analyze the effect of the plugin actions without actually applying the changes to the post.

Notice that by doing this we have made the post to be valid AMP, but we need to ensure there is no broken functionality or visual disparities. In this case, we checked the post and found that everything is good, except for the hamburger menu that was broken by the removal of one of the theme JS scripts which provided that functionality.

The next step is to make the fixes in the theme to remove the causes of the errors and implement the functionality of the hamburger menu in a way that is AMP compatible.

Fixing the Errors

In the style.css file, we first remove the CSS viewport at rules that are not needed.

In the functions file of the theme we implement a function to check when AMP content is being requested and use it to wrap the parts of the theme where the JS files are being enqueued and prevent that from happening on AMP responses.

Then we add theme support to tell the plugin to handle the hamburger menu conversion. Most themes include some custom JavaScript to support presenting the nav menu. Since the implementation looks very similar for most themes, we added support in the AMP plugin to provide an AMP compatible implementation. To leverage that functionality:

// Add AMP theme support for responsive navigation menu
add_theme_support(
  'amp', 
     array(
        'paired'            => true,
        'nav_menu_toggle'   => array(
	  'nav_container_id'  => 'site-navigation',
	  'nav_container_toggle_class' => 'toggled-on',
	  'menu_button_xpath' => '<xpath to button>',
	  'menu_button_toggle_class'   => 'menu-toggle',
     )
   )	
);

Where we pass the “amp” parameter to the add_theme_support functio, and an array of additional parameters extending AMP support:

  • paired = true”: the plugin is operating in Transitional mode
  • nav_menu_toggle”: gives the plugin information about the hamburger menu markup, so it can provide the corresponding functionality using <amp-bind>

The next step is to verify the fixes.

Verify the Fixes

To verify the fixes, we trigger a recheck of the post in the compatibility tool, and see that all the errors are gone. Finally, we review the functionality of the post and ensure that everything is in order, including the functionality of the hamburger menu.

“Graduating” to Native AMP

At this point the AMP and non-AMP versions of our 2013 theme are identical both in terms of functionality and look-and-feel. Therefore, there is no need to keep both and we can graduate our site to Native Mode. As you can see in the video this is as simple as changing the value of the parameter paired passed to the add_theme_support function from true to false.

Conclusions

In this post we provided a concise yet extensive description of the official AMP plugin for WordPress, with details on its functionality, how its capabilities fit in the developing AMP-first sites in WordPress, and went over a simplified but representative example of how to make a theme AMP compatible.

To learn more about the AMP plugin please check the plugin product site, and follow the development of the project on Github.

Leave a Reply

Your email address will not be published. Required fields are marked *