written by Andre Liem
07/24/2017

Improving the SEO of a Nuxt Js site with Meta Tags

TL;DR Nuxt JS makes it easy to customize the meta tags of each page to ensure your site is following SEO best practices.

First off, this article is not a SEO guide by any means, it's simply a short article to get you going with some basic Meta tags which should help with SEO. I know that the rules of the game for SEO change constantly, but from what I've observed, having good content and accurate meta tags is a pretty consistent rule of thumb for being indexed well by search engines like Google.

Understanding Nuxt Meta

NuxtJs makes configuration of meta tags on a per page/url basis very easy. Lets start with the top level in nuxt.config.js

Here is what I have in my site configuration.

module.exports = {
  head: {
    title: 'Vuejs Radar - Stay in the loop with VueJS News',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: 'Vue JS Radar' },
      { hid: 'keywords', name: 'keywords', content: 'vuejs, nuxt, javascript, tutorials, development, software' }
    ],

This is pretty self explanatory.

The title value maps directly to the HTML <title></title>, and then each value within the meta array creates a new <meta></meta> tag with the corresponding name and content attribute.

The result is something like this:

<meta data-n-head="true" charset="utf-8"/>
<meta data-n-head="true" name="viewport" content="width=device-width, initial-scale=1"/>
<meta data-n-head="true" data-hid="description" name="description" content="Tips for having a Nuxt site optimized for SEO"/>
<meta data-n-head="true" data-hid="keywords" name="keywords" keywords="vuejs, nuxtjs, seo, meta, sitemap, modules"/> 
<title data-n-head="true">TITLE GOES HERE</title> 

Nuxt adds in data-n-head into this but for the most part it's pretty standard meta tags.

HID?

You are probably wondering about the key name hid? It's needed if you want to overwrite any meta tag with another one. The most obvious example is where you have dynamically generated URLs which need to have custom meta tags. This is of course very important to have for search engines so that they can uniquely index each of your pages.

For now, just note that the HID value can be anything you want. I just decided to call it description and keywords to keep things simple.

Custom Meta Tags per URL with HID

In the case of our site, we use the file _slug/index.vue to generate unique blog post URLs. This file will have access to blog post data defined in a vuex store.

We currently store all of the SEO data within each blog post like this.

{
  id: 6,
  is_published: true,
  slug: 'seo-for-nuxt',
  title: 'Improving the SEO of a Nuxt Js site',
  created_at: '07/20/2017',
  meta: {
    id: 6,
    name: 'Improving the SEO of a Nuxt site',
    content: 'Tips for having a Nuxt site optimized for SEO',
    keywords: 'vuejs, nuxtjs, seo, meta, sitemap, modules'
  }
}

This is an arbitrary data structure. It's a bit verbose as most of the values in the meta tags are the same as the main post content. For now this serves my purposes well as I want the ability to customize the meta tag content beyond the plain title description.

Going into the file which renders each blog post _slug/index.vue, there's a specialized function called head() which is responsible for returning customized head data.

The gist of this is here:

<script type="text/javascript">
  head () {
    let post = this.post
    return {
      title: post.meta.name,
      meta: [
        {
          hid: `description`,
          name: 'description',
          content: post.meta.content
        },
        {
          hid: `keywords`,
          name: 'keywords',
          keywords: post.meta.keywords
        }
      ]
    }
  }
</script>

With this basic function, all we need to do is pull in the post data and map it to the returned head object. We can overwwrite the description and keyword meta tags which were defined globally by ensuring the hid tags here match the same values.

The official docs explain the head method in more detail here

That's basically it! With this basic setup you can now have customized meta tags per blog post, keeping all of this work mostly centralized in your vuex store.