A Comprehensive Guide to Supporting AMP in WordPress

Standard

AMP is a new technology that’s gaining the attention of online marketers in every field.  It formats content in a way that loads blazingly fast for mobile visitors, whose page load time expectations can be as little as three seconds.

In this post, we’ll discuss what AMP is, as well as how to wire up your WordPress themes to support AMP templates.  You’ll find a large amount of information and code samples in this post.

Quick Links:


All About AMP

amp-project-logo

AMP stands for “Accelerated Mobile Pages.” It is an open source project backed by Google that makes web pages load really, really fast.  There are also some huge benefits for publishers who take advantage of AMP:

  • AMP pages are cached and served by Google itself.
  • Two versions of the page are now available to search queries: HTML and AMP.
  • They receive Google’s “Mobile-friendly” or “AMP” label in search results, notifying users that the page will load quickly.
  • Google may use AMP as a PageRank consideration in the future (“mobile-friendliness” already is).
google-amp-label

Example of the Google “AMP” label.  Don’t ask why I was googling Pokemon Go.

Further reading: Does Google AMP Affect SEO?

In order for Google to cache your pages and give it the AMP label, it must have valid AMP markup.  AMP HTML is very similar to regular HTML5, with just a few exceptions.

AMP HTML

AMP HTML is quite simple.  In most cases, it’s nearly identical to regular HTML5, with the exception that certain element tags are replaced with an AMP version.  For instance, the <img> tag becomes <amp-img></amp-img>.

Further reading: The AMP Spec Document

AMP has very specific standards. These standards are in place so that it can render each page as quickly as possible.  Here are some highlights of the requirements for valid AMP documents:

  • The document <head> must contain specific scripts and styles.
  • Only inline styles are allowed (No external stylesheets)
  • The inline styles are limited to 50Kb in size
  • Slow-loading elements — like <frame>, <object>, and  — are prohibited.
  • No custom JavaScript is allowed (but there are several AMP extensions that provide common JS functionality for you)

AMP Extensions (or, “Components”)

AMP Extensions are helpful components that expand what AMP does by default.

Below are a few noteworthy examples, but there are many other Extensions available.

amp-sidebar (or “menu”)
The AMP Sidebar extension is what is commonly used as a menu in WP.  It allows for a button (or other element, like a hamburger icon) to trigger a menu that slides into the page from the side.  I’ll discuss this in detail below.

This element can only be used once on a page, and it essentially only allows text, images, and accordions, so keep that in mind.

amp-ad
So your site depends upon ad revenue (who’s doesn’t?).  Thankfully, AMP provides a format for including these in your markup with the AMP Ad extension.

 

amp-brightcove
Hey, who doesn’t love Brightcove content?  To support the need for this feature, AMP has created the AMP Brightcove Extension.  Note that even if you have a lot of custom parameters to pass into Brightcove, you can still do that.

amp-social-share
AMP Social Share is really quite handy, as it takes care of integrating a bunch of sharing into your template by passing just some basic attributes.


The WordPress AMP Plugin

wp-amp-plugin

The good news for you is that the team at Automattic has created a very nice plugin to handle creating valid AMP documents in WordPress.  It’s simply called “AMP,” but for clarity’s sake, I’ll refer to it as “WP AMP” throughout this discussion.

To a user, the plugin simply makes an AMP version of a post is available.  This post is found at the same URL as the post, but with “/amp” tacked on to the end.

So if the URL is yoursite.com/hello-world, the AMP version is found at yoursite.com/hello-world/amp/.

For developers, WP AMP is basically a templating system.  It contains a basic AMP HTML template, and uses hooks and filters to ensure your content is rendered as valid AMP markup.  For example, the provided template includes the required code for the <head>, and it filters the post content to ensure your <img> tags are replaced with <amp-img>.

Further reading: WP AMP plugin documentation

Screen Shot 2016-07-21 at 10.43.13 AM

The default WP AMP post template.


AMP Template Customization for Themes

So, if you’re a theme developer, you’ll want to customize this document’s appearance to match the rest of your layout so that your users will have a seamless visual experience.  The rest of this post discusses how to do just that.

Customizing the WP AMP plugin to work with your theme takes a bit of work, but it will definitely be a big bonus to your users.  As this is a growing technology, there will be increasing demand for the fast page load times and Google recognition that AMP provides.  At this point, it will set your work apart from other WordPress themes.

Basic AMP Support Setup

Note that this tutorial is written for WP AMP version 0.3.2.

1. Set Up Your AMP Directory

To get started, create a directory in your theme called “amp/”.  Inside that directory, create “amp.php.”  We’ll add all of our backend code inside this file.

