next.js icon indicating copy to clipboard operation
next.js copied to clipboard

Adding elements to the next/head causes meta-tags to be replicated/duplicated

Open jaybytez opened this issue 3 years ago • 22 comments

Bug report

Describe the bug

We have a Layout component that we use the next/head to build out our meta-tags as well as include our css/scripts.

When we include our Tag Manager, it exposed an issue when the Tag Manager injects scripts onto the page, we are seeing meta-tags get duplicated in the view source. When we remove the Tag Manager, the duplicated meta-tags go away.

We realized that the Tag Manager is adding scripts to the head, and when it does this, it appears to tells next/head to

https://github.com/vercel/next.js/discussions/17020 https://github.com/vercel/next.js/issues/9794

To test this out, we checked out the head-elements example, added a custom JS file that the only thing it does within it is create some elements that it adds to the head. And when the adds happen, meta-tags get duplicated. Not all of the tags get duplicated, just the number of tags about = to the number of head adds our script does.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

https://github.com/jaybytez/head-elements

When running this application and view the Inspector (Firefox) or Elements (Chrome), you can see that meta-tags have been duplicated (charset, viewport, author). The number of tags duplicated is relative to how many add to head calls are made in the script.

Expected behavior

I would expect that adding scripts/elements to the head would not cause meta-tags to be recreated/duplicated.

Screenshots

image

System information

  • OS: [e.g. macOS, Windows]
  • Browser (if applies) [e.g. chrome, safari]
  • Version of Next.js: [e.g. 6.0.2]
  • Version of Node.js: [e.g. 10.10.0]

Additional context

It is weird that the meta-tags are duplicated based on an n-1 elements added to the head. So if I make 4 add head calls (like in this example), only 3 meta-tags are duplicated. If I do 3 head calls, then 2 are duplicated.

Also, the view source appears to not have duplicates (I just noticed), but the Inspector/Elements shows the duplicates.

jaybytez avatar Sep 14 '20 18:09 jaybytez

Can you try next@canary, the head injection/removal was refactored to work in a different way.

timneutkens avatar Sep 15 '20 10:09 timneutkens

@timneutkens, upgrading to the next@canary did resolve the duplicate meta-data issue within the head-elements project. We need to update our project for the webpack 5 pieces, but yes, this is great. It does resolve the duplicate issue.

jaybytez avatar Sep 15 '20 15:09 jaybytez

Great so this was fixed in https://github.com/vercel/next.js/pull/16758 and this issue can be closed.

timneutkens avatar Sep 15 '20 15:09 timneutkens

Duplication issue is resolved, will close.

jaybytez avatar Sep 16 '20 22:09 jaybytez

Still busted in next 10.0.3

krikork avatar Dec 27 '20 04:12 krikork

Having this issue in 10.0.7 too. I have a component with pagination that dynamically adds canonical/next/prev to the header, but by including <Head> in the component I get duplicate meta charset and meta description tags.

benwwalker avatar Mar 12 '21 16:03 benwwalker

This issue exists again in versions of 10.0.x.

jaybytez avatar Mar 17 '21 15:03 jaybytez

i am having the same issue if i use gtm script in next 10.0.9

renedaniel avatar Mar 17 '21 22:03 renedaniel

happened to me also

GalInvesting avatar Mar 18 '21 10:03 GalInvesting

I am experiencing this as well using next 10.0.9. I removed _document.js from my project entirely to eliminate any potential problems with <Head/> from next/document. I'm now only using the <Head/> component from next/head in my page components and I'm still seeing duplication.

Additionally, the behavior changes depending the order of my tags in next/head component. In this scenario, both charset and description meta tags are duplicated:

<Head>
  <meta name="description" content={description}  />
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
  <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
  <title>{title}</title>
</Head>

Re-arranged with title first, and I only see a duplicate charset tag.

<Head>
  <title>{title}</title>
  <meta name="description" content={description} />
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
  <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
</Head>

jperezlatimes avatar Mar 23 '21 22:03 jperezlatimes

