I need help with dynamic metatags in Nuxt application. I have dynamic component, like this:
```
<template>
<div>
<QcLoader v-if="$fetchState.pending" />
<heroSection :blog="blog" />
<remoteSection :blog="blog" />
<readmoreSection :more-blogs="moreBlogs" />
</div>
</template>
<script>
import { BLOCKS } from '@contentful/rich-text-types'
import { documentToHtmlString } from '@contentful/rich-text-html-renderer'
import client from '@/plugins/contentful'
export default {
name: 'Blogid',
components: {
QcLoader: () => import('@/components/partials/QcLoader.vue'),
heroSection: () =>
import('@/components/sections/company/blog/post/heroSection.vue'),
remoteSection: () =>
import('@/components/sections/company/blog/post/remoteSection.vue'),
readmoreSection: () =>
import('@/components/sections/company/blog/post/readmoreSection.vue'),
},
data() {
return {
blog: [],
moreBlogs: [],
metadataObject: {}
}
},
fetchDelay: 1000,
fetch() {
client
.getEntries({
content_type: 'blogPost',
'fields.slug[in]': this.$route.params.blog,
})
.then((entry) => {
console.log("::: BLOG ENTRY :::", entry)
console.log(this.$router.getRoutes())
entry.items.forEach(blog => {
this.metadataObject = {
title: blog.fields.title,
description: blog.fields.firstTestField.content[0].content[0].value || blog.fields.firstTestField.content[0].content[0].content[0].value,
url: `https://qedcode.io/company/blog/${blog.fields.slug}`,
imageUrl: blog.fields.image.fields.file.url,
imageWidth: blog.fields.image.fields.file.details.image.width,
imageHeight: blog.fields.image.fields.file.details.image.height,
}
})
console.log("::: METADATA :::", this.metadataObject)
this.blog = entry.items[0]
const rawRichTextField = entry.items[0].fields.firstTestField
const options = {
renderNode: {
[BLOCKS.EMBEDDED_ASSET]: (node) => {
const file = node.data.target.fields.file
if (
file.contentType === 'image/jpeg' ||
file.contentType === 'image/png'
) {
return '<img src=' + file.url + '>'
}
},
},
}
return documentToHtmlString(rawRichTextField, options)
})
.then((renderedHtml) => {
document.getElementById('blog-html').innerHTML = renderedHtml
})
.catch((err) => {
return err
})
client
.getEntries({
content_type: 'blogPost',
order: '-sys.createdAt',
})
.then((res) => {
this.moreBlogs = res.items
})
.catch((err) => {
this.moreBlogs = []
return err
})
},
head() {
return {
title: this.metadataObject.title,
titleTemplate: '%s',
meta: [
{
name: 'description',
hid: 'description',
content: this.metadataObject.title,
},
/* Open Graph */
{
name: 'og:title',
hid: 'title',
content: this.metadataObject.title,
},
{
name: 'og:site_name',
hid: 'site-name',
content: 'QED',
},
{
name: 'og:url',
hid: 'url',
content: this.metadataObject.url,
},
{
name: 'og:description',
hid: 'description',
content: this.metadataObject.description,
},
{
name: 'og:type',
hid: 'type',
content: 'website',
},
{
name: 'og:image',
hid: 'image',
content: this.metadataObject.imageUrl,
},
{
name: 'og:image:width',
hid: 'image-width',
content: this.metadataObject.imageWidth,
},
{
name: 'og:image:height',
hid: 'image-height',
content: this.metadataObject.imageHeight,
},
/* Twitter */
{ name: 'twitter:card', content: 'summary_large_image' },
{ name: 'twitter:site', content: '@QED_code' },
{
name: 'twitter:title',
content: this.metadataObject.title,
},
{
name: 'twitter:description',
content: this.metadataObject.description,
},
{ name: 'twitter:url', content: this.metadataObject.url },
{
name: 'twitter:image',
content: this.metadataObject.imageUrl,
},
],
link: [
{
rel: 'canonical',
herf: 'https://qedcode.io',
},
],
}
},
fetchOnServer: false,
}
</script>
```
The problem is that when I click on "View Page source", the metatags are undefined. My guess is that fetch() method executes after head() method.
This is Page source after code is executed (you can see that all values are undefined): Page source
The component is type of blog, so it's dynamic and for each blog I need different metatags.
When I click on each blog, the metadataObject fills that data property like this:

By default ssr property is switched ON in your nuxt.config.js which enabled crawlers to recieve a page from the server (instead of just a JS package that is impossible to crawl for meta tags etc).
This forces you to use asyncData due to the nuxtJS lifecycle. You can still access most of the app's information that you would need for your meta.