Title / Meta description into the page HEAD

I'm new at VueJs.
I'm building a Portfolio website and want to add the page title and meta descriptions to the pages.
In the vue examples they are added as static content into the public/index.html.

Is there a way to get these fields from the Prismic Repo ?

Hi Henk,

Welcome to the community!

Yes, you can do this from your Prismic repo no problem.

First you’ll have to add the fields in your custom type and document in Prismic. We describe this here:

Though essentially you’ll just need to add some key text fields to add your seo title & descriptions etc.

Then because Vue creates an SPA, meaning you can add SEO tags to each view, you’ll need to use the Vue-Meta plugin:

This allows you to create an ‘Head’ seo object in your views. Then here you’ll pass in the content of your SEO fields from Prismic.

Let me know how this goes. :grin:

Thanks.

How do i get those key fields into the VueMeta? You have an example for this?

Sure, essentially you need to query your different meta data fields and set them as variables, here I also used an or operator as a backup for empty fields:

this.meta.seo_title = document.data.seo_title || 'default title'

Then you need return the content in the data function.

data () {
  return {
    meta: {
      seo_title: null
    }
},

Finally Instead of defining metaInfo as an object, define it as a function and access this:

metaInfo () {
  return {
    title: this.meta.seo_title
  }
},

Here’s a full example I prepared using our sample vue blog.

data () {
  return {
    dateOptions: { year: 'numeric', month: 'short', day: '2-digit' },
    documentId: '',
    meta: {
      seo_title: null,
      seo_description: null
    },
    fields: {
      title: null,
      date: null
    },
    slices: []
  }
},
metaInfo () {
  return {
    title: this.meta.seo_title,
    meta: [
      { vmid: 'description', name: 'description', content: this.meta.seo_description }
    ]
  }
},
methods: {
  getContent (uid) {
    //Query to get post content
    this.$prismic.client.getByUID('post', uid)
      .then((document) => {
        if (document) {
          this.documentId = document.id
          this.fields.title = document.data.title
          this.fields.date = document.data.date
          this.meta.seo_title = document.data.seo_title || 'default title'
          this.meta.seo_description = document.data.seo_description ||  'default description'
          
          //Set slices as variable
          this.slices = document.data.body
        } 
        else {
          //returns error page
          this.$router.push({ name: 'not-found' })
        }
      })
  }
},

Here’s the plugin’s doc’s on dynamic data and remember to pass the plugin to vue.use if you’re using the vue-router.

Thanks for your example :slight_smile:

I added the Tab Social Cards with the Slice : general_card fields: seo_title , seo_description and seo_image in my JSON like your first example.

Because it’s a slice, I think it must be setup in the slice?

Your code is for the views/Blog.vue. So I must add the fields to the custom type, and not to a Slice.

Or can I add it to the App.vue so it’s not needed to add to each Custom Type in the Views folder ?

In my App.vue:

export default {
  name: 'App',

  metaInfo: {
    title: 'Default Title',
    titleTemplate: '%s - Company Name',
    htmlAttrs: {
      amp: true
    }
  },

When I add to my views/HomePage.vue:

<script>

// imports for all components
import SlicesBlock from '../components/SlicesBlock.vue';
import Banner from "../components/Banner.vue"

export default {
  name: 'home',
  components: {
    SlicesBlock,
    Banner
  },
  data () {
    return {
      documentId: '',
      fields: {
        title: null,
        page_title: null,
        tagline: null,
        image: null,
        button_link: null,
        button_label: null
      },
      slices: []
    }
  },
  metaInfo () {
    return {
      title: this.fields.page_title,
    }
  },
  methods: {
    getContent () {
      //Query to get home content
      this.$prismic.client.getSingle('home')
        .then((document) => {
          if (document) {
            this.documentId = document.id;
            this.fields.page_title = document.data.page_title;


            //Set slices as variable
            this.slices = document.data.body

          } else {
            //returns error page
            this.$router.push({ name: 'not-found' })
          }
        })
    },
  },

  created () {
    this.getContent()
  }
}
</script>

my Window Title will display: [object Object] - Company Name

When I change the title to custom text:

  metaInfo () {
    return {
      title: 'custom text',
      titleTemplate: '%s   - Company Name',
    }
  },

my Window Title will display: custom text - Company Name

I can’t find out why the variable isn’t showing up.


Edit:

My fault, I had a Title field instead of a Key Field. With the Key field it is working!! :see_no_evil:

Yes, I should have made it clearer that using key text fields are easier to use here.

It seems you figured out that this needs to be done on the view level, that’s good.

Did you figure out how to pass the data from the Slice to the metaInfo function?

In the example of the SEO tags & social cards the fields were RichTextFields instead of the Key text fields. When it’s on a slice level, the views template is much cleaner.

Only on view level indeed :slight_smile:

I didn’t figure out how to get the data it in Slice…

When I share a link of the site, the default title and description in the public/index.html were shown. Do I need to remove the title and meta description in the public/index.html file?