To avoid the tags duplication you need to add a key property to the elements, with the same value. e.g. <meta name="description" content={description} key="description"/>

I do have an issue with meta tags, but related to not rendering with SSR when using next/head. It's always only on the client.

devdpontes avatar Mar 24 '21 16:03 devdpontes

Thankns @devdpontes. That suggestion works for the description tag in scenario 1, but it doesn't explain the re-ordering phenomenon or why I have duplicate charset tags.

jperezlatimes avatar Mar 24 '21 17:03 jperezlatimes

I've created this repro using [email protected]: https://codesandbox.io/s/laughing-payne-dt1ty?file=/pages/_app.tsx

import { AppProps } from "next/app";
import { GoogleFonts } from "next-google-fonts";
import Head from "next/head";

import "./global.css";

const scriptThatAddsElToHead =
  `var n=document.createElement('script');` +
  `var a=document.getElementsByTagName('script')[0];` +
  `a.parentNode.insertBefore(n,a);`;

export default function App({ Component, pageProps }: AppProps): JSX.Element {
  return (
    <>
      <h1>Custom App</h1>
      <Head>
        <title>Google Fonts Repro</title>
        <script dangerouslySetInnerHTML={{ __html: scriptThatAddsElToHead }} />
      </Head>
      <GoogleFonts href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" />
      <Component {...pageProps} />
    </>
  );
}

nicholaschiang avatar Mar 30 '21 17:03 nicholaschiang

@timneutkens - this issue was resolved at some point but is a problem in all versions of nextjs 10+. And for us the problem is that there is the i18n issue with trailingSlash redirecting to the default language, this is fixed in a later nextjs 10.x.x version but we can't upgrade because of this issue causing duplicate meta-tags. Is there any ETA if this will be addressed? We are trying to determine if we have to stay on an older version with a hack in our CDN to manage the trailing slash/i18n issue or determine the SEO impacts of having duplicate meta-tags.

jaybytez avatar Apr 27 '21 16:04 jaybytez

So for others having this issue, we are seeing this primarily on charset and viewport. Not sure if others are seeing different tags?

While our SEO team said this isn't a huge impact, the problem is not having a 100% confidence that this wouldn't happen to impact title or description which would significantly impact SEO if these were duplicated.

jaybytez avatar Apr 28 '21 15:04 jaybytez

Is the viewport tag exactly the same when duplicated? Because next adds a viewport tag by default, so it might be related to that, when trying to add a custom one.

devdpontes avatar Apr 29 '21 13:04 devdpontes

@devdpontes, interesting point and I will take a look at that. For us, the problem only manifests itself in an env where we use our Tag Manager. Our lower level environments shows no duplicates, but they show up when the Tag Manager is enabled, its possible because the Tag Manager utilizes doc write for sync integration, potentially this causes a conflict and makes Nextjs fire this off again.

jaybytez avatar Apr 29 '21 21:04 jaybytez

is there any solution for this?

GalInvesting avatar Jun 10 '21 11:06 GalInvesting

any updated on this issue?

stefanonava77 avatar Jun 11 '21 10:06 stefanonava77

I am able to reproduce this in 11.0.0 as well

In _document.js

<head>
 <meta property="og:title" content="foo" key="title" />
</Head>

and in a page

<head>
 <meta property="og:title" content="bar" key="title" />
</Head>

In the rendered page, both these appear

georgeck avatar Jun 22 '21 05:06 georgeck

Hi, any updates or workarounds on this? I'm able to reproduce the same issue in next 12.1.0.

cristicismas avatar Oct 26 '22 10:10 cristicismas

I don't know where i've seen this, but i've heard that if you add the same key to the <Head /> element everywhere you call it to prevent this.

Something like this :

// In _document.js
<Head key='head'>
 <meta property="og:title" content="foo" key="title" />
</Head>

// In a page
<Head  key='head'>
 <meta property="og:title" content="bar" key="title" />
</Head>

Fredkiss3 avatar Oct 26 '22 13:10 Fredkiss3