React-helmet: any possible way to disable 'data-react-helmet="true"' from server side rendering?

Created on 2 Dec 2015  ·  51Comments  ·  Source: nfl/react-helmet

i don't mind if its in the client but i don't like these extra chars in my markup.

any suggestions?
thanks

bug

Most helpful comment

data-react-helmet is annoying

All 51 comments

We currently use that markup to distinguish Helmet's tags from existing tags in the app, in case a user wants tags managed outside of Helmet. The current implementation clears all the tags managed by Helmet and re-adds them. If we eliminated this from the server, we couldn't distinguish on the front end.

We will be moving to an implementation that will track individual tags on the front end and only update the changed ones. But for that we still need the client to establish a set of known Helmet-managed tags.

We could potentially re-visit why we have separate Helmet-managed tags and consider having Helmet manage everything...or perhaps an opt-in for full management vs. partial management. Hmmm....thoughts?

@cwelch5 Having such an option would be cool

Still nothing?

Realy need to disable data-attributes from meta tags on server side. I have asked support of Yandex and they say data attributes not allowed in meta tags

@dergachevm As a workaround, you can replace it with empty string. Something like:

const Head = Helmet.rewind()
const regexp = / data-react-helmet="true"/g
const attr = Head.htmlAttributes.toString()
const title = Head.title.toString().replace(regexp, '')
const link = Head.link.toString().replace(regexp, '')
const style = Head.style.toString().replace(regexp, '')
const meta = Head.meta.toString().replace(regexp, '')
const script = Head.script.toString().replace(regexp, '')

@svagi Thank you

Anyways I can do this in the client? I have a React client side rendered page and trying to use meta tags for Twitter Card.

Only remove the data attribute from element sets that aren't already in the <head>:

<head>
${head.meta.toString().replace(regExp, '')}
${head.title.toString().replace(regExp, '')}
${head.script.toString().replace(regExp, '')}
${head.link.toString()}
${cssBundle ? `<link rel="stylesheet" type="text/css" href="${cssBundle}" />` : ''}
</head>

Otherwise, the <link> tag will get wiped out.

@cwelch5 Can you make HELMET_ATTRIBUTE configurable?

In the mean time, a dirty workaround is:

require('react-helmet/lib/HelmetConstants.js').HELMET_ATTRIBUTE='data-react';

Personally, I don't feel comfortable exposing the fact that the server-side code is using a particular framework. Exposing in markup that react-helmet is being used to generate headers creates a possible attack vector.

I am wondering if anybody has evidence that the data-react-helmet attribute is a detriment to SEO?

We are using react-helmet for SEO. We use it to insert content into the <title> tag, and manage other tags such as <link rel="canonical" href="...">, etc.

Our SEO consultant suspect that the attribute data-react-helmet may affect SEO negatively.

Since we are implementing an isomorphic application, removing the data-react-helmet attribute server-side (e.g. ${head.title.toString().replace(regExp, '')}) is not an option, because this will cause the element to be duplicated when the page is re-rendered client-side.

So I am considering working on a fork (or pull-request) which does not use the attribute data-react-helmet. But this will be a lot of work. And clearly according to W3C data-* attributes are allowed and should not cause any issue. So do the Google bots correctly ignore the data-* attributes when analysing the HTML?

I've run into another issue with this data attribute — it breaks Google AMP's [albeit strict] validation for their boilerplate tags.

Please. 🙏

+1 This is affecting Google's AMP pages

It also affect Facebook debugger
https://developers.facebook.com/tools/debug/

