nuxt logo

Traducción de Documentación (No Oficial)

SEO y Metadatos

Mejora el SEO de tu aplicación Nuxt utilizando configuraciones de encabezado potentes, composables y componentes.

La gestión de etiquetas de encabezado en Nuxt se realiza a través de Unhead. Proporciona configuraciones adecuadas por defecto y ofrece varios composables potentes y numerosas opciones de configuración para gestionar el encabezado de la aplicación y las metaetiquetas de SEO.

Configuración de Nuxt

Puedes personalizar estáticamente el encabezado de toda la aplicación configurando la propiedad app.head en nuxt.config.ts.

Este método no permite proporcionar datos reactivos. Recomendamos usar useHead() dentro de app.vue.

Es una buena práctica establecer aquí etiquetas que no cambian, como el título predeterminado del sitio, el idioma y el favicon.

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      title: 'Nuxt', // título predeterminado
      htmlAttrs: {
        lang: 'en',
      },
      link: [
        { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
      ]
    }
  }
})

También puedes proporcionar opcionalmente las claves enumeradas en Tipos a continuación.

Etiquetas predeterminadas

Nuxt proporciona las siguientes etiquetas por defecto, asegurando que tu sitio web funcione sin problemas desde el principio.

  • viewport: width=device-width, initial-scale=1
  • charset: utf-8

Rara vez necesitarás sobrescribir estos valores predeterminados, pero es posible actualizarlos usando atajos con clave.

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      // actualizar los valores predeterminados de Nuxt
      charset: 'utf-16',
      viewport: 'width=device-width, initial-scale=1, maximum-scale=1',
    }
  }
})

useHead

La función composable useHead admite entradas reactivas y permite gestionar programáticamente las etiquetas de encabezado.

app.vue
useHead({
  title: 'My App',
  meta: [
    { name: 'description', content: 'My amazing site.' }
  ],
  bodyAttrs: {
    class: 'test'
  },
  script: [ { innerHTML: 'console.log(\'Hello world\')' } ]
})

Recomendamos revisar los composables useHead y useHeadSafe.

useSeoMeta

El composable useSeoMeta permite definir las metaetiquetas SEO del sitio como un objeto con seguridad de tipos completa.

Esto ayuda a evitar errores tipográficos y errores comunes, como usar name en lugar de property.

app.vue
useSeoMeta({
  title: 'My Amazing Site',
  ogTitle: 'My Amazing Site',
  description: 'This is my amazing site, let me tell you all about it.',
  ogDescription: 'This is my amazing site, let me tell you all about it.',
  ogImage: 'https://example.com/image.png',
  twitterCard: 'summary_large_image',
})
Ver también api > composables > use-seo-meta

Componentes

Aunque se recomienda el uso de useHead en todos los casos, puede ser preferible definir etiquetas de encabezado utilizando componentes dentro de una plantilla.

Para este propósito, Nuxt proporciona los siguientes componentes: <Title>, <Base>, <NoScript>, <Style>, <Meta>, <Link>, <Body>, <Html> y <Head>. Presta atención a la capitalización de estos componentes, lo que asegura que no se utilicen etiquetas HTML nativas no válidas.

<Head> y <Body> pueden aceptar metadatos anidados (por estética), pero esto no afecta dónde se renderizan los metadatos anidados en el HTML final.

app.vue
<script setup lang="ts">
const title = ref('Hello World')
</script>

<template>
  <div>
    <Head>
      <Title>{{ title }}</Title>
      <Meta name="description" :content="title" />
      <Style>
      body { background-color: green; }
      </Style>
    </Head>

    <h1>{{ title }}</h1>
  </div>
</template>

Se sugiere envolver tus componentes en un componente <Head> o <Html>. Las etiquetas se eliminarán de manera intuitiva.

Tipos

A continuación se enumeran los tipos no reactivos para useHead, app.head y componentes.

interface MetaObject {
  title?: string
  titleTemplate?: string | ((title?: string) => string)
  templateParams?: Record<string, string | Record<string, string>>
  base?: Base
  link?: Link[]
  meta?: Meta[]
  style?: Style[]
  script?: Script[]
  noscript?: Noscript[];
  htmlAttrs?: HtmlAttributes;
  bodyAttrs?: BodyAttributes;
}

