Skip to main content

AMP Tech Guide: Making It Work

Perficient's Guide to AMP

Nuts and Bolts

If you’ve read our canonical guide to AMP, you know that AMP provides a great experience for users and publishers alike, if you take the time to get it right. This study goes into great detail on some specific issues we encountered along the way. The specific things included within are:

Getting Correct Analytics Data in AMP: Setting Up Session Stitching

Since AMP pages accessed by search are found in the CDN hosted by Google (this is called “AMP on cache”), they are initially on a domain. But as the user does more with the publisher site (which I’ll refer to here as “”, they leave the Google cache, and end up in pages on the domain.

This causes a problem as the person arriving at the publisher’s domain is seen as an external referral from the Google CDN, instead of it being seen as a continuation of the same visit. The following graphic illustrates the issue:


The result is a broken analytics implementation that results in the following issues:

  • When you add the AMP on cache sessions to the sessions on your main domain, your total session count will be too high. That’s because you’ll be double-counting the AMP on cache visitors that click through to the main site, once as a new AMP on cache session, and once as a new session in the main site analytics.
  • The Bounce Rate shown in the AMP on cache analytics will be too high.
  • The Pages Per Session shown in the AMP on cache analytics will be too low.
  • The Average Session Time shown in the AMP on cache analytics will be too low.

This problem alone caused many publishers to abandon AMP. Accurate analytics is really important in digital marketing! But, Google has since worked through a fix for this. The conceptual solution to this is being referred to many as “session stitching”, and the basic idea is to pass a Client ID from the AMP on cache analytics to your main site analytics so that the visit can be recognized as one single session:


This fix was announced by Google on September 5, 2017. The fix uses the new AMP Client ID API to pass the Client ID information. To implement the fix, you follow these steps (partially taken from Google’s support page):

1. Place this tag in the section of your AMP page:

stitching code

Do not place this tag on the non-AMP pages on your site.

2. On your non-AMP pages, add the following into the rest of your Google Analytics script, just prior to the tag:

ga(‘create’, ‘UA-23199282-1’, ‘auto’, {‘useAmpClientId’: true});

If you’re using Google Tag Manager, do it this way:

  • Navigate to Tag Configuration > Fields to Set
  • Set useAmpClientId to true
  • Save the new tag configuration
  • Submit the tag
  • Publish the container

Here is how it looks in the UI:


Session Stitching, the Advanced Class

The above outline to address session stitching should allow you to capture all of your users, but it does leave some issues. What it’s doing is taking data from two different sources and tying them together with a Client ID. At this point, you’ll be able to see what’s coming through AMP pages vs. regular pages. There are still some shortcomings:

  • You can’t see the difference between your own hosted AMP pages vs. Google CDN-hosted pages.
  • If you segment to determine transaction sources, the AMP pages will show as a web data source with zero sessions and some transactions.

The following steps, provided courtesy of Adam Young of Event Tickets Center and Morgan Jones of, will help address those issues.

  1. 1. The first step is to make sure that ‘’ is added into the Referral Exclusion List under the Property Settings in the Admin section of the Google Analytics account. This should remove a majority of self-referrals from the CDN. This does not remove the records in GA. It removes the referral (source/medium) override from the user moving from CDN to site on second click. Therefore, if the traffic hits the CDN via google/cpc or google/organic it remains as that for the cross-data source navigation rather than being overridden by the referral from the CDN.


    This referral exclusion will help eCommerce (and other) sites maintain tracking of a user session from initial entry on an AMP page in the CDN all the way through to checkout.
  2. 2. Google also recommends that you add all subdomains of to your referral exclusion list. This step only applies if you’ve got subdomains on your site (or that are being used as PPC landing pages) that are coded in AMP. If the site does not have a need to specifically track/override the referral currently when navigating between CDN and site, then excluding ‘’ referral sufficiently covers any override from the CDN. Google recommends excluding each subdomain but if you have a large number of subdomains in your setup, this may not be practical.
  3. 3. Create a hit-level custom dimension called “AMPDOC_HOST” in the Google Analytics property: This enables you to segment traffic that started in CDN versus AMP hosted page.


  4. 4. Set the pageview in Google Tag Manager for the AMP Container to include the custom dimension set the “Dimension Value” to “AMPDOC_HOST”:


    Note: “AMPDOC_HOST” does not need to be defined as a variable in the variable settings. The value can be set just like it is in the above screenshot.
  5. 5. You are then able to view pages served up in the CDN vs. AMP pages in the content reports. To view landing pages served up by the CDN, filter by “cdn” by landing page:


  6. 6. Then, finally, exclude “cdn” and include “amp” in the filter to view AMP landing pages:


Final Notes on Session Stitching

Support for AMP by other analytics providers remains a work in progress for most. A Google spokesperson explained that the above outlined solution is available to third party analytics platforms, but that “the best place for info is still the Google Analytics solution, since the AMP team is still working on getting documentation up for other third parties.”

Adobe has written two articles related to addressing AMP, which you can see here, and here.

Accurate analytics is really important in digital marketing.

Ad Network Support

In the early days of AMP, one of the big issues was the support of Ad networks. One of the core underlying reasons for this was that AMP requires https support, and many ad networks did not support this. However, most ad networks today do support https, and so this has largely become a non-issue. When implementing ads, take the time to make sure that they work in AMP.

In addition, further impacting those custom formats is that because of AMP’s very nature, there are requirements on the way that ads are rendered on the screen.

You can read a great deal more about this in this post by Malte Ubi, a Tech Lead on the AMP Project. From that post, here are the core objectives in the approach to ads:

  • Content first. AMP loads ads after the rest of the content, so ads would never slow down load time.
  • Containment. AMP strictly manages the area of a page that ads can access and control to a well defined rectangle. Among other things this avoids pages “jumping around” as ads pop in.
  • Mitigation. AMP mitigates against various JavaScript worst practices often found in ad tech such as `document.write`, by limiting their effect on the ad itself vs. the entire page.
  • Intervention. AMP slows down timers such as those used for animations for ads that are not currently visible, so that ads use much less battery and CPU when they aren’t being seen. Firefox, Safari, Opera and Chrome have recently started doing this by default and we’ll be happy to delete the code when this rolls out to more users. Because in AMP all legacy ads run inside iframes (many ads outside of AMP have access to the host page), these new browser interventions work particularly well in AMP.

At this point in time, ad support in AMP is quite broad, and most ad platforms, and even custom ads, run very well in AMP. In addition, publishers can adopt AMP for Ads which will provide them with better performance (revenue and technical) benefits. Note that AMP Ads can be used anywhere on the web, not just on AMP pages.

With these items largely addressed, you should be able to get access to sufficient ads to fill your inventory without any major issues.

However, if your approach to showing ads on your site was very aggressive (Ads too high on the page, pop-ups, and the like), AMP won’t let you do that.

Knowing Whether AMP Pages Are Indexed or Not

One of the study participants raised the concern that it’s hard to know when an AMP pages is indexed or not. Search Console does not appear to provide information on this, and site: commands don’t appear to support this as well. We’ll add more info here once we get more information on the plans for this.

What is the AMP Cache Update Policy?

Several of the companies we spoke to indicated a concern about how frequently the cache is updated. These were companies with inventories that update in real time on their site. In speaking to Google we learned that the AMP CDN works on a “one behind” model. What that means is that Google reloads your page after each user access.

As a result, if you’ve just updated the page, at most one user will get the outdated version of the page. This is because Google updates the cache after each user visit.

It was also interesting to learn from those dialogues that Google is experimenting with a Push API. If/when this model rolls out, you’ll simply be able to push your new page into the cache whenever you update it.

This will also bring Google the enormous benefit of reducing overall crawling for them. They’ll no longer need to crawl your site to see if/what changes have occurred there, you’ll notify them instead.

Remote.HTML and Real-Time Config

The following is an update on a super advanced sub-component of AMP-Ads that you can safely ignore unless you already know about it. Remote.HTML is a file that you can use to help you setup real-time tracking.

The news we’re sharing here is that it’s something that will be deprecated in the near future. It will be replaced by a new component called real-time config. The reason this is being one is so that it’s more performant, and can call multiple different sources to fetch information.

When implementing ads, take the time to make sure that they work in AMP.

AMP-Bind Component

AMP-Bind is a component that was created in order to support a broad level of interactivity on a page. It’s a coding layer on top of AMP that supports components sitting on top of one another, and it can toggle states. This enables many types of features such as those you might need on an eCommerce category page or a product detail page.

Typical interactions would be a bunch of product configurations, where you can change size, quantity, price, users can click to add to cart, and other similar features. AMP-bind makes all of that possible. The entire page can be aware of the changes in state of individual items, and different elements on the page can interact with each other.

A bit more technical description is that the content on these types of pages require stateful interactivity. It does this via data binding and JavaScript style expressions that causes other elements on the page to mutate.

For example, if a user is on a product category page, and clicks on a filter to only show products under $100, this impacts what gets shown on other parts of the page. They have changed the state of the page with their filter selection, and other parts of the page need to respond to show the user what they want. Selecting a sort order also impacts the page state. Another example of stateful interaction would be an image gallery with a scrolling thumbnail list, where selecting a thumbnail changes the main image on display on the page.

The AMP-bind component is a big deal, because prior to it’s implementation you could not implement this type of interactivity with a page in AMP without some form of hacks, and this type of functionality is critical for e-commerce. However, there are still some limitations in AMP-bind, such as fetching content in real time from different systems.

You can see a demo implementing a tabbed interface in AMP and the source code for the tabbed menu in AMP here. Here you can see demo implementing sort orders in AMP here and the source code for the sort order implemented in AMP here. Both of these demos leverage AMP-Bind and AMP-List working together.

AMP-List Component

One of the challenges that AMP presents is that pages from your site may be loaded from a content delivery network. For example, when a user clicks on a search result that loads an AMP page from your site, Google will fetch the page from its cache which resides on This is all straightforward, except when your page routinely requests elements from third party sources (not from your own web server), such as fonts, images, videos, stylesheets, scripts, and iframes.

These are known as cross-origin requests, and browsers restrict these types of requests within scripts for security reasons. The solution to this is a mechanism called cross-origin resource sharing (CORS). In modern browsers, this typically happens via an API container such as XMLHttpRequest (XHR) or Fetch. These are both designed to lower the risks of obtaining resources from third-party sources, which is why all major browsers support them.

AMP-list uses XHR, but what it does to speed things up is that it operates in an asynchronous, batched mode so that the CORS requests don’t slow down fetching and rendering of the main content of the page.

Note that this means the content being retrieved by XHR won’t render until it’s received, so a key AMP concept is to design the above the fold content to not be dependent on that content on it’s initial page load.

When using AMP-List in combination with AMP-Bind, to issue XHR requests to get updated content when user’s make faceted navigation selection, this is not an issue, since the initial page load will already have occurred.

You can see a demo implementing a tabbed interface in AMP and the source code for the tabbed menu in AMP here. Here you can see demo implementing sort orders in AMP here and the source code for the sort order implemented in AMP here. Both of these demos leverage AMP-Bind and AMP List working together.

AMP-iframe Component

AMP-iframe is a component that can be used to integrate into an AMP page code that would not normally validate in AMP. The basic use case for it is to support functionality that is not currently supported by AMP itself. While the continued growth of AMP capabilities is making these scenarios more uncommon, they do still exist.

AMP-iframes can’t appear in the top 600 pixels of a page, or within the first 75% of the viewport when scrolled to the top (whichever is smaller). AMP-iframes are also not allowed to be used primarily for displaying advertising, as this is not consistent with the overall philosophy of the AMP project. You can read more about AMP-iframes here.

AMP-iframe Component

Snapchat and Instagram have gotten great results from their Stories features, and the AMP project has also created a similar format. The goal of AMP stories is to offer users a simple storytelling mechanism specifically designed for the mobile (Smartphone) format.

It’s particularly well suited for images and video experiences. This allows the publisher to provide easily consumed, visual information that captures user’s attention. It turns out that it’s also super easy to implement. Here are some examples that we’ve created, along with their companion code, to make it easy for you to get started:

Our demos are not maxed out from a design perspective; they’re meant to make it easy for you to get started with AMP Stories. You can add your own styling!

Uncertain about which services will best address your business challenge? Let us help. Contact our digital marketing experts to see how we can help drive your business’s performance.