Creating Google AMP Pages With ASP.NET MVC

With the recent announcement of Google AMP, you don't need to worry about a redesign of your site. Today, I show you a quick and easy way to make AMP pages with ASP.NET MVC.

February 17th, 2016 • MVC •
2 (2 votes)
Speedy Bus Flying By a London Telephone Booth

When Google first announced Mobilegeddon, webmasters were worried about their Google rank dropping because their site didn't support mobile pages.

Now, Google announced AMP pages where they focus on delivering static content from publishers as quickly as possible and possibly rewards early adopters with a boost in rank.

Yes, they are asking website owners to downgrade their webpages. Not replace, mind you...make additional pages.

How, you ask?

By asking the webmasters to remove all of the irrelevant fluff and providing real value with true content to your audience.

So in simple terms, they want a slimmed-down version of your content so they can deliver it quicker.

UPDATE: After looking at my approach for creating Google AMP pages, there was a significant problem using a query string ?amp on the end of the Url.

When someone (or Google) would view the Google AMP page, it would be cached and the next person requesting it would receive the Google AMP page instead of the nicely formatted blog post.

To fix this issue: If you aren't using caching, this technique would work, but since I cache my site heavily, I created an AmpController specifically for Google AMP pages and this seems to work perfectly.

I also mention this in my saga of converting my site to work with Google Amp pages in a recent post

What is AMP?

Google AMP (Accelerated Mobile Pages) is an initiative to create a faster web for users by having website owners "trim the fat" around their content. The video (25 minutes) talks about how to integrate AMP pages into your website.

TheNextWeb has even considered it a game-changer for publishers and their audience.

It requires three components:

  • AMP HTML - Restricted and structured HTML
  • AMP JS - Ensures the fast rendering of AMP pages
  • AMP CDN - Delivers the AMP pages

Depending on how many sites a webmaster manages, this update could mean countless hours modifying thousands of pages to match the AMP requirements.

Luckily, if you have a site built in ASP.NET MVC, you can easily setup AMP pages.

How do we apply AMP to our ASP.NET MVC site?

A while back, I always wondered why DisplayModes were introduced to ASP.NET MVC. What possible use could I have for that? I guess I never needed a reason to use DisplayModes...

...until now.

The way DisplayModes work is that when a certain condition is met, it will redirect to a View of your choice. Everything is handled exactly the same way as before except that you are sending the ViewModel to a different View.

DisplayModes require four things:

  • Registering your DisplayModes
  • An common class for your Views (pages). I created a GoogleAmpDisplayMode class.
  • A ContextCondition for redirecting to the new DisplayMode
  • The actual View

First, let's start with registering our DisplayMode.

Registering Your DisplayMode

In your Global.asax, place these lines at the bottom of your Application_Start method.

// Used for Google AMP (https://www.ampproject.org/docs/get_started/about-amp.html)
DisplayModeProvider.Instance.Modes.Clear();
DisplayModeProvider.Instance.Modes.Add(new GoogleAmpDisplayMode());
DisplayModeProvider.Instance.Modes.Add(new DefaultDisplayMode());

The GoogleAmpDisplayMode class is defined below and then the DefaultDisplayMode is used. Order does matter. If the ContextCondition is not fulfilled, it will move on to the next DisplayMode.

For my website, I created a directory called DisplayModes and created a GoogleAmpDisplayMode.cs. It's a simple class.

DisplayModes\GoogleAmpDisplayMode.cs

public class GoogleAmpDisplayModeDefaultDisplayMode
{
    public GoogleAmpDisplayMode() : base("amp") // for filename.amp.cshtml files.
    {
        ContextCondition = context => context.Request.RawUrl.Contains("?amp");
    }
}

Anytime we create a new piece of content, it will act as a regular webpage with all of the trimmings.

However, when we add a "?amp" to the end of the URL as a query string, we will get our AMP page.

All you need to do now is add your AMP files to wherever you want to "AMP" up your pages for Google.

Guidelines for the View