In order to deal with this annoying behaviour, you can do this hack, which removes the data-react-helmet attribute between Helmet calls.

    <!-- The mount point for the header.js component; this can be whatever you want. -->
    <div id="header"></div>

    <!-- The mount point for the footer.js component; this can be whatever you want. -->
    <div id="footer"></div>

    <script>
        (function() {
          this.removeAttribute = function(tagName, attribute) {
            var tags = document.getElementsByTagName(tagName)
            // Convert our nodelist to an array, so we can iterate using forEach
            tags = Array.prototype.slice.call(tags);
            tags.forEach(function (tag) {
              tag.removeAttribute(attribute)
            })
          }

          this.renderComponent = function(component, mountPoint, props) {
            // We need to remove the data-react-helmet attribute from any <style>s added
            // previously by react-helmet, otherwise on the next invocation (i.e. inside a component)
            // it will remove these styles from the DOM.
            // https://github.com/nfl/react-helmet/issues/79
            this.removeAttribute('style', 'data-react-helmet')

            ReactDOM.render(
              React.createElement(component, props || {}, null),
              document.getElementById(mountPoint)
            )
          }

          // Render the header
          this.renderComponent(StuffIsomorphicComponent__header, 'header')

          // this.renderComponent(StuffIsomorphicComponent__headline, 'headline', {title: 'What is this?'})

          // Render the footer
          this.renderComponent(StuffIsomorphicComponent__footer, 'footer')
        }())
    </script>

It affects the Facebook open graph...

Same problem here for _Twitter_ Cards

any updates on this one?

I have forked react-helmet and removed the data-react-helmet attribute usage, it's published as react-cap.

There is one caveat, if you include _any_ metadata in your render using alternative methods (not react-helmet syntax), you must assign the HTML element the attribute data-ignore-metadata. There's more information on the readme page.

Obviously it would be preferable if react-helmet included an option to disable use of the attribute, but given this issue is over 2 years old that seems unlikely. As a side note, the fork was originally created to enable support of the react 16 server-side streaming interface.

Any updates on this?

Any news on this?

data-react-helmet is annoying

Our project is using Helmet too and we use server side rendering. When checking the SEO with https://seositecheckup.com/ we get missing tags (especially the description meta tag) although it is there. We suspect that thedata-react-helmettags might cause this problem.
Note, we don't have problems with the Facebook og:+* tags...
So it might not be a real problem, just that the mentioned site gives us a bad note...

How to add meta tag of twitter card in react-helmet to render dynamic data

+1

+1

As this issue is pretty old, there are lots of people subscribed to it through email. We would appreciate if instead of adding +1 comments you used the reactions feature.

+1.

Using this as workaround and feel bad about it.

````js
/**

  • Regular expression used in removeAdditionalHelmetAttributes.
  • @type {RegExp}
    */
    const ATTRIBUTE_REGEXP = / data-react-helmet="true"/g;

/**

  • Removes "data-react-helmet" attributes from generated HTML, as it
  • cannot be currently disabled.
  • @method removeAdditionalHelmetProps
  • @see https://github.com/nfl/react-helmet/issues/79
  • @param {Object} helmet
  • @return {Object}
  • @private
    */
    const removeAdditionalHelmetAttributes = (helmet) => {
    return Object.keys(helmet).reduce((previous, acc) => {
    const handler = helmet[acc];
    const _toString = handler.toString;
    const toString = () => _toString.call(handler).replace(ATTRIBUTE_REGEXP, '');
return {
  ...previous,
  [acc]: { ...handler, toString },
};

}, {});
};

// In your middleware:

/**

  • Collect properties for Helmet after rendering.
  • @type {Object}
    */
    const helmet = removeAdditionalHelmetAttributes(Helmet.rewind());
    ````

react-head might be an interesting alternative, haven't tried it myself, yet, but it uses React Portals and says it's SSR ready. Medium article

Still didn't had the time to test it yet, example app won't install, and the code mentions data-rh attribute, so…

+1

Is there any alternative to this issue yet?

Apart from hacky workarounds.

This project hasn't received any updates for more than 7 months now. I think it's safe to say that if you want a library that doesn't have this bug, it would be better to search for an alternative (especially considering they would use newer React features such as portals) instead of waiting for the react-helmet team to fix this.

@CanRau suggested an alternative above

@hugmanrique @AndyPresto only thing is react-head is still missing some, for me, important features like manipulating <html /> attributes e.g. setting <html lang="en"> and wont let you change <body/> attributes either, I didn't had the time to come up with a PR so far
If you need it you would have to use plain js to update them at the moment, which might not be a big deal..just a note ;-)