Now take a step back, and require the amp/amp.php file near the top of your theme’s functions.php:

require( dirname( __FILE__ ) . '/amp/amp.php' );

2.  Register Your Custom Templates

Here’s where the fun begins.  We’ll be adding your own template files so that you can customize them to match your theme.

After this following step, your theme’s file structure should end up looking like this:

your-theme/
   amp/
      templates/
         single.php
         style.php
      amp.php
   functions.php
   index.php
   style.css

 

Start by creating a directory inside of “amp/” called “templates/”.  Not surprisingly, this will hold your template files.

Next, create a file inside templates called “style.php” (note that it’s a PHP file, not CSS).  If you like, you can just copy the default style.php from the WP amp plugin: wp-content/plugins/amp/templates/style.php.

Now, go into the WP AMP plugin and copy the default single.php file (wp-content/plugins/amp/templates/single.php).  Place this in your theme’s “amp/” directory.  It’s important that you copy this one instead of starting from scratch, as there’s important data in its <head>, plus it also contains some of the actions we’ll be hooking into later.

3.  Register Your Custom Templates

Add the function below to include support for both your new “single.php” and “style.php”


Going Further

Support Custom Post Types

If you have Custom Post Types in your theme, you’ll need to tell WP AMP what they are so that those posts will have AMP versions available.

Next, we’ll add our CPT templates.

Custom Post Type Templates

Adding special templates for your custom post types is optional, but the previous step is not.  You’ll want a special CPT template if your CPT posts have a different layout or functionality than a typical post.

In your /templates directory, copy the single.php and rename it after the slug of your CPT.  For instance, you may have a “book.php” now.

Then, we need to tell WP AMP to redirect to this template.  Edit the function that I called jr3_amp_custom_templates() earlier.  It will now look like this:

Component Scripts

Each AMP Extension (once again, also called a “Component”) has a supporting JS resource.

If you’re using any other Extensions in your template files, like amp-ad, amp-social-share, or amp-sidebar, you must register the JS with WP AMP so it gets loaded correctly.


Customizing Your Template

Custom CSS

As AMP does not allow external stylesheets, all CSS must be found in the document’s <head>.  WP AMP gives us a tool for hooking styles into the <head>, which we’ve already set up.  As a reminder, it will use our our templates/style.php file.

The contents of that file are pretty easy to understand.  Open up the default WP AMP style.php and you’ll see that it’s almost all just plain text, except for a few places where colors and a few other settings are pulled in to render the desired CSS styles.

Keep in mind that the total size of CSS on the page cannot exceed 50Kb.

Here is an example of how the PHP interacts with the CSS:

Add A Nav Menu

A Navigation Menu is one feature that is glaringly lacking from the default WP AMP template.  Naturally, its authors are unable to know if you have a nav menu in your theme, and even if they did, they don’t know what location label you’ll give it, so it’s understandable why they left it up to you to customize.

AMP has an Extension called “amp-sidebar.”  This is a block of content that is triggered by a click that slides in from the side of the page.  We’re going to use this for our menu.

Screen Shot 2016-07-21 at 12.58.52 PM

Example of a basic Navigation Menu using amp-sidebar.

First, following the example code below, add two functions to your amp.php:

jr3_amp_sidebar_component_scripts() tells WP AMP to load the amp-sidebar JS into the template’s <head>.  (Check to make sure you didn’t already add this if you added the component scripts earlier)

jr3_clean_nav_menu_items() is a helper function I wrote to make a barebones list of menu items.  It skips adding all of the unneeded wrappers and classes to the nav menu.

Below those functions are two blocks of HTML to add to your single.php (and other template files).  The first is the HTML that holds our primary nav menu.  The next is the actual button that will trigger the opening/closing of the amp-sidebar menu.

By default, featured images are not included in the WP AMP templates.  Here’s how you do that, taken almost directly from the WP AMP docs.

Social Share Buttons

Since social share buttons often require JS to function, AMP has added support for them via its amp-social-share Extension.  The code below can go directly into your template file.  Don’t forget to register the amp-social-share component script with WP AMP.

I’ve found that Facebook requires an App ID, so be sure to add yours into your code.  Naturally, you’ll need to add some PHP support for this to draw the Fb App ID from wherever you have it in your theme’s settings.


Bonus: Handling Shortcodes

As AMP has very specific rules about what markup is allowed, we need to be careful to only allow valid HTML to our templates.

Shortcodes are a way that unintended output can be slipped in to our content and render the page invalid.  One simple (but not preferable) way to prevent this is to remove shortcodes from the content altogether.

Unfortunately, this approach is pretty brutish.  You should really use another solution for this issue, as you may want to allow certain shortcodes, or even filter the content to replace the shortcode with custom formatting.

