| 1 | # Scripts |
| 2 | |
| 3 | Loading third-party scripts in Next.js. |
| 4 | |
| 5 | ## Use next/script |
| 6 | |
| 7 | Always use `next/script` instead of native `<script>` tags for better performance. |
| 8 | |
| 9 | ```tsx |
| 10 | // Bad: Native script tag |
| 11 | <script src="https://example.com/script.js |
| 12 | |
| 13 | // Good: Next.js Script component |
| 14 | import Script from "next/script |
| 15 | |
| 16 | <Script src=" |
| 17 | ``` |
| 18 | |
| 19 | ## Inline Scripts Need ID |
| 20 | |
| 21 | Inline scripts require an `id` attribute for Next.js to track them. |
| 22 | |
| 23 | ```tsx |
| 24 | // Bad: Missing id |
| 25 | <Script dangerouslySetInnerHTML= |
| 26 | |
| 27 | // Good: Has id |
| 28 | <Script id=" |
| 29 | |
| 30 | // Good: Inline with id |
| 31 | <Script id=" |
| 32 | {`document.getElementById('banner').classList.remove('hidden')`} |
| 33 | </Script> |
| 34 | ``` |
| 35 | |
| 36 | ## Don't Put Script in Head |
| 37 | |
| 38 | `next/script` should not be placed inside `next/head`. It handles its own positioning. |
| 39 | |
| 40 | ```tsx |
| 41 | // Bad: Script inside Head |
| 42 | import Head from 'next/head |
| 43 | import Script from 'next/script |
| 44 | |
| 45 | <Head> |
| 46 | <Script src= |
| 47 | </Head> |
| 48 | |
| 49 | // Good: Script outside Head |
| 50 | <Head> |
| 51 | <title>Page</title |
| 52 | </Head> |
| 53 | <Script src=" |
| 54 | ``` |
| 55 | |
| 56 | ## Loading Strategies |
| 57 | |
| 58 | ```tsx |
| 59 | // afterInteractive (default) - Load after page is interactive |
| 60 | <Script src=" |
| 61 | |
| 62 | // lazyOnload - Load during idle time |
| 63 | <Script src=" |
| 64 | |
| 65 | // beforeInteractive - Load before page is interactive (use sparingly) |
| 66 | // Only works in app/layout.tsx or pages/_document.js |
| 67 | <Script src=" |
| 68 | |
| 69 | // worker - Load in web worker (experimental) |
| 70 | <Script src=" |
| 71 | ``` |
| 72 | |
| 73 | ## Google Analytics |
| 74 | |
| 75 | Use `@next/third-parties` instead of inline GA scripts. |
| 76 | |
| 77 | ```tsx |
| 78 | // Bad: Inline GA script |
| 79 | <Script src=" |
| 80 | <Script id=" |
| 81 | {`window.dataLayer = window.dataLayer || []; |
| 82 | function gtag(){dataLayer.push(arguments);} |
| 83 | gtag('js', new Date()); |
| 84 | gtag('config', 'G-XXXXX');`} |
| 85 | </Script> |
| 86 | |
| 87 | // Good: Next.js component |
| 88 | import { GoogleAnalytics } |
| 89 | |
| 90 | export default function Layout |
| 91 | return ( |
| 92 | <html> |
| 93 | <body>{children} |
| 94 | <GoogleAnalytics gaId= |
| 95 | </html> |
| 96 | ) |
| 97 | } |
| 98 | ``` |
| 99 | |
| 100 | ## Google Tag Manager |
| 101 | |
| 102 | ```tsx |
| 103 | import { GoogleTagManager } |
| 104 | |
| 105 | export default function Layout |
| 106 | return ( |
| 107 | <html> |
| 108 | <GoogleTagManager gtmId |
| 109 | <body>{children} |
| 110 | </html> |
| 111 | ); |
| 112 | } |
| 113 | ``` |
| 114 | |
| 115 | ## Other Third-Party Scripts |
| 116 | |
| 117 | ```tsx |
| 118 | // YouTube embed |
| 119 | import { YouTubeEmbed } |
| 120 | |
| 121 | <YouTubeEmbed videoid=" |
| 122 | |
| 123 | // Google Maps |
| 124 | import { GoogleMapsEmbed } |
| 125 | |
| 126 | <GoogleMapsEmbed apiKey=" |
| 127 | ``` |
| 128 | |
| 129 | ## Quick Reference |
| 130 | |
| 131 | | Pattern | Issue | Fix | |
| 132 | | --------------------------------------------- | -------------------------- | |
| 133 | | `<script src="...">` | No optimization | Use |
| 134 | | `<Script>` without id | Can't track inline scripts | Add |
| 135 | | `<Script>` inside `<Head>` |
| 136 | | Inline GA/GTM scripts | No optimization | Use `@next/third-parties` |
| 137 | | `strategy="beforeInteractive"` outside layout | Won't work | Only use in root layout |