Removing the enhancement tag and escalating to a bug. We are in the process of discussing the roadmap for the next update major update and will be addressing some of these bugs.

Removing the enhancement tag and escalating to a bug. We are in the process of discussing the roadmap for the next update major update and will be addressing some of these bugs.

Any ETA?

@zolero sorry I do not have an ETA. I wish we had a dedicated team for OOS but the maintainers are volunteers from the engineering department.

Please bear with me while I get caught up with the project.

@zolero sorry I do not have an ETA. I wish we had a dedicated team for OOS but the maintainers are volunteers from the engineering department.

Please bear with me while I get caught up with the project.

Any update on this?

Same here.
Can't use react-helmet because of this and have no time waiting for an update...

I had to do this trick in order to remove helmet attribute from title tag

let TitleComponent = helmet.title.toComponent();
let title = TitleComponent[0] && TitleComponent[0].props ? (TitleComponent[0].props.children || '') : '';
return (
    <head>
        {title ? <title>{title}</title> : ''}
        {helmet.meta.toComponent()}
        {helmet.link.toComponent()}
    </head>
);

Regarding the Facebook sharing specifically: I noticed that, while the Facebook Sharing Debugger complains that the og:title/og:etc tags are missing, _it still parses them just fine_, both in the debugger and when sharing on facebook.com. It seems to be just the warnings section that's apparently looking for the exact string <meta property="..., rather than flexibly looking for a meta tag with the desired property.

I wrote about it in an existing bug report here: https://developers.facebook.com/support/bugs/494075494676805/?comment_id=504627553621599

Note that, if you move data-react-helmet to the _end_ of the meta tag, Facebook no longer complains. So perhaps a fix for this would be to simply move the data-react-helmet attribute to the end?

Also, to all of you who are recommending ways to remove the React Helmet attributes or replace it with an empty string: you may be at risk for having duplicated tags or tags with incorrect values. As @cwelch5 mentioned at the beginning, React Helmet uses those attributes to determine which elements it controls. If you remove them, _chaos could ensue_ 🤯

If data-react-helmet="true" breaks Twitter summary cards or open graph rich previews on WhatsApp or LinkedIn, please double-check if you're response has Content-Type: text/html.

Setting Content-Type: text/html in the response headers fixed Twitter summary cards and WhatsApp open graph tag previews for me.

Please say something 😞

all these "problems" are not due to react-helmet....

One of my personal favorites is as @gajus said

Personally, I don't feel comfortable exposing the fact that the server-side code is using a particular framework. Exposing in markup that react-helmet is being used to generate headers creates a possible attack vector.
>
Wrong in so many cases, usage of react-helmet is negligible. Serve it as cold html ... is that html a vector?... anyway even then you can remove it from the generated static html files. (your app js as react is still recognizable as react.. still can see anything you use... usage of react-helmet is negligible);

If you don't like the attribute, the fear of the dark;
When you are SSR you have control of the output. If not look to the library used. Else remove the scare before deploy.
When you are SG you have control of the output. If not look to the library used. Else remove the scare before deploy.

The only reason for removing the attribute is management purity. Which in most cases is negligible. If you think you may need to remove it then add a job after the build.

