Nuxt 3: SEO/Meta data from API not visible when sharing link on social media

274 views Asked by At

I have a blog in Nuxt 3 and each blog content along with meta data is rendered through api response. The issue is when I share the blog on social media it do not show any meta data that received in API response but only show static meta data which is declared inside app.vue file. When I check meta tags through inspect elements tab in broweser dev tools, I can see all required data there.

// pages/blog/[slug].vue

<script setup>
import { onMounted, ref, defineProps } from 'vue';
import { useBlogStore } from '~/stores/blog';
import config from '~/app.config.ts'

const route = useRoute()
const blogStore = useBlogStore(); // Create an instance of the blog store
const blog = ref([]);
const { currentRoute } = useRouter();

onMounted(async () => {

  try {
    await blogStore.getBlog(route.params.slug); // Call the getBlogs action
    blog.value = blogStore.$state.blog; // Update the local ref with the fetched data
  } catch (error) {
    console.log(error);
  }

  useHead({
    title: blog.value.title,
    meta: [
      { name: 'description', content: blog.value.meta_description },
      { name: 'keywords', content: blog.value.keywords },
      { name: 'og:image', content: blog.value.image_url },
      { name: 'og:title', content: blog.value.title },
      { name: 'og:description', content: blog.value.meta_description },
      { name: 'og:type', content: 'article' },
      { name: 'og:url', content: config.web.baseURL + currentRoute.value.fullPath },
      { name: 'twitter:card', content: 'summary_large_image' },
      { name: 'twitter:url', content: config.web.baseURL + currentRoute.value.fullPath },
      { name: 'twitter:title', content: blog.value.title },
      { name: 'twitter:description', content: blog.value.meta_description },
      { name: 'twitter:image', content: blog.value.image_url },
    ],
  })
});
</script>
// app.vue

<script setup>
  definePageMeta({
    colorMode: 'dark',
  })

  useHead({
    title: 'My Title',
    meta: [
      { name: 'description', content: 'Nuxt app meta description for SEO!' },
      { name: 'theme-color', content: '#000000' },
    ],
  })
</script>
1

There are 1 answers

1
Nta On

I've been through this a couple of times, but then I figure it out. First you have to make sure was using the correct composable for fetch the api like useAsyncLazyData and useLazyFetch.

Read about those here : https://nuxt.com/docs/api/composables/use-lazy-async-data

Second you could use meta-tag which was provided by nuxt and setup by your needed

Here about nuxt's meta-tag : https://nuxt.com/docs/getting-started/seo-meta

For example :

<script setup>
// ... import section

definePageMeta({
  hidden: true,
});

const { data, pending } = await useLazyAsyncData(
  `products/${route.params.id}`,
  () =>
    $fetch(`${useRuntimeConfig()?.public.apiUrl}/products/${route.params.id}`, {
      method: "get",
    }),
  {
    transform: (payload) => payload?.result || null,
    watch: false,
  }
);

</script>
<template>
  <div>
    <n-skeleton v-if="pending" type="card" height="250px"></n-skeleton>
    <section v-else>
      <Head>
        <Title>{{ data?.title }}</Title>
        <Meta name="canonical" :content="url.origin" />
        <Meta name="description" :content="data?.description" />
        <Meta name="og:title" :content="data?.title" />
        <Meta name="og:description" :content="data?.description" />
        <Meta name="og:image" :content="data?.client?.picture" />
        <Meta name="twitter:title" :content="data?.title" />
        <Meta name="twitter:description" :content="data?.description" />
        <Meta name="twitter:image" :content="data?.client?.picture" />
        <Meta name="twitter:card" content="summary_large_image" />
      </Head>
      <ClientOnly>
        <molecules-product :data="data" :pending="pending" />
      </ClientOnly>
    </section>
    <br />
    <br />
  </div>
</template>

might it help...