question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

next/head deduping process can duplicate and overwrite dynamically inserted header tags

See original GitHub issue

What example does this report relate to?

Next/Head

What version of Next.js are you using?

^11.1.0

What version of Node.js are you using?

^15.6.1

What browser are you using?

Chrome

What operating system are you using?

Windows

How are you deploying your application?

AWS EC2

Describe the Bug

If you have integrations which dynamically add elements to the html document head, if the item added falls into the “old tags” range for the Next/Head implementation, any tags added dynamically will be duplicated because they no longer fall within the “old tags” range. Additionally, if you then have a re-render which causes the Next/Head to run again, the dynamically inserted elements from the integration will then be deleted.

The issue happens here (credit @tb-campbell) https://github.com/vercel/next.js/blob/f52211bad39c2a29a7caba40bfeb89b600524b41/packages/next/client/head-manager.ts#L73

Expected Behavior

The Next/Head component should manage the state of old and new tags internally and not count backward from an element inside the document head. Any elements that dynamically get inserted into the document head should be unaffected by the dynamic insertion by the Next/Head component, and the Next/Head component should manage the new and old Head tags without relying on the actual DOM.

To Reproduce

We are using google-tag-manager which has some 3rd party integrations which insert their scripts into the head of the document. This would also be applicable for a lot of ad frameworks and trackers as well. To recreate it without these, you could try dynamically injecting meta/link/script/etc tags into the head, until one overlaps in position with the tags set by the next head.

Below would be an example of a Head component usage for a page, where some of the fields are generated client side during runtime. If a script were to inject into the document head at any line where the tags below exist, they would first be duplicated, and on subsequent render be deleted.

<Head>
      <title key="title">{titleText}</title>
      <link key="canonical" rel="canonical" href={canonicalUrl} />
      <meta key="description" name="description" content={descriptionText} />
      <meta key="og:title" property="og:title" content={titleText} />
      <meta key="og:description" property="og:description" content={descriptionText} />
      <meta key="og:url" property="og:type" content="website" />
      <meta key="og:type" property="og:url" content={canonicalUrl} />
      <meta key="og:details" property="og:details" content={details} />
      <meta
        key="place:location:latitude"
        property="place:location:latitude"
        content={searchLocation?.position?.lat?.toString()}
      />
      <meta
        key="place:location:longitude"
        property="place:location:longitude"
        content={searchLocation?.position?.lng?.toString()}
      />
      <script
        key="breadcrumb-schema"
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: sanitize(JSON.stringify(breadcrumbs)) }}
      />
</Head>

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:10
  • Comments:13 (1 by maintainers)

github_iconTop GitHub Comments

4reactions
shehicommented, Feb 20, 2022

In my case, viewport meta tag is duplicated. I have custom _document.tsx and _app.tsx. Viewport tag alongside with all other Head tags is placed inside _app.tsx. _document.tsx only contains Head component with Google font imports.

1reaction
Puriicommented, Nov 11, 2022

Here’s a minimal example.

{
//...
 "next": "13.0.2",
 "react": "18.2.0",
 "react-dom": "18.2.0",
//...
}
import Head from "next/head";
import { useState } from "react";

const attachCss = () => {
  const charsetTag = document.head.querySelector("meta[charset]");
  const style = document.createElement("style");
  style.appendChild(document.createTextNode(".hello {color: red;}"));
  if (charsetTag) {
    document.head.insertBefore(style, charsetTag.nextSibling);
  }
};

export default function Home() {
  const [renderHead, setRenderHead] = useState(false);
  return (
    <div>
      <Head>
        <title>{renderHead ? 'Page Title B' : 'Page Title A'}</title>
      </Head>

      <p>Open the dev console and observe the DOM.</p>
      <ol>
        <li>
          <button onClick={attachCss}>Add Style-Element to head</button>
          <br />A style Element should be added to just below the charset.
        </li>
        <li>
          <button onClick={() => setRenderHead((prev) => !prev)}>
            Trigger rerender
          </button>
          <br />
          Title should be updated. The Style-Element is gone, but an additional
          charset Meta-Element popped up.
        </li>

        <li>
          <button onClick={attachCss}>Add Style-Element again</button>
          <br />A style Element should be added to just below the charset.
        </li>

        <li>
          <button onClick={() => setRenderHead((prev) => !prev)}>
            Trigger rerender
          </button>
          <br />
          Title should be updated. The Style-Element is still there.
        </li>
      </ol>

      <p>
        Interesting. The Title shouldn't be updated, since the next/head element
        is there twice.
      </p>
    </div>
  );
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

javascript - How to avoid duplicated meta tags? - Stack Overflow
To solve this constraint, you should set the default meta tags in your _app inside next/head (where they can be deduped), and overwrite...
Read more >
Avoid Duplicate Meta Description and Keywords in Next js
I'm developing my website with Next.js To upgrade my website's SEO performance, I'm trying to avoid duplicated meta tags. My Question.
Read more >
CN101410819A - Reliable, high-throughput, high-performance ...
Internet application users can use the overlay to obtain improved performance ... At next head is under the situation of TCP or UDP,...
Read more >
NextJS Dynamic Head For SEO | JavaScript Articles
We'll also briefly discuss some best practices for the meta tags and structured data applied to the site. We can also create “global...
Read more >
SANS Holiday Hack Challenge 2020 Write-up
My write-up for last year's KringleCon can be found here. ... entry 'z_MUNCHKIN=munchkin_20249649541603754' Next, head into the workshop.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found