nfl / react-helmet

A document head manager for React
MIT License
17.36k stars 661 forks source link

Can't add Google Analytics script tags #334

Open vfonic opened 6 years ago

vfonic commented 6 years ago

First of all, thanks for awesome library! :)

I tried to add this snippet from Google Analytics page (it looks a bit different than the "usual", seems like they changed the snippet again) to my main App.jsx component:

<script async src={`https://www.googletagmanager.com/gtag/js?id=${Meteor.settings.public.ga.account}`}></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', Meteor.settings.public.ga.account);
</script>

But I can't add the second script tag and make it work. I think it's the easiest if you try adding it yourself as there are different errors depending whether you leave or remove the semicolon after dataLayer.push(arguments);

Is this supported? Am I doing something wrong?

JacobDFrank commented 6 years ago

Have the same issue here, at the end of this line.

})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');

The semicolon seems to provoke a compilation error.

chenxsan commented 6 years ago

Looks like react-helmet doesn't support either React.Fragment or React Components inside <Helmet></Helmet> tag.

So I can't do it with:

<Helmet>
{site.google_analytics ? <Fragment>{ /* two scrip tags from google analytics */}</Fragment> : null}
</Helmet>

Here's how I made it at last:

{site.google_analytics ? (
            <script
              async
              src={`https://www.googletagmanager.com/gtag/js?id=${
                site.google_analytics
              }`}
            />
          ) : null}
          {site.google_analytics ? (
            <script>
              {`window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());

        gtag('config', '${site.google_analytics}');
      `}
            </script>
          ) : null}
siakaramalegos commented 6 years ago

From what I can tell from the readme, I think the children of the script tag need to be inside an expression that is a text string, like this:

<Helmet>
      {/* other stuff... */}

      {/* Global site tag (gtag.js) - Google Analytics  */}
      <script async src=`https://www.googletagmanager.com/gtag/js?id=${googleAnalyticsId}`></script>
      <script>
        {`
          window.dataLayer = window.dataLayer || [];
          function gtag(){dataLayer.push(arguments);}
          gtag('js', new Date());
          gtag('config', ${googleAnalyticsId});
        `}
      </script>
</Helmet>

I've done this but haven't deployed to see if it's working yet.

EDIT: Looks like GA successfully got the page hit using this.

vprokashev commented 6 years ago

You can use this solution: <script type='text/javascript' dangerouslySetInnerHTML={{__html: '(function(){ ... }())'}} />

https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml

snazbala commented 5 years ago

Thanks, this was super helpful!

For future folks, if you're using Google Analytics instead of Tag Manager, here's the snippet you'll need:


<script async src="https://www.google-analytics.com/analytics.js" />
  <script>
    {`
      window.ga=window.ga||function()
      {(ga.q = ga.q || []).push(arguments)}
      ;ga.l=+new Date; ga('create',
      ${googleAnalyticsId}, 'auto'); ga('send',
      'pageview');
    `}
  </script>
Volodymyrkohut commented 5 years ago

npm install react-ga --save

import ReactGA from 'react-ga'; ReactGA.initialize('UA-133011720-1');

and then do something like this

`componentWillReceiveProps(nextProps) {

    if (this.props.location.pathname !== nextProps.location.pathname) {
        ReactGA.pageview(nextProps.location.pathname)
    }

}`

cloverich commented 5 years ago

@Volodymyrkohut you likely want to use componentDidUpdate as componentWillReceiveProps is deprecated

Example usage with react-router for page view tracking:

    componentDidUpdate(prevProps) {
      const currentPage =
        prevProps.location.pathname + prevProps.location.search;
      const nextPage =
        this.props.location.pathname + this.props.location.search;

      if (currentPage !== nextPage) {
        trackPage(nextPage);
      }
    }
williamli commented 4 years ago

From what I can tell from the readme, I think the children of the script tag need to be inside an expression that is a text string, like this:

<Helmet>
      {/* other stuff... */}

      {/* Global site tag (gtag.js) - Google Analytics  */}
      <script async src=`https://www.googletagmanager.com/gtag/js?id=${googleAnalyticsId}`></script>
      <script>
        {`
          window.dataLayer = window.dataLayer || [];
          function gtag(){dataLayer.push(arguments);}
          gtag('js', new Date());
          gtag('config', ${googleAnalyticsId});
        `}
      </script>
</Helmet>

I've done this but haven't deployed to see if it's working yet.

EDIT: Looks like GA successfully got the page hit using this.

minor syntax update is required to get it to work:

<Helmet>
      {/* other stuff... */}

      {/* Global site tag (gtag.js) - Google Analytics  */}
      <script async src={`https://www.googletagmanager.com/gtag/js?id=${googleAnalyticsId}`}></script>
      <script>
        {`
          window.dataLayer = window.dataLayer || [];
          function gtag(){dataLayer.push(arguments);}
          gtag('js', new Date());
          gtag('config', "${googleAnalyticsId}");
        `}
      </script>
</Helmet>
corneliugaina commented 4 years ago

This solution is endorsed but does it works for anyone in 2020 ? It returns me error : either that Helmet cannot have child, or that scripts don't run.

(react-ga triggered by the onChangeClientState prop worked for me like a charm)

WillSquire commented 1 year ago

It doesn’t work for me and doesn’t add to <head>. It appends it to the bottom. Putting the same logic in CRA’s index.html works. Test it with Google Analytics’ DebugView to check.