ScreenshotNeo

BlogHow-to

How to Set Open Graph Tags in a Nuxt Website

Add page-specific Open Graph tags in Nuxt 4 with useSeoMeta or useHead, then inspect the rendered HTML to verify each route’s metadata.

By the ScreenshotNeo team4 October 20268 min read

For a Nuxt 4 page, add Open Graph metadata where that page’s data is available. In most cases, use useSeoMeta: it provides a flat, typed API for fields such as ogTitle, ogImage, and ogUrl. Use useHead when you want to write explicit property/content meta entries or need lower-level control of the document head.

The Open Graph Protocol requires four basic properties: og:title, og:type, og:image, and og:url. Add a useful og:description as well. Put route-specific values in the page or component that knows the route’s title, description, canonical URL, and image, then inspect the rendered HTML to confirm the final tags.

1. Add page-specific tags with useSeoMeta

In a Nuxt page, define the metadata in the same place where the page’s content is known. Replace the example URL and text with values for the actual route. The image should be an absolute URL to an image that represents the page.

<script setup lang="ts">
useSeoMeta({
  title: 'Article title',
  description: 'A concise page description.',
  ogTitle: 'Article title',
  ogDescription: 'A concise page description.',
  ogType: 'article',
  ogUrl: 'https://example.com/articles/article-slug',
  ogImage: 'https://example.com/images/article-share.jpg',
})
</script>

<template>
  <main>
    <h1>Article title</h1>
    <p>The page content goes here.</p>
  </main>
</template>

Nuxt’s useSeoMeta keys use camel case, such as ogTitle for the protocol property og:title. Nuxt documents this SEO-focused, typed interface as a way to reduce mistakes in metadata key names. See the Nuxt 4 SEO and Meta guide.

The example uses article as the Open Graph type because it represents an article page. Select a type that accurately describes the object being shared. The protocol defines the fields and their meanings; it does not determine how every sharing platform will display them.

2. Use reactive route data when metadata depends on content

For a page whose title and image come from loaded route data, derive the metadata from that data instead of repeating a static value. Nuxt’s useSeoMeta reference supports computed getter syntax for reactive values. Keep the metadata in the page where the relevant data is available.

<script setup lang="ts">
const route = useRoute()
const { data: article } = await useAsyncData(
  `article-${route.params.slug}`,
  () => $fetch(`/api/articles/${route.params.slug}`),
)

useSeoMeta({
  title: () => article.value?.title ?? 'Article',
  description: () => article.value?.description ?? 'Read this article.',
  ogTitle: () => article.value?.title ?? 'Article',
  ogDescription: () => article.value?.description ?? 'Read this article.',
  ogType: 'article',
  ogUrl: () => `https://example.com/articles/${route.params.slug}`,
  ogImage: () => article.value?.shareImage ?? 'https://example.com/images/default-share.jpg',
})
</script>

Adapt the data-loading endpoint and fields to your application. Ensure the fallback values are valid for routes where data is missing or still loading. If your app uses a different reactive source, use the corresponding Nuxt-supported reactive values.

3. Choose between useSeoMeta and useHead

API Use it when Example key style
useSeoMeta You want a flat, SEO-oriented object with typed metadata keys. ogTitle: 'About us'
useHead You want explicit meta objects or broader control over head entries. { property: 'og:title', content: 'About us' }

Both are Nuxt head-management APIs. Choose one style for a given set of fields and avoid declaring the same Open Graph property in global configuration and page metadata unless you have checked how the final head is composed.

With useHead, use the Open Graph property name literally and provide its content:

<script setup lang="ts">
useHead({
  meta: [
    { property: 'og:title', content: 'About Us' },
    { property: 'og:description', content: 'Learn more about our company.' },
    { property: 'og:type', content: 'website' },
    { property: 'og:url', content: 'https://example.com/about' },
    { property: 'og:image', content: 'https://example.com/images/about-share.jpg' },
  ],
})
</script>

useHead accepts dynamic and reactive inputs. Nuxt’s useHead reference documents the explicit property form and reactive head input. Use values that update with the relevant route data when the page is dynamic.

4. Set shared defaults without hiding page-specific values

Nuxt’s SEO guide documents app.head in nuxt.config for static, site-wide head configuration. It cannot supply reactive data. For reactive shared configuration, Nuxt recommends useHead() in app.vue. Page-specific Open Graph values belong where the corresponding route or content data is known.

A shared title template can add the site name to page titles:

// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      titleTemplate: '%s · Example Site',
    },
  },
})

Use shared defaults for genuinely shared information, and set each route’s own Open Graph title, description, URL, and image where needed. After combining global and page-level head entries, inspect the output so each property has the intended value.