Para tipos detallados, consulta @unhead/vue.

Funcionalidades

Reactividad

La reactividad es compatible con todas las propiedades. Esto se logra proporcionando valores calculados, getters u objetos reactivos.

const description = ref('My amazing site.')

useHead({
  meta: [
    { name: 'description', content: description }
  ],
})

Plantilla de título

Puedes proporcionar una plantilla dinámica para personalizar el título del sitio usando la opción titleTemplate. Por ejemplo, puedes agregar el nombre del sitio al título de cada página.

titleTemplate puede ser una cadena donde %s se reemplaza por el título, o una función.

Si deseas usar una función (para un control completo), no se puede configurar en nuxt.config. En su lugar, se recomienda configurarlo dentro del archivo app.vue para que esté disponible en todas las páginas.

useHead({
  titleTemplate: (titleChunk) => {
    return titleChunk ? `${titleChunk} - Site Title` : 'Site Title';
  }
})

Ahora, si configuras el título en otra página del sitio como My Page usando useHead, el título en la pestaña del navegador se mostrará como 'My Page - Site Title'. También puedes pasar null para establecer el valor predeterminado como 'Site Title'.

Parámetros de plantilla

Además del %s predeterminado, puedes usar templateParams para proporcionar marcadores de posición adicionales en titleTemplate. Esto permite una generación de títulos más dinámica.

useHead({
  titleTemplate: (titleChunk) => {
    return titleChunk ? `${titleChunk} %separator %siteName` : '%siteName';
  },
  templateParams: {
    siteName: 'Site Title',
    separator: '-'
  }
})

Etiquetas del cuerpo

Puedes usar la opción tagPosition: 'bodyClose' en las etiquetas aplicables para agregarlas al final de la etiqueta <body>.

Por ejemplo:

useHead({
  script: [
    {
      src: 'https://third-party-script.com',
      // las opciones válidas son: 'head' | 'bodyClose' | 'bodyOpen'
      tagPosition: 'bodyClose'
    }
  ]
})

Ejemplos

Usando definePageMeta

Dentro del directorio pages/, puedes usar definePageMeta junto con useHead para establecer metadatos basados en la ruta actual.

Por ejemplo, primero puedes establecer el título de la página actual (esto se extrae en tiempo de compilación mediante macros, por lo que no se puede establecer dinámicamente):

pages/some-page.vue
definePageMeta({
  title: 'Some Page'
})

Luego, en el archivo de diseño, puedes usar los metadatos de la ruta establecidos anteriormente:

layouts/default.vue
const route = useRoute()

useHead({
  meta: [{ property: 'og:title', content: `App Name - ${route.meta.title}` }]
})
Editar y previsualizar el código de ejemploexamples > features > meta-tags
Ver también guide > directory-structure > pages > #page-metadata

Título dinámico

En el siguiente ejemplo, titleTemplate se establece como una cadena que contiene el marcador de posición %s, o como una function. Esto permite establecer dinámicamente el título de la página para cada ruta en la aplicación Nuxt:

app.vue
useHead({
  // como una cadena,
  // donde `%s` se reemplaza con el título
  titleTemplate: '%s - Site Title',
})
app.vue
useHead({
  // o como una función
  titleTemplate: (productCategory) => {
    return productCategory
      ? `${productCategory} - Site Title`
      : 'Site Title'
  }
})

nuxt.config también se utiliza para establecer el título de la página. Sin embargo, nuxt.config no permite establecer dinámicamente el título de la página. Por lo tanto, se recomienda usar titleTemplate dentro del archivo app.vue para agregar títulos dinámicos y aplicarlos a todas las rutas de la aplicación Nuxt.

CSS externo

El siguiente ejemplo muestra cómo habilitar Google Fonts utilizando la propiedad link del composable useHead o el componente <Link>.

useHead({
  link: [
    {
      rel: 'preconnect',
      href: 'https://fonts.googleapis.com'
    },
    {
      rel: 'stylesheet',
      href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap',
      crossorigin: ''
    }
  ]
})