@AubreyHewes - it's not very constructive to tell people that there's no problem in helmet. This has been a long-standing issue and lots of people are clearly having issues with this, especially in the realm of unfurling (which is why I'm here), so please don't brush it off. Not everybody has the skills or ability to write sed or gc -replace or node scripts to go and muck around with machine generated markup. And unless you're a trained security expert, there's no telling what kind of information is useful to an attacker, no matter how benign or static the website is. Some people just want to to be able to control the generated markup, others don't want to expose what modules they used "just because"... and they should be allowed to do so.

I suggest that instead of writing arbitrary attributes to the helmet-controlled nodes, helmet should precede all helmet nodes with a special/configurable html comment:

<head>
  <!-- helmet -->
  <meta property="og:title" description="..." />
</head>

Then helmet could do something like this to get all of its controlled nodes:

const meta = Array.from(document.head.querySelectorAll('meta')).map(meta => 
    meta.previousSibling.nodeType === 8 && meta.previousSibling.textContent.trim() === 'helmet'
)

Not so hacky solution, but with caveats

For those who want to try out a post build script, you can do the following. Please note that this will fix the server-generated markup, but the mounted SPA will result in duplicate tags because helmet cannot differentiate between tags it created and tags it did not. This will not break your app, but it might confuse bots which execute javascript.

  1. Install this package: npm i replace-in-file
  2. Update your package.json to have a postbuild script:
    ```json
    "scripts": {
    "build": "gatsby build",
    "postbuild": "node scripts/postbuild.js",
    ...
    }
    ````
  3. Create a file at [root]/scripts/postbuild.js with the following content:

    const replace = require('replace-in-file')
    
    const replaceOptions = {
      files: ['public/**/*.html'],
      from: / data-react-helmet="true"/g,
      to: '',
    }
    
    async function replaceHelmetAttrs() {
      const results = await replace(replaceOptions)
      const count = results.reduce((cnt, res) => cnt + (res.hasChanged ? 1 : 0), 0)
      console.log(`replaceHelmetAttrs: ${count} files changed`)
    }
    
    const start = Date.now()
    replaceHelmetAttrs()
      .then(() => console.log(`postbuild done in ${Date.now() - start}ms`))
      .catch((err) => console.error(err))
    
  4. Run your build: npm run build

@DesignByOnyx your solution is exactly what I said

even then you can remove it from the generated static html files

I was not brushing anything off.

Your idea of a prepended comment does not work in react-helmet; and just exposes the exact same information (the original issue).

But still, when a developer uses this library they should know what they are doing, i.e. accept this issue /or resolve it themselves.

The solution for static generated sites is to remove the attribute (as I stated and your solution). Non static sites are crappy seo anyway. If you are not static but public.. then you need to rethink your application decisions.

This is only a problem if you think it is a problem or do not like the attribute. I have yet to generate a static site that does not work properly with opengraph compatible consumers (fb/twitter/etc -- unfurling).

I'm not doing SSR and I am trying to load a 3rd party script and it's complaining about the attribute data-react-helmet and throwing an error as part of a validation process. Now I fully understand that the 3rd party script should just ignore it but that is out of my control.

@AubreyHewes what is the problem with just adding a prop to get rid of this attr?

@scragg0x As you stated "Now I fully understand that the 3rd party script should just ignore it"...

Your best chance is to reach out to the 3rd party that they should ignore things that have nothing to do with them. Or use a 3rd party lib that does not test things that are not their responsibility... (which lib?)

To remove the prop requires ... well look at the codebase.

@AubreyHewes The library is from a CC payment gateway service, not an open source project on github so it's unlikely to change in a timely manner. I am resorting to a vanilla JS approach to loading the script. I use react-helment for other script includes, so it would of been nice to use it as well.

Same situation here, for example Google site verification also fails because of this, so I rely on hardcoding it in the index.html instead. I had issues with other platforms too, like Facebook, especially when it's about verification. It would be really nice to have an option (a prop?) to disable it.

@scragg0x @qdm12

The current solution is to add a post build script that scrubs the attribute as previously proposed. Though this depends on if the app/site in question is static SPA vs dynamic SPA.

you can remove it from the generated static html files

For a possible postbuild script see https://github.com/nfl/react-helmet/issues/79#issuecomment-712500440

@scragg0x So you are deploying as a dynamic SPA? If so there is not really a solution... the dynamically generated html will always have the attribute.

To reiterate this is not actually really a problem with the library but the usage/expectation within other frameworks.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tiagonapoli picture tiagonapoli  ·  3Comments

MiguelMachado-dev picture MiguelMachado-dev  ·  4Comments

lyquocnam picture lyquocnam  ·  3Comments

michaelBenin picture michaelBenin  ·  3Comments

lxe picture lxe  ·  5Comments