5. Know which Open Graph fields to include

Field Meaning and guidance
og:title The title of the shared object. Required by the protocol.
og:type The object type, such as article or website. Required.
og:image The representative image URL. Required.
og:url The canonical URL and permanent identifier for the object. Required.
og:description A description of the object. Optional in the protocol and generally recommended.
og:site_name The name of the overall site. Optional and useful when applicable.

The Open Graph Protocol also defines optional structured image properties: og:image:secure_url, og:image:type, og:image:width, og:image:height, and og:image:alt. Add them only when the values are accurate and useful. They supplement og:image; they do not replace it.

With useSeoMeta, use Nuxt’s documented camel-case SEO keys for the fields it exposes. With useHead, write the protocol property names directly. If you need a structured property that is not convenient in your SEO object, the explicit useHead form lets you express a property/content pair.

6. Inspect the rendered head

  1. Open the route’s returned HTML, using the page source or an HTTP response from the running or deployed application.
  2. Find the document’s <head> and check for og:title, og:type, og:image, and og:url.
  3. Confirm the values belong to this route: especially the canonical URL, title, and image URL.
  4. Check for duplicate declarations that could leave an unintended value in the final head.
  5. Repeat for representative routes, including a route that gets its metadata from loaded content and one using fallback data.

This checks what the application returned, rather than just what the component source intended to declare. Platform previews can differ; do not assume one HTML inspection proves every crawler renders a card identically.

7. Common problems and fixes

Symptom Likely cause Fix
A tag is absent or has an unexpected name. Using an incorrect key or metadata shape. Use Nuxt’s documented useSeoMeta key such as ogTitle, or an explicit { property: 'og:title', content: '...' } entry with useHead.
Every route shows the same title, URL, or image. Metadata is declared only as a static shared default, or route data is not wired into reactive values. Define route-specific metadata where that route’s data is available. Use reactive getters for values that change with data.
The URL identifies the wrong page. og:url was copied from another route or uses an unintended URL form. Set it to the actual canonical URL for this object and verify the rendered value.
The image field is missing or points to the wrong asset. The page has no page-specific image value, or a fallback is being used unexpectedly. Provide the intended image URL and inspect the final HTML. Add structured image properties only when their values are known.
Global metadata seems to conflict with page metadata. The same property is declared in multiple places. Remove redundant declarations where possible, then inspect the final head for one intended value per property.
Values appear stale after route data changes. The metadata was captured as a static value rather than derived reactively from the data source. Use the reactive form appropriate to the source; Nuxt documents computed getter syntax for useSeoMeta.

8. Performance, reliability, and cost

Open Graph tags are document metadata, so the key implementation concern is that the returned HTML for each route contains the correct values. Keep route metadata tied to the data-loading path that determines the page content, and provide deliberate fallback metadata for missing data. The reviewed Nuxt and protocol references do not establish universal crawler behavior or a preview-cache lifetime, so verify the actual HTML and avoid promises about identical displays across platforms.

Adding metadata through Nuxt’s head APIs does not require a screenshot service. If you need to visually inspect how a page renders, a screenshot can help you review the page itself, but it does not replace checking the returned head markup. ScreenshotNeo is a website screenshot API and MCP server; its API can capture a page as an image or PDF, with options such as waiting for a selector or capturing full-page content. See the ScreenshotNeo site and its API documentation.

For cost planning, ScreenshotNeo’s free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. ScreenshotNeo says only clean shots are billed, while bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, with response headers reporting the page verdict and billing status. These are screenshot-service terms, not a cost or performance guarantee for Nuxt metadata or social crawlers.

Or skip the browser setup

If you want a visual capture of a Nuxt route without setting up a browser automation stack, request a screenshot from ScreenshotNeo. Replace the target URL with a publicly reachable route you want to inspect. This captures the rendered page; inspect the page’s returned HTML separately to verify its Open Graph tags.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up for the free plan.

FAQ

Do I need a separate Open Graph package in Nuxt?

The Nuxt head APIs in this guide provide the documented way to set these metadata fields. Use useSeoMeta for the straightforward typed SEO object or useHead for explicit head entries.

Should Open Graph values match the visible page title?

They should accurately describe the page being shared. They can differ in wording, but keep the route’s identity and content consistent.

Is this advice for Nuxt 3?

This guide targets Nuxt 4. Nuxt’s v3 documentation identifies itself as v3.21.11 and says Nuxt 3 reached end of life on 31 July 2026. Treat Nuxt 3 instructions as version-specific legacy context and check the applicable support arrangement before relying on them. See the Nuxt 3 SEO and Meta documentation.