AMPifying pages at FabHotels

Charanjeet Kaur
FabHotels
Published in
5 min readOct 17, 2017

Cheers to all developers out there!

Are you putting all efforts to achieve search engine optimized web pages for your site and still not happy with the results? You have landed at the right place!

We, at Fabhotels, boast of a significant user base coming from Google Search Engine Result Pages (SERP) and to take this number even further, we worked on getting ourselves AMPified!

What could be better than google working as a CDN to cache a given page and taking responsibility for delivering it?

AMP Flow Diagram

Yes, you read it right, Google kinda adopts the AMP pages and delivers them under its own domain.

For example,

https://www.google.co.in/amp/s/www.fabhotels.com/amp/hotels-in-new-delhi

is hosted at

https://www.fabhotels.com/amp/hotels-in-new-delhi

Another benefit of adoption is that AMP pages are discoverable and, Google prefers AMP pages in the search results. All we have to do is construct our web page using a set of AMP tags.

So, what exactly is AMP?

AMP (Accelerated Mobile Pages) is interaction wise stripped down version of web pages that are built using a given set of amp tags.

It acts as a landing page which looks similar to the main website. It is easy to implement and can provide a major boost in reducing bounce rate and a better search rank. It has links pointing to other AMP pages and the corresponding website pages.

AMP pages are super optimized from performance point of view. It comes hand in hand with the number of rules imposed on development. Per se, our city listing AMP page loads in 1.90s, However our main webpage loads in 2.57s.

AMP page https://www.fabhotels.com/amp/hotels-in-mumbai Loading Time waterfall
Main webpage https://www.fabhotels.com/hotels-in-mumbai Loading Time waterfall

But.. How would we purge this cache?

It works on “Use Stale While Revalidating model”. i.e. when a URL is requested from Google CDN, it is picked from the cache while updating the cache content in the background.

We can ask to use the cached content and not make any background call for a certain duration by specifying the max-age header.

In hurry? Here is a link to boilerplate. Stay to learn more on development experience.

Development Experience

It works on either https or localhost.

The documentation of AMP is quite a verse. https://www.ampproject.org has API of all amp tags and, https://ampbyexample.com has the running example of all tags. You can also change the code and re-execute the examples. You should use the chrome extension AMP Validator. It can notify you of amp rule violations at the time of development itself.

A basic markup to start development can be found at https://www.ampproject.org/docs/tutorials/create/basic_markup. The only time we felt stuck was finding a way to add interactivity. Adding view more/less functionality was a major one. I will be explaining this in my next blog.

A simple example?

Let’s implement Image Gallery

It is as simple as defining <li> inside <ul>. You can play around at this link.

<amp-carousel height=”300" layout=”fixed-height” type=”carousel”>
<amp-img src=”image1.jpg” width=”400" height=”300"></amp-img>
<amp-img src=”image2.jpg” width=”400" height=”300"></amp-img>
<amp-img src=”image2.jpg” width=”400" height=”300"></amp-img>
</amp-carousel>

Continue reading to learn how to add Interaction!

How to interpolate variables?

amp-mustache is used as a template engine to render variables. It can be used to write if-else like statements. It follows https://github.com/janl/mustache.js/

{{variable}}: A variable tag. It outputs the the HTML-escaped value of a variable.{{#variable}}{{/variable}}: It executes the block if the variable exists.{{^variable}}{{/variable}}: It executes the block if the variable does not exist.

How to handle Dynamic Data?

amp-list helps us to fetch dynamic data from CORS enabled API. In this github example, we are rendering hotels of a given city. and, we are using amp-list to fetch each hotel’s price via ajax call. AMP ensures call batching and hence doesn’t create parallel requests on server.

Snippet from github. <% %> is templating engine syntax of ejs in nodejs.

<% for(var id in hotels) { %>    <% var src = ‘http://localhost:3000/hotelsPrice'%>    <amp-list 
width=”50"
height=”39"
layout=”responsive”
src=”<%= src%>”
items=”metadata.data.propertyListing”>
<template type=”amp-mustache”>
<span class=”hotel__price”>
{{<%= hotel.id %>.actualPrice}}
</span>
</template> </amp-list><% } %>

here, we are making an api call to src. items key holds the results of api callback and acts as a base key for amp-mustache.

{{<%= hotel.id %>.actualPrice}} is converted to {{111.actualPrice}} on the html by the server. and, the price data is interpolated after receiving the api callback. Api result has to be of the format:

{“items”: […]}

You may use amp-live-list to update information in real time. It can publish live updates to AMP page as new content becomes available at source API.

https://ampbyexample.com/components/amp-live-list/

Github

All these approaches are there on GitHub link. This project is built on Nodejs framework and, uses ejs as a templating engine. All of the relevant apis are mocked. You may run it using

git clone https://github.com/charanjeet2008/fab-ampifynpm installnpm run apinpm start

SEO

You can add Google Analytics’s pageview and custom events via amp-analytics. These will be attributed to to your domain only. Refer to analytics.ejs in the github example.

Deploying it

Follow https://ampbyexample.com/introduction/how_to_publish_amps/

Add following headers in your response

access-control-allow-origin:https://www-yourdomain-com.cdn.ampproject.orgaccess-control-expose-headers:AMP-Access-Control-Allow-Source-Originamp-access-control-allow-source-origin:https://www.yourdomain.com

You may submit one URL of AMP at google webmaster and see if it appears in search results within a day or two. And, then start referring amp from the main website by amphtml link

Keep an eye on crawl errors & Celebrate flash icon in google search.

Consolidated list of Resources

--

--