Next.js Discord

Discord Forum

load a script on the very top of <head>

Unanswered
Sweat bee posted this in #help-forum
Open in Discord
Sweat beeOP
is it possible to load a script with beforeInteractive on the very top of <head> with app router?

I tried the following:
- load the script in RootLayout in html -> causing hydration errors
- load the script in RootLayout in body -> works but comes very late in head
- load the script in RootLayout in <head> inside html above body -> works and it is higher in head as before but have to use <head> which may not work in future next updates anymore?!

Any ideas?

13 Replies

Sweat beeOP
I did that but I need it to load asap in head... Can we set some sort of priority, so it will load at the very top inside head?
apparently there is some flickering with AB testing when loading a custom self hosted GTM
so a difference of half a second matters
@Sweat bee I did that but I need it to load asap in head... Can we set some sort of priority, so it will load at the very top inside head?
there is no prop to set the priority. However it will load before nextjs stuff. So before the page is even visible. That means, that it should be fast enought
Sweat beeOP
So I load it directly into <html> in the RootLayout? Right? Why is this throwing hydration errors then?
@Sweat bee So I load it directly into <html> in the RootLayout? Right? Why is this throwing hydration errors then?
you can add the Script tag wherever you want to. It will be directly placed in your head
Sweat beeOP
<html lang="de" className={cn(soehne.variable, soehneCondensed.variable, iconFont.variable, htmlStyles())}>
      <Script
        id="_next-gtm-init"
        strategy="beforeInteractive"
        dangerouslySetInnerHTML={{
          __html: `
            (function(w,d,s,l){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='${src}'+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer');
          `,
        }}
      />
      <body className={layoutStyles()}>
        {children}
        <DraftModeBanner />
      </body>
    </html>
thats giving me:
Unhandled Runtime Error
Error: Hydration failed because the initial UI does not match what was rendered on the server.
See more info here: https://nextjs.org/docs/messages/react-hydration-error
when I set it to afterInteractive, no errors
even with the example from the docs I get hydration errors:
<Script src="https://example.com/script.js"   strategy="beforeInteractive"
        />
next 14.2.5 btw
in the docs they put it into body and then it works but it loads very late because its almost the last script in head and we are getting the flickering with AB testing... So only solution right now is to wrap it into <head> tag above <body>