skip to Main Content

In my Next.js app I’m trying to insert og meta tags with dynamic content on a product page. So the content of the meta tags will change based on the product data fetched from server.

I am fetching product data using getServerSideProps and passing product data to page component as props.

export const getServerSideProps = wrapper.getServerSideProps(
    store => async (context) => {

        const response = await fetch(url, {
            method: 'GET',
        });
        const data = await response.json();

        return {
            props: {
                host: context.req.headers.host,
                product: data.product
            }
        }
    }
)

First Approach

I tried to insert meta tags directly on my product page component within <Head> component. Here meta tags even with static conetnt are not showing in page source.

const Product = ({product}) => {
    return (
        product ?
            <>
                <Head>
                    <title>{product.title}</title>
                    <meta name="description"
                          content={product.description}/>
                    <meta property="og:title" content={product.title}/>
                    <meta property="og:type" content="video.movie"/>
                    <meta property="og:url" content={`${props.host}/products/${product.slug}`}/>
                    <meta property="og:description" content={product.description}/>
                    <meta property="og:image" content={product.thumbnail}/>
                </Head>
                <Course/>
            </> : null
    );
};

Second Approach

return (
    <Html lang="en">
        <Head>
            {/*<meta property="og:image" content="https://static.onlinevideobooks.com/abed1e5658b3ad23c38c22646968e4f2/files/media/images/2022/04/5b0645b9-ab03-4233-b5f3-86b092d4062b/conversions/cad47d2beb9143eab3d65ea4a75b0b0e-1280x720.webp" />*/}

            {/*<title>your keyword rich title of the website and/or webpage</title>*/}
            <meta name="description"
                  content="description of your website/webpage, make sure you use keywords!"/>
            <meta property="og:title" content="short title of your website/webpage"/>
            <meta property="og:type" content="video.movie"/>
            <meta property="og:url" content="https://example.com/"/>
            <meta property="og:description" content="description of your website/webpage"/>
            <meta property="og:image"
                  content="https://example.com/image"/>
        </Head>
    </Html>
);

I tried inserting meta tags within <Head> in _document.js file. Here I am passing only static conetnt as I don’t have dynamic data in _document.js. This time meta tags are showing up in page source and I can also preview them on facebook.

Third Approach

Then I try to insert those tag in _app.js file as I receive pageProps in this component.
Unfortunately when I pass dynamic content in meta tags like first approach, they do not show up in page source but they do when I pass static conetnt similar to second approach.

full _app.js code gist

UPDATE

As regard to my third approach, I checked once again and surprisingly I can see all meta tags in page source when inserted either with static or dynamic content in _app.js. I can preview the url when content is static but when content is dynamic I can not preview the url using either Facebook debug or Open graph

My Next.js version is 12.2.0

3

Answers


  1. It’s possible that the code you have in your _app.js is blocking the meta tags from being rendered. The "View page source" in browsers will not wait for client code to finish rendering. You can verify this and click "View page source" from your browser. Do you see any of the HTML you are expecting, for example do you see your meta tags and product html?

    I expect that you probably don’t see anything except some static HTML tags. One thing you could try is moving your use of hooks and rendering logic down into its own MainLayout component.

    You can then try your first approach where you do something like this:

    const Product = ({product}) => {
        return (
            product ?
                <>
                    <Head>
                        <title>{product.title}</title>
                        <meta name="description"
                              content={product.description}/>
                        <meta property="og:title" content={product.title}/>
                        <meta property="og:type" content="video.movie"/>
                        <meta property="og:url" content={`${props.host}/products/${product.slug}`}/>
                        <meta property="og:description" content={product.description}/>
                        <meta property="og:image" content={product.thumbnail}/>
                    </Head>
                    <MainLayout>
                        <Course/>
                    <MainLayout>
                </> : null
        );
    };
    
    

    Where MainLayout contains all the logic you have in your _app.js. This should keep your actual _app.js free of any client side code that is blocking the meta tags from rendering.

    Basically we want to utitlize Next.js static optimization and have it pre-render the meta tags for your page so that the browser and web crawlers get the data without having to wait for any client side rendering.

    Login or Signup to reply.
  2. Hopefully this helps someone, but my issue was the placement of the <Head> tags within _app.js. For some reason, when it was nested under <Auth0ProviderWithHistory> the meta tags would not render, moving it outside of this gave me victory.

    Broken

    <Auth0ProviderWithHistory>    
    <Head>
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
                
                {openGraphData.map((og) => (
                    <meta {...og} />                
                ))}
    
                <title>{pageProps.title}</title>
    
            </Head>    
            <CssBaseline>            
                    <div className="page-layout">                                         
                        <NavBar />     
                        <Component {...pageProps} />
                        <Footer />                
                    </div>
            </CssBaseline>
        </Auth0ProviderWithHistory>   
    

    Fixed

    <span>
            <Head>
                <meta http-equiv="X-UA-Compatible" content="IE=edge" />
                <meta name="viewport" content="width=device-width, initial-scale=1" />
                
                {openGraphData.map((og) => (
                    <meta {...og} />                
                ))}
    
                <title>{pageProps.title}</title>
    
    
            </Head>
        <Auth0ProviderWithHistory>        
            <CssBaseline>            
                    <div className="page-layout">                                         
                        <NavBar />     
                        <Component {...pageProps} />
                        <Footer />                
                    </div>
            </CssBaseline>
        </Auth0ProviderWithHistory>
        </span>
    
    Login or Signup to reply.
  3. Not sure what’s going under the hood, but removing the Head tag resolves this for me.

    I just put my meta tags without nesting them inside Head, and it worked.

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