Ember performance tweaks: Search engine optimization

12 min read • 20th July 2020
SEO score

In the last post, we discussed how to perform fingerprinting and for what kind of assets it needs to be enabled. We especially saw how to optimize image assets during runtime, instead of build time. We also touched upon service workers and how we can use that for all assets. This is the third post in the performant Ember app series:

  1. Improving build timelines & optimizing build size
  2. optimizing Assets
  3. Search engine optimization ← this post
  4. Improving the accessibility of Ember apps
  5. Making Ember apps installable

One of the key things to build blazing fast UI is to make sure the web apps/sites score a 100 on the Lighthouse tool.

Predominantly, Lighthouse has five categories. They are:

  • Performance
  • Progressive web app
  • Best practices
  • Accessibility; and
  • SEO

In this article, we will see the last category of Lighthouse audits, which is SEO. Although I must say SEOs are much more important for websites, a small fraction of it also applies to single-page web apps.

Since this blog series is aligned closer to building performant Ember apps, we will see how to obtain a score of 100 for the SEO category on Lighthouse.

Link to this sectionA brief about SEO and why

SEO stands for Search Engine Optimization, which is the practice of increasing the quantity and quality of traffic to your website through organic search engine results.

Quoting from moz.com, here's how SEO works:

Google (or any search engine you're using) has a crawler that goes out and gathers information about all the content they can find on the Internet. The crawlers bring all those 1s and 0s back to the search engine to build an index. That index is then fed through an algorithm that tries to match all that data with your query.

As a developer, a quick introduction to SEO can be obtained from the Chrome console by running Lighthouse audits. Lighthouse is an excellent tool because any Audit contains a suggestion on why one should fix it.

Link to this sectionNew Ember app and Lighthouse score

When I began creating this website ground-up using Ember, the primary motive was to make it optimal from day one. It had to be green on all the Lighthouse categories. I ran the audit only for SEO, to focus on attacking SEO specific problems. The first time I ran the Lighthouse audit on my new Ember app, the SEO score was 90 (green). It is a delightful way to work on an app with such a score. It helps to progressively improvise on top of it.

Interestingly, one of the passed audits also had a description:

✅ Add a <meta name="viewport"> tag to optimize your app for mobile screens. Learn more.

The page belonged to a category called SEO Audits, and that was the goldmine for me to learn what SEO was, as a developer.

First Lighthouse SEO score

Link to this sectionNoticing the suggestions to improvise

Based on the Lighthouse Report, as shown in the screenshot above, a meta tag on the page does not seem to have a proper description. Let's see what index.html holds:

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">

<meta name="description" content="">

<meta name="viewport" content="width=device-width, initial-scale=1">

<meta name="description" content=""> doesn't seem to contain content because we never told it to. Adding the content value, and rerunning the audits, resulted in an SEO score of 100.

Lighthouse SEO score after adding content value

Hurray 🎉! The score is 100, and the results remain green!

For a simple single pager like the one above, there isn't much to do. As the website grows or as we add more articles, every article needs to be validated manually for the SEO category to be green. We will also see how to automate this at the end.

Going back to the Lighthouse SEO page that talks about "How well can search engines understand your content?", the key pointers are:

Let's see what each of these requirements to optimize for SEO are and how Ember can help solve that for you.

Link to this sectionMake sure search engines understand your content

Link to this sectionDocument doesn't have a <title> element

The first point talks about the page having a <title> element or not. By default, while creating a new Ember app, the index.html file generated by ember-cli contains the <title> tag. It contains the name of the app as the title content. If the name of your Ember app is a hyphenated content like sample-web-app, then the output may not be readable and looks like below:


Although it would pass the Lighthouse Audit, it is not a meaningful name!

On the other hand, my website is a collection of blog posts. As a result, each blog post should have its own page title. That means, on page change, the title content should change dynamically.

A quick search on ember observer for addons related to page titles yields a lot of them. We need an addon to solve for the page title to be generated dynamically.

In the latest #st-a11y team meeting, we had a discussion about framing an RFC around adding ember-page-title in the default ember-cli blueprints. While it could become a default after the RFC process, there are also other addons you could choose from. For example, I use ember-cli-meta-tags as a single purpose addon for adding HTML tags (link, script, meta, title, etc) into the <head> section of a page.

Both these addons depend on ember-cli-head and have a requirement to add <HeadLayout /> in the app/templates/application.hbs file.

Link to this sectionDocument does not have a meta description

One of the key requirements of SEO is to provide a proper description in the <meta> tag of each webpage. Earlier, we saw the default <meta name="description" content=""> generated by ember-cli, and we went ahead and added the application's description on what it does. However, a blog, on the other hand, has each post that has its own description. That description changes as we navigate pages.

The content in the description meta tag is used by search engines and social media snippets to showcase the right text under the title.

Like ember-page-title which solves the title problem in Ember apps, I used ember-cli-meta-tags, which we saw in the previous section, for this blog. There are other addons as well. However, the approach of adding a dynamic title plus meta tags and their content could all be solved by this single addon that also works in Fastboot. To install ember-cli-meta-tags:

ember install ember-cli-meta-tags

And in the app/routes/blogs/show.js, the change of the meta content happens in the model() hook. Once the blog's content is fetched from the API, the data is then used in the <meta> tag. Also remember, the meta tags could also be useful for all pages (like category listing) and not only for blog posts. To speak in terms of code, it looks something like below:

import Route from '@ember/routing/route';

export default class BlogShowRoute extends Route {
  model({ slug }) {
    return this.store.findRecord('blog', slug);

  afterModel(model) {

  setHeadTags(model) {
    let headTags = [{
      type: 'title',
      content: model.title
    }, {
      type: 'meta',
      attrs: {
        name: 'title',
        content: model.title
    }, {
      type: 'meta',
      attrs: {
        name: 'description',
        content: model.description
    }, {
      type: 'meta',
      attrs: {
        name: 'author',
        content: "abhilashlr"
    }, ...];

    set(this, 'headTags', headTags);

The above snippet generates the following HTML output:

<title>Ember performance tweaks: Search engine optimization</title>

<meta name="title" content="Ember performance tweaks: Search engine optimization">
<meta name="description" content="Third part in the Ember performance optimization blog series. In this post we concentrate on SEO.">
<meta name="author" content="abhilashlr">

You can check this out by viewing the current page's source or inspecting it in the browser console.

The reason why page source works is because this app is built using prember. This is also an important criteria for SEO since search engine bots need to read the content as mentioned in the beginning. They crawl on pages that has content and index them.

Link to this sectionMake sure search engines can crawl and index your page

Link to this sectionPage is blocked from indexing

For a detailed explanation of what web.dev means, by page indexing can be read here. If the blog has an admin UI that should not be part of search results, they need to be blocked from indexing by the search bot crawlers. To prevent search bots from crawling the admin pages, they can be responded back by adding a header on the HTML response:

X-Robots-Tag: noindex

or those html pages could also contain the following meta tags:

<meta name="robots" content="noindex">

The meta tag could be added as part of the ember-cli-meta-tags script that we added in the previous section.

If you use Netlify as part of your CI/CD and use deploy preview, indexing issue arises in Lighthouse because Netlify prevents indexing of deploy previews by default.

Link to this sectionrobots.txt is not valid

Quoting web.dev:

The robots.txt file tells search engines which of your site's pages they can crawl.

From an Ember app perspective, ember-cli adds a robots.txt file in the public folder. If your apps shouldn't be crawlable, setting the right values in this file should be enough. But setting a wrong value can cause other types of problems like not crawling a public page. Or, crawl all the pages, including sensitive pages like the blog admin.

Solution to fix the robots.txt is well explained here.

Link to this sectionMake your page mobile-friendly

Link to this sectionDoes not have a <meta name="viewport"> tag with width or initial-scale

For an ember app, the meta tag related to "viewport" is set by default and should be green already.

<meta name="viewport" content="width=device-width, initial-scale=1">

Some of the sections discussed above are also part of Accessibility and we would discuss them in the next blog post related to Accessibility.

Link to this sectionBonus: Automating the Audits

One of the fundamental things I look out while working is to automate the repetitive steps. Can we automate the Lighthouse audits? The answer is yes!

Lighthouse's CI tool LHCI can be integrated for performance optimizations as part of your CI/CD pipelines.

LHCI can be integrated with Github Actions or Jenkins and be part of your CI/CD pipeline.

To read more on automations with LHCI, here's my bookmarks that I used for adding it part of my CI/CD pipeline:

Hope that was helpful to you and your team! In the next post, we will see how to improve accessibility of your Ember apps.

Enjoyed this article? Tweet it.

I guess you might be looking to add your comments? Glad to tell you that this section is under construction. But don't hold on to your thoughts! DM them to me on Twitter