skip to Main Content

I’m having an issue with generating meta tags for my Next.js blogging application. I am currently using Typescript and apollo-codegen to generate query hooks to fetch information from my Strapi backend. Because i’ve read on many other posts that dynamic meta tag information won’t show in the view page source if the information is client-side rendered, I made the change to use graphql-codegen-next-ssr (https://github.com/correttojs/graphql-codegen-apollo-next-ssr). All of my queries are now pre-rendered rendered.

[slug].tsx

const BlogDetails: PageGetBlogDetailComp = (props) => {
  return props?.data ? (
    <div className=" container mx-auto mb-8 bg-light-neutral px-10 dark:bg-dark-neutral">
      <Head>
        <title>
          Apex Blogs | {props?.data?.blogs?.data[0]?.attributes?.title}
        </title>
        <meta
          property="og:title"
          content={props?.data?.blogs?.data[0].attributes?.title}
        />
        <meta property="og:description" content="Open Graph Description" />
        <meta property="og:type" content="video.movie" />
        <meta
          property="og:image"
          content={
            props?.data?.blogs?.data[0]?.attributes?.featureImage?.data
              ?.attributes?.url
          }
        />
        <meta
          property="og:url"
          content={`https://apex-blogs.vercel.app/blog/${props?.data?.blogs?.data[0]?.attributes?.slug}`}
        />
      </Head>
  //......



export const getStaticProps: GetServerSideProps = async ({ params, req }) => {
  const res = await ssrGetBlogDetail.getServerPage(
    {
      variables: { slug: params?.slug?.toString() || "" },
    },
    { req }
  );

  if (res.props.error) {
    return {
      notFound: true,
    };
  }

  return res;
};

Despite this, I am still having no luck seeing my meta tags. I can’t even view tags I’ve added in my __app.ts in the page source. The meta tags only show up in inspect element. The only way I could see the meta tags in page source is if added them in the _document.ts file, but my tags need to be dynamic.

My goal is to have shareable blog posts. Please let me know if I need to add additional infomation.

2

Answers


  1. Make sure you’re importing Head from the right place

    import Head from 'next/head';
    

    Here an example that are working

    // on your ./pages/index(or any path here).tsx
    
    import { GetServerSideProps } from "next";
    import Head from "next/head";
    
    const getSiteTitle = async () => {
      return Promise.resolve({
        siteTitle: "this is my website title",
      });
    };
    export default function Index({ siteTitle = null }: HomeProps) {
      return <Home siteTitle={siteTitle} />;
    }
    export const getServerSideProps: GetServerSideProps<HomeProps> = async () => {
      let siteTitle = null;
    
      const response = await getSiteTitle(); // any async promise here.
    
      siteTitle = response.siteTitle;
    
      if (!siteTitle) {
        return {
          notFound: true,
        };
      }
    
      return {
        props: { siteTitle }, // will be passed to the page component as props
      };
    };
    
    // Home must be a component, you can save this file on src/templates or src/scenes to keep the react pattern.
    
    export type HomeProps = {
      siteTitle: string,
    };
    export const Home = ({ siteTitle }: HomeProps) => {
      return (
        <>
          <Head>
            <title>{siteTitle}</title>
          </Head>
          <div>
            <h1>Hello World </h1>
          </div>
        </>
      );
    };
    
    Login or Signup to reply.
  2. I worked it out this way. First, You don’t need to add Head component in every page component.
    because It won’t show in the source anyway.(In my case though.)
    But If you place Head component in the _app.js component, It will appears in the source.
    Let’s take advantage of this.

    1. Place <Head> component on _app.js file like below.
      And delete all the <Head> component in other page components If you’ve placed.
    function MyApp({ Component, pageProps }: AppProps) {
      const router = useRouter()
      return (
        <Suspense>
          <Head>
               <title>{pageProps?.title}</title>
               <meta name="description"  content={pageProps?.description}/>
               <meta property="og:title" content={pageProps?.title} />
          </Head>
          <Component {...pageProps} />
        </Suspense>
      )
    }
    
    
    1. And in the page components, add getInitialProps function like below.
      This is to send the contents to be shown in the Head component to _app.js. so if you change pages, _app.js component will receive some props from that page to display in the Head component via the ‘getInitialProps’ function.
    //in Main page component..
    
    import { NextPageContext } from 'next'
    
    export default function Main(){
       return <div>…</div>
    }
    
    Main.getInitialProps = async (ctx: NextPageContext) => {
      return {
        title: ’Title you wanna show’,
        description: ’Desc you wanna show’
      }
    }
    
    
    1. now if you console.log(pageProps) in the _app.js, you will see
      all the props you passed in current page components like below.
      { title: ’Title you wanna show’, description: ’Desc you wanna show’ }

    2. Save all the codes and open source page by press option + command + u keys. then you will see all meta tags you’ve added.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search