Vue cookbook · Beginner
Add SEO metadata and structured data in Nuxt
Product pages have generic titles, no social previews and no structured data.
Approach
Set title, description, canonical URL and Open Graph tags with useSeoMeta and useHead from the page's data,
and add JSON-LD structured data. Everything is rendered on the server for crawlers.
Solution
<!-- app/pages/products/[slug].vue -->
<script setup lang="ts">
const route = useRoute();
const { data: product } = await useFetch(`/api/products/${route.params.slug}`);
if (!product.value) throw createError({ statusCode: 404, statusMessage: "Product not found" });
const url = `https://shop.example.com/products/${route.params.slug}`;
useSeoMeta({
title: () => `${product.value?.name} | Kitchen shop`,
description: () => product.value?.summary,
ogTitle: () => product.value?.name,
ogDescription: () => product.value?.summary,
ogImage: () => product.value?.imageUrl,
twitterCard: "summary_large_image",
});
useHead({
link: [{ rel: "canonical", href: url }],
script: [{
type: "application/ld+json",
innerHTML: () => JSON.stringify({
"@context": "https://schema.org",
"@type": "Product",
name: product.value?.name,
image: product.value?.imageUrl,
offers: { "@type": "Offer", price: product.value?.price, priceCurrency: "USD", availability: "https://schema.org/InStock" },
}),
}],
});
</script>
<template>
<h1>{{ product?.name }}</h1>
</template>
Pitfalls
- Setting metadata in
onMounted, which crawlers don't see. - Missing canonical URLs on pages reachable through several URLs (filters, tracking parameters).
- Status 200 for missing products; throw
createErrorwith 404.
Variations
- The
@nuxtjs/seomodule adds sitemaps, robots rules, OG image generation and schema.org helpers. - Use
titleTemplateinapp.vuefor a consistent site suffix.
Further reading: SEO and meta
Reference: https://nuxt.com/docs/4.x/getting-started/seo-meta
More Vue recipes
- Access child component methods with template refs and defineExpose
- Build an accessible modal with Teleport
- Build custom inputs with defineModel and modifiers
- Catch component errors with an error boundary
- Debounce user input with a custom ref
- Fetch data in a composable and cancel stale requests
- Fetch, refresh and share data with Nuxt useFetch
- Implement a dark mode toggle that respects system settings