A synchronous <script> tag in <head> without async or defer halts the HTML parser entirely until the script downloads, parses, and executes — this is the most severe form of render-blocking resource under ISO-25010 time-behaviour measurement. Google Tag Manager, Hotjar, and Meta Pixel are frequently copied from vendor docs as bare <script src> tags, each adding its full download time as a sequential blocking delay before any page content renders. Two synchronous third-party scripts on a 4G connection can add 400–600ms of blocked parser time, pushing FCP and LCP into 'needs improvement' territory and penalising the page in Google's Page Experience scoring.
High because a single synchronous script in `<head>` blocks HTML parsing for the duration of its download, adding its full latency directly to FCP and LCP regardless of the script's functional purpose.
Replace bare <script> tags with Next.js Script component, specifying the correct strategy for each use case — afterInteractive for analytics and pixels, lazyOnload for non-critical widgets.
import Script from 'next/script'
// Google Tag Manager — fires after hydration
<Script
src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXXX"
strategy="afterInteractive"
/>
// Hotjar — can wait until idle
<Script
src="https://static.hotjar.com/c/hotjar-XXXXXX.js"
strategy="lazyOnload"
/>
beforeInteractive is only appropriate for scripts that genuinely need to run before hydration — A/B testing tools sometimes require it for flicker prevention, but verify with the tool's documentation before using it. The default should always be afterInteractive.
ID: marketing-page-speed.resource-optimization.render-blocking-resources
Severity: high
What to look for: Check the <head> section (root layout, HTML template, _document.tsx) for <script> tags without async or defer. Any script in <head> without these attributes blocks HTML parsing and rendering. This is the most common mistake with third-party marketing tools: analytics tags, A/B testing scripts, and ad pixels are often pasted directly from vendor documentation which includes synchronous <script> tags. Count every CSS and JavaScript resource in the that blocks rendering. Enumerate each with its URL and size.
Pass criteria: No <script> tags in <head> (or before the closing </body>) lack async or defer. Next.js Script component is used with appropriate strategy (beforeInteractive only when genuinely required, afterInteractive or lazyOnload everywhere else). At least 1 implementation must be confirmed.
Fail criteria: One or more <script> tags in <head> are synchronous (no async, no defer). beforeInteractive strategy used for scripts that do not genuinely require it. Do NOT pass if more than 2 render-blocking CSS files are loaded in the without media queries or critical CSS extraction.
Skip (N/A) when: No <head> scripts present (no third-party scripts).
Cross-reference: The script-loading-strategy check verifies that JavaScript does not block the critical rendering path alongside CSS.
Detail on fail: "2 synchronous <script> tags in root layout <head>: Google Tag Manager and Hotjar snippet pasted verbatim from vendor docs. Both block HTML parsing."
Remediation: Make every marketing script asynchronous:
import Script from 'next/script'
// Google Tag Manager — afterInteractive is correct
<Script
src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXXX"
strategy="afterInteractive"
/>
// A/B testing tools (Optimizely, VWO) — may need beforeInteractive
// but verify with the tool's documentation first
<Script
src="https://cdn.optimizely.com/js/YOUR_ID.js"
strategy="beforeInteractive"
// Only use this if the tool genuinely requires it for flicker prevention
/>