gatsbyjs/gatsby

Avoid polluting header html tags when using Gatsby Head API

Opened this issue · 0 comments

Preliminary Checks

Description

The addition of the Gatsby Head API was a great feature, but as oppose to React Helmet it pollutes the inserted scripts with attributes like data-gatsby-head="true" causing issues on search engines.

For instance on the following implementation:

export const Head = () => (
  <>
      <script type="application/ld+json">
          {JSON.stringify({"@context":"http://schema.org","@type":"Hotel"})}
      </script>
  </>
  )

I would expect a clean output on the header:

<head>
    <script type="application/ld+json">{"@context":"http://schema.org","@type":"Hotel"}</script>
</head>

Nonetheless the output is:

<head>
    <script type="application/ld+json" data-gatsby-head="true">{"@context":"http://schema.org","@type":"Hotel"}</script>
</head>

Note the data-gatsby-head="true" attribute, this messes up Google's structured data recognition, although it is recognized by structured data validators it doesn't work well on Google's search results, probably because they use some kind of regex to parse the schemas.

Reproduction Link

https://codesandbox.io/p/devbox/avoid-polluting-header-html-tags-when-using-gatsby-head-api-phdpp7?layout=%257B%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522rootPanelGroup%2522%253A%257B%2522direction%2522%253A%2522horizontal%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522id%2522%253A%2522ROOT_LAYOUT%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522clzmy232v00073b6lg9hamdo7%2522%252C%2522sizes%2522%253A%255B70%252C30%255D%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522EDITOR%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522id%2522%253A%2522clzmy232v00023b6l8dmiqwml%2522%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522SHELLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522id%2522%253A%2522clzmy232v00043b6ln4vzho6x%2522%257D%255D%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522DEVTOOLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522id%2522%253A%2522clzmy232v00063b6lllh4ozxx%2522%257D%255D%257D%255D%252C%2522sizes%2522%253A%255B50%252C50%255D%257D%252C%2522tabbedPanels%2522%253A%257B%2522clzmy232v00023b6l8dmiqwml%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clzmy232u00013b6lfadtwmo2%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522FILE%2522%252C%2522filepath%2522%253A%2522%252FREADME.md%2522%252C%2522state%2522%253A%2522IDLE%2522%252C%2522initialSelections%2522%253A%255B%257B%2522startLineNumber%2522%253A8%252C%2522startColumn%2522%253A1%252C%2522endLineNumber%2522%253A8%252C%2522endColumn%2522%253A1%257D%255D%257D%255D%252C%2522id%2522%253A%2522clzmy232v00023b6l8dmiqwml%2522%252C%2522activeTabId%2522%253A%2522clzmy232u00013b6lfadtwmo2%2522%257D%252C%2522clzmy232v00063b6lllh4ozxx%2522%253A%257B%2522id%2522%253A%2522clzmy232v00063b6lllh4ozxx%2522%252C%2522activeTabId%2522%253A%2522clzmye48c002u3b6kkdrubthg%2522%252C%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clzmy232v00053b6lauak1qgp%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522TASK_PORT%2522%252C%2522taskId%2522%253A%2522start%2522%252C%2522port%2522%253A8000%257D%252C%257B%2522type%2522%253A%2522CHANGELOG%2522%252C%2522id%2522%253A%2522clzmyaftq000g3b6kpab8int2%2522%252C%2522mode%2522%253A%2522permanent%2522%257D%252C%257B%2522type%2522%253A%2522SANDBOX_INFO%2522%252C%2522isCloud%2522%253Atrue%252C%2522id%2522%253A%2522clzmye48c002u3b6kkdrubthg%2522%252C%2522mode%2522%253A%2522permanent%2522%257D%255D%257D%252C%2522clzmy232v00043b6ln4vzho6x%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clzmy232v00033b6luyuuxlda%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522TASK_LOG%2522%252C%2522taskId%2522%253A%2522start%2522%257D%255D%252C%2522id%2522%253A%2522clzmy232v00043b6ln4vzho6x%2522%252C%2522activeTabId%2522%253A%2522clzmy232v00033b6luyuuxlda%2522%257D%257D%252C%2522showDevtools%2522%253Atrue%252C%2522showShells%2522%253Atrue%252C%2522showSidebar%2522%253Atrue%252C%2522sidebarPanelSize%2522%253A15%257D

Steps to Reproduce

  1. Go to the provided sandbox link.
  2. Take a look at the src/pages/index.js and see how the API pollutes the HEAD script adding data-gatsby-head="true" to the generated script, making it useless for Search engines, or at least for Google's structured data/enriched search results).

Expected Result

<head>
    <script type="application/ld+json">{"@context":"http://schema.org","@type":"Hotel"}</script>
</head>

(Expecting a clean output, not made up attributes like:data-gatsby-head="true")

Actual Result

<head>
    <script type="application/ld+json" data-gatsby-head="true">{"@context":"http://schema.org","@type":"Hotel"}</script>
</head>

Environment

System:
    OS: macOS 14.5
    CPU: (10) arm64 Apple M1 Max
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.15.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 8.4.1 - /opt/homebrew/bin/npm
  Browsers:
    Chrome: 127.0.6533.100
    Edge: 127.0.2651.98
    Firefox: 129.0
    Safari: 17.5
  npmPackages:
    gatsby: ^5.13.3 => 5.13.4 
    gatsby-plugin-google-tagmanager: ^5.13.1 => 5.13.1 
    gatsby-plugin-image: ^3.13.1 => 3.13.1 
    gatsby-plugin-manifest: ^5.13.1 => 5.13.1 
    gatsby-plugin-newrelic: ^2.5.0 => 2.6.0 
    gatsby-plugin-perf-budgets: ^0.0.18 => 0.0.18 
    gatsby-plugin-s3: ^0.4.1 => 0.4.1 
    gatsby-plugin-sass: ^6.13.1 => 6.13.1 
    gatsby-plugin-sharp: ^5.13.1 => 5.13.1 
    gatsby-plugin-sitemap: ^6.13.1 => 6.13.1 
    gatsby-plugin-svgr: ^3.0.0-beta.0 => 3.0.0-beta.0 
    gatsby-plugin-use-query-params: ^1.0.1 => 1.0.1 
    gatsby-plugin-webpack-bundle-analyser-v2: ^1.1.32 => 1.1.32 
    gatsby-source-apiserver: ^2.1.8 => 2.1.8 
    gatsby-source-filesystem: ^5.13.1 => 5.13.1 
    gatsby-transformer-sharp: ^5.13.1 => 5.13.1 
  npmGlobalPackages:
    gatsby-cli: 5.8.0

Config Flags

Not relevant here