Show off your Lighthouse scores as static HTML in Eleventy with the PageSpeed Insights API

The Eleventy neighborhood is targeted on efficiency in a method that you do not are likely to see with different instruments, principally as a result of it tends to draw followers of preserving issues lean and appreciating the basics of the net (the holy trinity of HTML, CSS, and minimal JS – in that order of precedence), and maybe partly as a result of Eleventy Leaderboards baiting everybody’s aggressive sides!

After I first began constructing my personal site I used to be very centered on getting a very good Lighthouse rating. It is dipped then recovered a couple of occasions over time, but it surely has been on the level the place it is one thing I’ve wished to indicate off in my web site’s footer for some time.

At first, I did this utilizing Zach Leatherman’s <speedlify-score> web component which makes use of the Eleventy Leaderboards/Speedlify as its supply of knowledge.

This labored effectively, however the leaderboards are solely up to date sometimes, so it took time for enhancements to indicate up. It additionally felt counter-productive to be utilizing a third-party bundle with its personal client-side JavaScript and CSS to report on efficiency metrics!

I began one thing I might use at construct time as a substitute, and located that the PageSpeed Insights API can return the outcomes of a Lighthouse take a look at!




Getting knowledge from the PageSpeed Insights API and utilizing it in Eleventy

This is not a full tutorial and assumes some prior information of working with npm, APIs, and atmosphere variables.

Let’s check out how I acquired my Eleventy web site to set off a Lighthouse take a look at every time it’s constructed and to indicate the leads to my web site footer.



Get an API key and retailer it in an atmosphere variable

Head to the PageSpeed Insights API’s getting started guide and comply with the hyperlinks to get an API key.

Add the important thing into an atmosphere variable (regionally and in your distant environments – remember to do it on Netlify and so on or your deployments will fail!) referred to as PAGESPEED_API_KEY.



Create a JavaScript knowledge file to carry our API name

Create a lighthouse.js file inside your Eleventy knowledge listing.

Be sure you have put in the dotenv and @11ty/eleventy-cache-assets packages (or alternate options, should you favor).

Add the script under, swapping https://instance.com on your personal URL, or an atmosphere variable representing your individual URL.

require('dotenv').config();
const Cache = require('@11ty/eleventy-cache-assets');

module.exports = async operate () {
  const params = new URLSearchParams();
  params.append('url', 'https://instance.com');
  params.append('key', course of.env.PAGESPEED_API_KEY);
  // We use the fields question string param to ask the Google API to solely
  // return the info we want - a rating and title for every class within the
  // Lighthouse take a look at. With out this, the API returns a *lot* of knowledge, which
  // is not the tip of the world however can also be pointless.
  params.append('fields', 'lighthouseResult.classes.*.rating,lighthouseResult.classes.*.title');
  params.append('prettyPrint', false);
  // I exploit the cell technique, however `desktop` is a sound worth too.
  params.append('technique', 'cell');
  // I've not used the PWA class, however you may whether it is related to your web site.
  params.append('class', 'PERFORMANCE');
  params.append('class', 'ACCESSIBILITY');
  params.append('class', 'BEST-PRACTICES');
  params.append('class', 'web optimization');

  let knowledge = await Cache(`https://www.googleapis.com/pagespeedonline/v5/runPagespeed?${params.toString()}`, {
    length: '1d',
    sort: 'json',
  });

  knowledge = knowledge.lighthouseResult.classes;

  const getGrade = operate (rating) {
    if (rating < 0.5) {
      return 'unhealthy';
    }
    if (rating < 0.9) {
      return 'okay';
    }
    return 'good';
  };

  Object.keys(knowledge).map(operate (key) {
    knowledge[key].rating = (knowledge[key].rating * 100).toFixed();
    knowledge[key].grade = getGrade(knowledge[key].rating);
  });

  return {
    classes: knowledge,
  };
};
Enter fullscreen mode

Exit fullscreen mode

The operate will return an object containing one other object referred to as classes, within which will probably be your scores. I nested the scores within the classes object in case we ever need to return the rest from lighthouse.js, like some Core Internet Vitals scores maybe?



Instance output

{
  "classes": {
    "efficiency": { "title": "Efficiency", "rating": "100", "grade": "good" },
    "accessibility": { "title": "Accessibility", "rating": "100", "grade": "good" },
    "best-practices": { "title": "Finest Practices", "rating": "100", "grade": "good" },
    "web optimization": { "title": "web optimization", "rating": "100", "grade": "good" }
  }
}
Enter fullscreen mode

Exit fullscreen mode



Utilizing the info in a template

Due to the magic of Eleventy knowledge recordsdata, now you can loop over the scores by way of lighthouse.classes virtually wherever you want.

Most of my web site makes use of the Eleventy Vue plugin, however my footer continues to be utilizing a Nunjucks file, so here is how I displayed the scores. I am utilizing Tailwind right here for styling, however after all, you’ll be able to type the output nonetheless you want – it is your web site!

<div class="flex flex-wrap items-center gap-2">
  <p id="homepage-lighthouse-scores">Homepage Lighthouse scores (%):</p>
  <ul
    class="flex items-center space-x-1"
    aria-labelledby="homepage-lighthouse-scores"
  >
    {% for key, lead to lighthouse.classes %}
    <li
      class="flex items-center justify-center cursor-help rounded-full h-8 w-8 border-2 {{ 'border-green-300' if consequence.grade === 'good' else 'border-yellow-400' }}"
      title="{{ consequence.title }}"
    >
      <span class="sr-only">{{ consequence.title }}: </span>{{ consequence.rating }}
    </li>
    {% endfor %}
  </ul>
</div>
Enter fullscreen mode

Exit fullscreen mode

…and here is the way it appears!:

Screenshot of a website showing Lighthouse test results represented by coloured circles. Each circle is green and shows a score of 100



Room for enchancment

Listed here are some concepts for methods to adapt this to make it your individual:

  • My web site is principally a single big web page, so I solely hassle to check one URL. Maybe you’d prefer to swap the info file for a template function so you’ll be able to run a person take a look at for every web page in your web site by using this.page.url?
  • My color scheme for my footer is yellow so that is the default color I’ve used for my rings. Even when I acquired a nasty Lighthouse rating, the rings would nonetheless be yellow, not crimson. If you’re getting some low scores it’s best to most likely add some further Nunjucks code to output a crimson border if consequence.grade === 'unhealthy', in any other case the yellow color I’m utilizing would make it seem like all of your grades are ‘okay’!

Add a Comment

Your email address will not be published. Required fields are marked *