How to Add Async JSON+LD Structured Data to a Nuxt.js Web App
If you are not just building a web app, but are serving a content-rich experience on top of it, there is no way around using structured data. Here’s how.
To ensure that content is easily indexed and displayed in rich snippets, we use Google’s JSON+LD structured data.
Most content-driven websites such as recipe or news websites use schema.org vocabulary, but you should rely on the documentation on developers.google.com for Google Search behavior, rather than the schema.org documentation.
A website that runs on WordPress has SEO built in and outputs structured data by default, so most bloggers won’t even know about schema.org, let alone have to deal with it. As a developer of a custom website, you need to ensure that you can at least keep up with that.
Structured Data Delivered Server-Side
Nuxt.js is a minimal framework for creating Vue.js applications with server-side rendering (SSR), code-splitting, static generation and more. If you are developing with Vue.js but are not familiar with Nuxt.js, I urge you to check it out as it will dramatically speed up your development and standardize your app’s structure.
Its vibrant ecosystem has already come up with libraries which you can plug into your app to allow structured data, but I am a fan of being in charge of our own source code. Therefore, no third-party libraries will be used here.
The following snippet will be very useful to those who are already familiar with Nuxt.js’ structure:
<script>
export default {
data() {
return {
structuredData: {
"@context": "http://schema.org",
"@type": "Recipe",
// More structured data...
}
}
},
head() {
return {
__dangerouslyDisableSanitizers: ['script'],
script: [{ innerHTML: JSON.stringify(this.structuredData), type: 'application/ld+json' }]
}
},
async asyncData(context) {
// Pre-fetch and return recipe data server-side.
}
}
</script>
The Snippet Explained
Inside data()
, we define all values that we aim to print out in the structured data block. In case you need to feed the structuredData object with data fetched dynamically from a database back-end, you will want to place the object withinasyncData()
itself, instead of data()
.
Nuxt.js has a very convenient way to inject meta data into a pages’ head section with the help of head()
. This is exactly the place where our structured data block belongs. We create a script tag by returning a script
array. It will have an inner HTML containing the JSON-converted structuredData. Be sure to declare the script of type application/ld+json
.
By default, we would get sanitized HTML which is what the __dangerouslyDisableSanitizers: ['script']
will prevent. Otherwise the inner HTML content will contain quotation marks converted to " and it’s not what Google will be able to parse.
Changes Since Vue Meta 2.1+
Adarsh Madrecha kindly pointed out that vue-meta now supports adding JSON data directly which makes the whole code cleaner. It works for versions 2.1 and above. __dangerouslyDisableSanitizers
is no longer needed:
<script>
export default {
data() {
return {
structuredData: {
"@context": "http://schema.org",
"@type": "Recipe",
// More structured data...
}
}
},
head() {
return {
script: [{ type: 'application/ld+json', json: this.structuredData }]
}
},
async asyncData(context) {
// Pre-fetch and return recipe data server-side.
}
}
</script>
Conclusion
You can now ensure that your content will be easily readable to Google’s crawler and presented as rich snippets in its search results.