2
votes

I have my index.html page in react project as following:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>Bucard | Digital Business Card</title>

  <meta name="title" content="Bucard | Digital Business Card">
  <meta name="description" content="Bucard - Description for bucard" />
  <meta property="og:title" content="Bucard | Digital Business Card" />
  <meta property="og:image" content="http://m.digital-card.co.il/zedka/152/images/icon.png" />
  <meta property="og:description" content="Bucard - Description for bucard" />
  <meta property="og:url" content="https://bucard.co.il/" />
</head>

<body>
  <div id="root"></div>
</body>

</html>

And have my react-helmet section, which exist in component with a path of it self on the url:

<Helmet>
   <title>{"Digital card of " + this.state.card.Name}</title>

   <meta name="title" content={"Digital card of " + this.state.card.Name} />
   <meta name="description" content="Description for the react-helmet section" />
   <meta property="og:title" content={"Digital card of " + this.state.card.Name} />
   <meta property="og:image" content="http://m.digital-card.co.il/friedman/249/images/icon.png" />
   <meta property="og:description" content="Description for the react-helmet section" />
   <meta property="og:url" content={"https://bucard.co.il/digitalCard/" + this.state.card.ShortID} />
</Helmet>

Now, the propblem here is that the only tag that replaces here is the <title> tag, but none of the <meta> tags are replaced.

I don't have server side rendering, I do have server side (node.js) and function that returns json of some values, that I render in my react application.

I search for almost 2 weeks but couldn't solve this yet, and this is very important to my project. Tried also put data-react-helmet=true in different situations, still not working though.

Can anyone please help me figure this out? Thanks a lot :)

2
you cannot add open graph meta data using react-helmet read more here: github.com/nfl/react-helmet/issues/489rand0m
@rand0m and what about the <meta name="description" content="Description for the react-helmet section" /> tag? Why isn't it updates?Naor Anhaisy
It should work, I don't see any reason why it shouldn't. Here's a quick mock up: stackblitz.com/edit/react-helmet-test check the markup in dev tools, not page sourcerand0m
@rand0m Hi, currently it worked and the meta tag did update, but still the image is not working when I share on social such as Whatsapp. look for example here: bucard.co.il/digitalCard/אטליז_שינו_ובניו_-_מרכז_הבשר_החלק-VRNNaor Anhaisy
Congratulations! you can use developers.facebook.com/tools/debug or debug.iframely.com or opengraph.xyz to check the validity of your code. It seems that the ogimage is being pulled from favicon. I think you make necessary adjustments there to suit your needs.rand0m

2 Answers

1
votes

For an SPA without SSR (server side rendering), from a bot's point of view, your head tags are in your static index.html file in your dist/public folder. To add the ability to serve dynamic elements from head tag to bots you can:

  • Use a pre-render service
  • Alternatively use next.js to render your pages (or parts of the page) on the server so bots can crawl this
  • Look into other solutions for SSR

You may read - https://github.com/nfl/react-helmet/issues/489

An approach that worked for me:

  1. Direct your traffic to a node server

  2. From this node server return your index.html file and also pass head tags.

    return res.render('index', {
      headTags: ReactDOMServer.renderToStaticMarkup(tags),
    })
    

Here, tags is an array of HTML elements like <meta/>, <title/> etc.

Bonus: You can import the same tags module on frontend to get the head tags for Helmet.

  1. In your index.html you can use handlebars to read the head tags that are passed from node server and print the head tags in head section.

    <head>
    
      {{{
        headTags
      }}}
      ...
    </head>
    

and to use handlebar as an engine, add this to your node sever

app.engine('html', handlebars.engine);

0
votes

I faced the same issue. And solved it as below.

In your server file (say server/index.js), add const helmet = Helmet.renderStatic() after ReactDOMServer.renderToString. My code looks like:

const app = ReactDOMServer.renderToString(<App />);

const helmet = Helmet.renderStatic()
const indexFile = path.resolve('./build/index.html');
  fs.readFile(indexFile, 'utf8', (err, data) => {
     let updated = data.replace('<div id="root"></div>', `<div id="root">${app}</div>`);
     return res.send(updateHtmlContent(updated, helmet));
  }

and add the following function. This is to update html content with helmet tags.

function updateHtmlContent(app, helmet) {
      return `
        <!DOCTYPE html>
        <html lang="en">
          <head>
            ${helmet.title.toString()}
            ${helmet.meta.toString()}
          </head>
          <body>
            <div id="root">
              ${app}
            </div>
          </body>
        </html>
      `
    }

This may help you :)