Advanced SEO-Workflow with Nuxt 2

SEO
Mixins
Nuxt
Oct 18, 2021

Learn how to improve your Nuxt SEO-Workflow using Mixins and the "Don’t repeat yourself" principle.

What to achieve?

In a past post, I showed how to successfully implement SEO aspects like OGP, JSON-LD and more in Nuxt. However, in this post, I want to show you how to use advanced workflows to improve effectiveness and maintainability.

If you are not quite familiar with SEO in Nuxt, read the mentioned post first.

How to achieve?

To set SEO information, in Nuxt we use the head() method of a page.

Vue
pages/index.vue
<script>
  export default {
    head() {
      // ...
    }
  };
</script>

However, as the project size increases, so does the number of pages. Since we always use the same method, we can start here. The goal is not to write the same method and all its implementation for each page individually and statically.

What are Mixins?

Since there is already Nuxt 3 in beta and the Composition API is available, using mixins is considered kind of obsolete. When Nuxt 3 is out of beta, I will create a new and updated post. However, the following content will still work well with Nuxt 2.

Mixins are a flexible way to distribute reusable functionalities for Vue components. A mixin object can contain any component options. When a component uses a mixin, all options in the mixin will be “mixed” into the component’s own options.

Vue Documentation

Tl;dr - you can write your head() method once and reuse it in any of your pages.

You can look in the Vue docs to learn more about Mixins.

Create the Mixin

The first thing we do is create our Mixin. Create the folder ~/mixins. Also create the Mixin file named SEO.js inside the folder and add the head() method.

JavaScript
mixins/SEO.js
export default {
  head() {
    // ...
  }
};

To use the Mixin, you can implement it within a page as follows.

Vue
pages/index.vue
<script>
  import SEO from '~/mixins/SEO.js';

  export default {
    mixins: [SEO]
  };
</script>

Get the data

In order to be able to use the created Mixin in a meaningful way, we first have to define how we get the SEO data. Since the Mixin is a part of the component and therefore has full access to its data, we can define an object with all the necessary SEO properties.

Vue
pages/index.vue
<script>
  import SEO from '~/mixins/SEO.js';

  export default {
    mixins: [SEO],

    data() {
      return {
        seo: {
          title: 'Blog | thenextbit',
          description: 'Blog about Jamstack, ...',
          image: 'https://...'
        }
      };
    }
  };
</script>

The properties structure you set is up to your needs. In the following example, you can see the implementation of the title, description, and OGP properties inside the Mixin.

JavaScript
mixins/SEO.js
export default {
  head() {
    const head = {
      title: this.seo.title,
      meta: [
        {
          hid: 'description',
          name: 'description',
          content: this.seo.description
        },
        // OGP
        {
          hid: 'og:title',
          property: 'og:title',
          content: this.seo.title
        },
        {
          hid: 'og:description',
          property: 'og:description',
          content: this.seo.description
        },
        {
          hid: 'og:type',
          property: 'og:type',
          content: this.seo.type || 'website'
        },
        {
          hid: 'og:image',
          property: 'og:image',
          content: this.seo.image
        },
        {
          hid: 'og:locale',
          property: 'og:locale',
          content: 'en_US'
        },
        {
          hid: 'og:url',
          property: 'og:url',
          content: 'https://thenextbit.de' + this.$route.path
        },
      ]
    };

    return head;
  }
};

Make it more dynamic

You can now make logical conditions and adjustments according to your needs. In the following example, I add the appropriate OGP metadata to each page of type "article".

JavaScript
mixins/SEO.js
export default {
  head() {
    const head = {
      // ...
    };

    if (this.seo.type === 'article') {
      head.meta.push(
        {
          hid: 'article:published_time',
          property: 'article:published_time',
          content: this.seo.first_publication_date
        },
        {
          hid: 'article:modified_time',
          property: 'article:modified_time',
          content: this.seo.last_publication_date
        },
        {
          hid: 'article:author',
          property: 'article:author',
          content: 'https://thenextbit.de/en/about'
        }
      );
    }

    return head;
  }
};

Conclusion

You can now manage your SEO structure centrally and in a DRY way. You no longer need to implement the same structure every time for every page.