According to Google, the AMP HTML documents MUST:

  • Start with the doctype <!doctype html>.
  • Contain a top-level <html ?> tag (<html amp> is accepted as well).
  • Contain <head> and <body> tags (They are optional in HTML).
  • Contain a <link rel="canonical" href="$SOME_URL" /> tag inside their head that points to the regular HTML version of the AMP HTML document or to itself if no such HTML version exists.
  • Contain a <meta charset="utf-8"> tag as the first child of their head tag.
  • Contain a <meta name="viewport" content="width=device-width,minimum-scale=1"> tag inside their head tag. It’s also recommended to include initial-scale=1.
  • Contain a <script async src="https://cdn.ampproject.org/v0.js"></script> tag as the last element in their head (this includes and loads the AMP JS library).
  • Contain the following in their <head> tag: <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>

This excerpt was taken from the page called Create Your AMP HTML page.

Our View looks like a basic Razor page...just slimmer and trimmer.

Views\Blog\Detail.amp.cshtml

@using CaramelCMS.Core.Extensions
@model DanylkoWeb.ViewModel.BlogPageViewModel
@{
    Layout = null;
}
<!doctype html>
<html amp>
<head>
    <meta charset="utf-8">
    <link rel="canonical" href="@(Model.Url != null ? Model.Url.GetLeftPart(UriPartial.Path): String.Empty)">
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
    <style amp-boilerplate>body {-webkit-animation-amp-start 8s steps(1, end) 0s 1 normal both;-moz-animation-amp-start 8s steps(1, end) 0s 1 normal both;-ms-animation-amp-start 8s steps(1, end) 0s 1 normal both;animation-amp-start 8s steps(1, end) 0s 1 normal both}@@-webkit-keyframes -amp-start {from { visibilityhidden }to { visibilityvisible }}@@-moz-keyframes -amp-start {from { visibilityhidden }to { visibilityvisible }}@@-ms-keyframes -amp-start {from { visibilityhidden }to { visibilityvisible }}@@-o-keyframes -amp-start {from { visibilityhidden }to { visibilityvisible }}@@keyframes -amp-start {from { visibilityhidden }to { visibilityvisible }} </style>
    <noscript>
        <style amp-boilerplate>
            body {
                -webkit-animationnone;
                -moz-animationnone;
                -ms-animationnone;
                animationnone;
            }
        </style></noscript>
    <script async src="https://cdn.ampproject.org/v0.js"></script>
</head>
<body>
    <article>
        <h2>@Html.Raw(Model.Post.Title)</h2>
        <div class="date-info">
            <div class="row">
                <div class="col-md-8">
                    @Html.Raw(Model.Post.PublishedOn.Value.ToFormattedDateTime(false))
                </div>
                <div class="col-md-4 text-right">
                </div>
            </div>
        </div>
        <h3 class="abstract">@Html.Raw(Model.Post.Abstract)</h3>
        @Html.Raw(Model.Post.Description)
    </article>
    
</body>
</html>

Here is our result.

Sample AMP Page using DisplayModes

It's not sexy, but this was my first draft. Hey...this is what Google is looking for to deliver content to users quickly.

How Does Our AMP Pages Get Discovered?

Based on what I've read, you need to place a canonical in your primary content that points to an AMP page.

Since our ContextCondition is looking for an "?amp" on the end of a URL to get the AMP page, this isn't hard to place into our existing header content.

For more information on "Discovery," read over the Google Search Guidelines to get a clear understanding of what you need to do to fully implement Google AMP pages.

To examine your AMP pages, you need to head over to the Google Search Console (formerly Webmaster tools) and look under Search Appearance and you'll find Accelerated Mobile Pages.

Conclusion

I didn't realize this, but Google AMP initiative started in October of last year (2015), but as of this month, the bots are on the hunt for AMP pages.

Fortunately for us ASP.NET MVC users, we have a simple way of building them quickly and easily using DisplayModes.

Did this technique save you a ton of time? Got a better ContextCondition? Post your comments below.

The Complete Guide To Google AMP with ASP.NET MVC

Was this informative? Share it!

Looking to become a better developer?

Sign up to receive ReSharper Design Pattern Smart Templates, ASP.NET MVC Guidelines Checklist, and Newsletter Updates!

Picture of Jonathan Danylko

Jonathan Danylko is a freelance web architect and avid programmer who has been programming for over 20 years. He has developed various systems in numerous industries including e-commerce, biotechnology, real estate, health, insurance, and utility companies.

When asked what he likes to do in his spare time, he replies, "Programming."

comments powered by Disqus