Here’s an example of how I modified a hypothetical shortcode called “podcast” to accommodate <amp-audio>.  You’ll note that I also include a helper function to grab the shortcode attributes that we need so we can add that data to our <amp-audio> tag.

Final Thoughts

AMP is going to be a big deal, and soon.  In my experience, clients are already asking us at XWP to integrate it into their WP sites.

If you want to stay ahead of the competition in the WP theme world, or offer your clients another valuable service, you definitely need to integrate this into your themes.

I hope that my experience in this speciality will help you on your way.

Happy coding!

Resources

 

Scheduling Events with WordPress Tutorial

Standard

There are many reasons to schedule events; maybe you need to check an external API, or prehaps periodically empty a cache. This process can even be used for something as simple as making a post un-sticky after a certain length of time.

Scheduling Events in WordPress is basically running a Cron, just simplified by WP. There are several functions available as tools for this process, and here we’re going to take a look at three of them:

In the code at the bottom of this post is a plugin that you can insert into your wp_content/plugins folder. It will produce an admin menu item entitled “Schedule Event Tutorial.” This plugin is very simple: You check a checkbox and set a time for it to become unchecked. After that time has passed, the checkbox will become unchecked.

Screen Shot 2013-11-11 at 10.23.07 PM

The Process

The way the plugin works is that when the checkbox is checked and a time is selected, a function is run that does two things:

1. Checks to see if another “unchecking” event is already scheduled. If so, it removes that event.

2. Schedules the new “unchecking” event.

How it Works

First of all, The actual unchecking is done by the function uncheck_checkbox(). You will see around line 44 that we have hooked that function into the action we’re calling ‘uncheck_event_hook’.

This is just like any other add_action(). The array(__CLASS__….) part is a part of the Object-Oriented Programming we’re using. It tells the add_action function that we’re referencing a method (funciton) inside this class.

add_action( 'uncheck_event_hook', array( __CLASS__, 'uncheck_checkbox' ) );

The interesting part is teling ‘uncheck_event_hook’ when to fire.

Now, follow along in the schedule_event() function…

First, check to make sure process only runs if the “Save Changes” button has been pressed.

if ( ! isset( $_GET['settings-updated'] ) )
    return;

Then a check is run to see if an event exists on this hook. It gets the next time this hook is scheduled to fire by using wp_next_scheduled. Then, if any value is returned, wp_unschedule_event is used to unschedule that event from the ‘uncheck_event_hook’.

// Remove any scheduled event on this hook
    $scheduled_event = wp_next_scheduled( 'uncheck_event_hook' );
    if ( $scheduled_event !== false ) {
        wp_unschedule_event( $scheduled_event, 'uncheck_event_hook' );
    }

Next, we do the actual scheduling. We grab the value of our expiration time setting, and if it’s a number, we set the time the ‘uncheck_event_hook’ will run.

// Schedule the event to uncheck the checkbox
    $exp_time = self::expiration_time();
    if ( is_numeric( $exp_time ) ) {
        wp_schedule_single_event( $exp_time, 'uncheck_event_hook' );
    }

At this point, we wait until the time passes our expiration time, then on the next time any page is viewed on your site, the ‘uncheck_event_hook’ will fire off uncheck_checkbox(), as we set in the add_action() at the beginning of the process.

The Full Plugin Code

I decided to write this as a fully-featured plugin for a few reasons:

  1. An installable plugin would help make this process a bit more practical
  2. I learn best by viewing others’ code. Maybe you can learn something new by looking at how another developer does it

By presenting the full code, less-experienced developers have the chance to learn more about Object-Oriented code, as well as what it takes to set up a Plugin. Of course, if you have any questions about what’s going on, be sure to hit me up. I’d love to help you on your way to learning something new!

How to Enqueue Scripts in WordPress

Standard

The right way to include javascripts in your theme isn’t by putting links like this in the <head> of your header.php:

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

The right way to do it is to enqueue the scripts in your functions.php file like so:

function load_my_scripts() {

//don't use (deregister) WP's jQuery version
wp_deregister_script( 'jquery' );

//Use jQuery from Google Code
wp_register_script('jquery', 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js');
wp_enqueue_script('jquery');

//Include one of my custom javascript files
wp_register_script('myscript', get_bloginfo('template_url').'/js/myscript.js', array('jquery'), '1.0', true );
wp_enqueue_script('myscript');

}
add_action('wp_enqueue_scripts', 'load_my_scripts');

When applied this way, your scripts will load in wp_footer() at the bottom of your pages, allowing the page to load before the scripts do.

For more detail, check out what the Codex has to say. Also, WP.TutsPlus has a related article, but the final code is a little wonky.