Twenty Sixteen

Here are some steps to make a theme AMP-compatible, using Twenty Sixteen as an example.

The most common challenge for AMP compatibility is reimplementing scripts. Because JavaScripts files aren’t allowed, the plugin will remove them if they’re present.

Validation Errors

This plugin will display validation errors on removing JavaScript, to alert you of this:

You could allow the plugin to remove the JavaScript and report the error, but it’s better to prevent outputting it. And you can reimplement it with amp-bind.

AMP Helper Function

To begin, create a function that determines if this is an AMP endpoint:

/**
 * Whether this is an AMP endpoint.
 * This must only be called after the ‘parse_query’ action.
 *
 * @return bool Is AMP endpoint (and AMP plugin is active).
 */
function twentysixteen_is_amp() {
	return function_exists( 'is_amp_endpoint' ) && is_amp_endpoint();
}

Then, prevent enqueuing scripts if this is an AMP endpoint. For example, in the function twentysixteen_scripts():

function twentysixteen_scripts() {
	if ( twentysixteen_is_amp() ) {
		return;
	}

	// Enqueues scripts here.
}

This function exits early on AMP endpoints, so the scripts aren’t enqueued.

Re-implementing JavaScript

The function.js file that is present on the non-AMP URL enables toggling the display of the menu:

You can reimplement this with amp-bind:

<?php if ( twentysixteen_is_amp() ) : ?>
        <amp-state id="navMenuToggledOn">
                <script type="application/json">false</script>
        </amp-state>
<?php endif; ?>
<button
        id="menu-toggle"
        class="menu-toggle"
        <?php if ( twentysixteen_is_amp() ) : ?>
                on="tap:AMP.setState( { navMenuToggledOn: ! navMenuToggledOn } )"
             	[class]="'menu-toggle' + ( navMenuToggledOn ? ' toggled-on' : '' )"
                aria-expanded="false"
                [aria-expanded]="navMenuToggledOn ? 'true' : 'false'<?php endif; ?>
>
        <?php _e( 'Menu', 'twentysixteen' ); ?>
</button>

<div
        id="site-header-menu"
        class="site-header-menu"
        <?php if ( twentysixteen_is_amp() ) : ?>
                [class]="'site-header-menu' + ( navMenuToggledOn ? ' toggled-on' : '' )"
        <?php endif; ?>
>

At the top of the snippet, the <amp-state> holds state of whether the menu is toggled on.

And the <button> has an on attribute that changes the state when it’s tapped.

For example, tapping it causes the <div id="site-header-menu" …> at the bottom of the snippet has its class toggled.

This is with the [class] attribute, which allows dynamic values:

[class]="'site-header-menu' + ( navMenuToggledOn ? ' toggled-on' : '' )"

Similarly, this uses amp-bind for the sub-menu buttons in the navigation menu, replacing the non-AMP JavaScript: