remix-run / remix

Build Better Websites. Create modern, resilient user experiences with web fundamentals.
https://remix.run
MIT License
29.51k stars 2.49k forks source link

remix hydration error when using gtag #9231

Open pullmann4rent opened 5 months ago

pullmann4rent commented 5 months ago

Reproduction

Root

import * as gtag from "~/utils/gtag";

export default function App() {
  const { showBanner, gaTrackingId } = useLoaderData<typeof loader>();

  const location = useLocation();

  useEffect(() => {
    if (gaTrackingId?.length) {
      gtag.pageview(location.pathname, gaTrackingId);
    }
  }, [location, gaTrackingId]);

  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width,initial-scale=1" />
        <script async src={`https://www.googletagmanager.com/gtag/js?id=${gaTrackingId}`}></script>

        <script async dangerouslySetInnerHTML={{ __html: `
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());

            gtag('config', '${gaTrackingId}');
              `
          }} />

      <Suspense fallback={null}>
        <script async dangerouslySetInnerHTML={{ __html: `
        (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
        new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
        j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
        'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
        })(window,document,'script','dataLayer','xxxx');
                      `
                  }} />
        </Suspense>

        <Meta />
        <Links />
        <ExternalScripts />

      </head>
      <body>
      <>
      <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=XXXX"
height="0" width="0" style={{display: 'none',visibility:'hidden'}}></iframe></noscript>

        <Whatsapp />
        <Outlet />
        <ScrollRestoration />
        <Scripts />
        <LiveReload />
      </body>
    </html>
  );
}

export async function loader({ request }: LoaderArgs) {
  const cookieHeader = request.headers.get("Cookie");
  const cookie = await userPrefs.parse(cookieHeader);
  return json({ showBanner: cookie ?? null, gaTrackingId: 'xxx' });
}

gtag util

declare global {
  interface Window {
    gtag: (
      option: string,
      gaTrackingId: string,
      options: Record<string, unknown>,
    ) => void;
  }
}

/**
 * @example
 * https://developers.google.com/analytics/devguides/collection/gtagjs/pages
 */
export const pageview = (url: string, trackingId: string) => {
  if (!window.gtag) {
    console.warn(
      "window.gtag is not defined. This could mean your google analytics script has not loaded on the page yet.",
    );
    return;
  }
  window.gtag("config", trackingId, {
    page_path: url,
  });
};

/**
 * @example
 * https://developers.google.com/analytics/devguides/collection/gtagjs/events
 */
export const event = ({
  action,
  category,
  label,
  value,
}: Record<string, string>) => {
  if (!window.gtag) {
    console.warn(
      "window.gtag is not defined. This could mean your google analytics script has not loaded on the page yet.",
    );
    return;
  }
  window.gtag("event", action, {
    event_category: category,
    event_label: label,
    value: value,
  });
};

System Info

System:
    OS: Windows 10 10.0.19045
    CPU: (4) x64 AMD FX(tm)-4170 Quad-Core Processor
    Memory: 1.75 GB / 7.98 GB
  Binaries:
    Node: 18.18.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.21 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 10.2.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Chromium (123.0.2420.97)
    Internet Explorer: 11.0.19041.3636
  npmPackages:
    @remix-run/css-bundle: ^2.0.1 => 2.7.1
    @remix-run/dev: ^1.15.0 => 1.19.3
    @remix-run/eslint-config: ^1.15.0 => 1.19.3
    @remix-run/express: ^1.15.0 => 1.19.3
    @remix-run/node: ^1.15.0 => 1.19.3
    @remix-run/react: ^1.15.0 => 1.19.3
    @remix-run/serve: ^1.15.0 => 1.19.3
    @remix-run/vercel: ^1.15.0 => 1.19.3

Used Package Manager

npm

Expected Behavior

That I got no hydration err

Actual Behavior

Google analatiycs works but not google tag manager. I got hydration error when I use this code:

      <Suspense fallback={null}>
        <script async dangerouslySetInnerHTML={{ __html: `
        (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
        new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
        j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
        'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
        })(window,document,'script','dataLayer','xxxx');
                      `
                  }} />
        </Suspense>
suhaotian commented 5 months ago

To fix this, we recommend the using the ClientOnly component in the remix-utils community package. An example of its usage can be found in the examples repository.

emirefek commented 3 months ago

To fix this, we recommend the using the ClientOnly component

Can you please show an example actually uses GTag scripts? Because using it with ClientOnly prevents firing of that script. So It renders but does not sends any data to google. Does not works.

Or any other tracking scripts. Meta(Facebook) Events, GTag, Ms Clarity.