AMP website cookie consent and further tuning

May 22, 2020

I promised improvements in my previous blog posts and I want to keep you updated about the changes of the last twelve days.

  • A major feature is that I introduced a Cookie consent notification. I’m using amp-consent in combination with amp-lightbox. Sicne this is such a common scenario I thought it’ll be a simple task. Unfortunately it was utterly painful. The amp-consent component is pretty advanced, for example it is able to distinguish geological regions if needed.
    • amp-consent is not capable of handling cookie categories though. Therefore all I needed was a modal dialog which listed the possible cookies my website would use.
    • No categories would mean that if someone rejects the consent, then all cookie related features would be turned off, there’s no cherry picking or middle ground. In my case these features are Google Analytics and Disqus comments. This can be achieved by marking the AMP elements which needs to be turned off with data-block-on-consent attribute.
    • Without AMP it’s actually not trivial to block a Google Analytics snippet to kick in until a consents is Accepted. It’d require injecting some DOM after the consent. AMP at least does that out of the box for us. But before that you’d need to get the consent form working.
    • I wanted to keep it simple and avoid hosting an own modal dialog in an off-site domain for an iframe based solution. Cookie consent is so common that such task should be able to be carried out in-house (without external site).
    • I scouted out the amp-story-consent route so I’d be able to take advantage of the default UI the story can provide me. This alley was a failure. I realized that despite the simple code snippets I’d need story pages and bookend, which is just an overkill, just like the 81.4 KB size of the amp-story-0.1.js. For a glimpse of my desperate tries click here.
    • I tried to utilize amp-user-notification along with amp-consent but after lengthy trials I had to give up and abandon that route as well. The two just don’t work together.
    • I had to move back to the basics and design my own modal dialog from ground zero. But the modal backdrop didn’t want to work and it’d be quite ugly if users could still accidentally click behind the consent dialog. Noone came to my help until I accidentally came across amp-lightbox during my desperate tries and that saved me from tearing all my hair out.
    • This was not needed in the end (I can use “consentRequired”: true for a simple scenario), but just to show you how far I went: I even spinned out my own cloud function REST endpoints for data-show-if-href of amp-user-notification and the checkConsentHref of amp-consent. I went through hell fighting with various flavors of CORS related error messages until I figured out working versions:
addEventListener("fetch", event => {
    event.respondWith(handleRequest(event.request))
  })

  /**
   * Respond to the request
   */
  async function handleRequest(request) {
    return new Response(
      JSON.stringify({ "consentRequired": true }),
      {
        headers: {
          "Access-Control-Allow-Origin": request.headers.get("Origin"),
          "Access-Control-Allow-Credentials": "true",
          "Content-Type": "application/json"
        },
        status: 200
      }
    )
  }
  • rel=”noopener noreferrer” was added to the target=”_blank” links to increase site security (hint was given by the webhint.io scanner).
  • Removed some accidental !important directives from CSS, these are not allowed by AMP validation and are anti-patterns anyway.
  • Some tools revealed that one of my webp images was accidentally a jpeg. I re-encoded the resource. Also some manifest and touch icons weren’t the expected dimensions. I regenerated those to the proper size from vectorial SVG using InkScape.
  • Added type attribute to some buttons.
  • Ironed out some accessibility issues: specified labels and titles.
  • The wide range of tools including the AMP validator and the Chrome Developer tools help to spot any inconsistency with validity, accessibility, or security.
  • Since Roboto is the default font of Android and Chrome OS and it’s widely used and cached I think it was a good decision to move towards it. I played around with the font hosting though to gauge speed. Not self hosting the font at all seemed to not yield any speed increase. I wanted to move to Google CDN hosting, but their link means an extra request. I settled with a hybrid solution: for woff2 I refer to Google’s CDN, but I self host the woff and the ttf versions. This seems to be an ideal solution so far which doesn’t hurt performance for default cases.
  • On the hosting front-end I’m minifying the HTML content. This is done by jekyll-minifier and compress-html.

Let’s talk about the measurements:

  1. Official Lighthouse, results: 98 / 100 / 100 / 100
  2. webpagetest.org Lighthouse, results 05/14/2020: 96 / 100 / 100 / 100, results 05/15/2020: 94 / 100 / 100 / 100
  3. webhint.io scanner, results: 12 / 49 hints

Future plans: feature amp-google-vrview-image on blog posts which include VR content (GooglePlex visits for example). Besides that the goal is to improve further and reach 100 / 100 / 100 / 100 score.

Load more