[{"data":1,"prerenderedAt":1024},["ShallowReactive",2],{"content:\u002Fframework-performance\u002Fnextjs-performance\u002Fchoosing-next-script-loading-strategies":3,"surroundings:\u002Fframework-performance\u002Fnextjs-performance\u002Fchoosing-next-script-loading-strategies":1016},{"id":4,"title":5,"body":6,"description":995,"extension":996,"meta":997,"navigation":1009,"path":1010,"seo":1011,"stem":1014,"__hash__":1015},"content\u002Fframework-performance\u002Fnextjs-performance\u002Fchoosing-next-script-loading-strategies\u002Findex.md","Choosing next\u002Fscript Loading Strategies",{"type":7,"value":8,"toc":976},"minimark",[9,14,29,52,199,204,240,244,250,256,262,268,272,277,460,464,467,471,474,478,481,614,618,621,625,634,638,644,648,651,735,739,742,746,775,779,785,797,813,827,831,845,854,866,875,887,899,908,917,926,935,939,962,966,969,972],[10,11,13],"h1",{"id":12},"how-to-choose-nextscript-loading-strategies","How to Choose next\u002Fscript Loading Strategies",[15,16,17,18,23,24,28],"p",{},"This guide is part of ",[19,20,22],"a",{"href":21},"\u002Fframework-performance\u002Fnextjs-performance\u002F","Next.js Performance",", within ",[19,25,27],{"href":26},"\u002Fframework-performance\u002F","Framework Performance",". Third-party scripts — analytics, tag managers, consent platforms, chat widgets, A\u002FB testing, ads, social embeds — often cost more main-thread time than the application itself. In a Next.js app, they compete with hydration: if a tag manager executes 200ms of JavaScript while React hydrates, both take longer, and interactions during that window are slow.",[15,30,31,35,36,39,40,43,44,47,48,51],{},[32,33,34],"code",{},"next\u002Fscript"," controls when scripts load. ",[32,37,38],{},"beforeInteractive"," injects scripts into the initial HTML so they load before hydration. ",[32,41,42],{},"afterInteractive"," (the default) loads scripts after hydration begins on the client. ",[32,45,46],{},"lazyOnload"," waits until the browser is idle after load. ",[32,49,50],{},"worker"," (experimental) runs scripts in a web worker via Partytown. Choosing well — and loading some scripts only on interaction — protects LCP and INP without losing the scripts' function.",[15,53,54],{},[55,56,62,63,62,70,62,74,62,77,62,86,62,92,62,97,62,106,62,113,62,116,62,122,62,127,62,130,62,135,62,139,62,142,62,149,62,154,62,161,62,167,62,171,62,175,62,179,62,183,62,187,62,191,62,195,62],"svg",{"viewBox":57,"width":58,"role":59,"ariaLabel":60,"style":61},"0 0 760 254","100%","img","Timeline showing when scripts load relative to hydration and the load event for each next\u002Fscript strategy.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[64,65],"rect",{"className":66,"x":68,"y":68,"width":58,"height":58,"fill":69},[67],"svg-canvas","0","#ffffff",[71,72,73],"title",{},"When scripts run under each strategy",[75,76,60],"desc",{},[64,78],{"x":79,"y":79,"width":80,"height":81,"rx":82,"fill":83,"stroke":84,"style":85},"1","758","252","10","none","currentColor","stroke-opacity:0.18",[87,88,73],"text",{"x":89,"y":90,"fill":84,"style":91},"28.0","34.0","font-size:16px;font-weight:700",[87,93,96],{"x":89,"y":94,"fill":84,"style":95},"74.0","font-size:12.5px;font-weight:700","App",[64,98],{"x":99,"y":100,"width":101,"height":102,"rx":103,"fill":104,"stroke":104,"style":105},"258.7","56.0","144.8","26.0","3","#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[87,107,112],{"x":108,"y":109,"fill":84,"style":110,"textAnchor":111},"331.1","73.5","font-size:11.5px","middle","hydration",[87,114,38],{"x":89,"y":115,"fill":84,"style":95},"112.0",[64,117],{"x":118,"y":119,"width":120,"height":102,"rx":103,"fill":83,"stroke":84,"style":121},"200.2","94.0","71.6","stroke-opacity:0.35",[87,123,126],{"x":124,"y":125,"fill":84,"style":110,"textAnchor":111},"236.1","111.5","script",[87,128,42],{"x":89,"y":129,"fill":84,"style":95},"150.0",[64,131],{"x":132,"y":133,"width":120,"height":102,"rx":103,"fill":84,"stroke":84,"style":134},"317.2","132.0","fill-opacity:0.06;stroke-opacity:0.4",[87,136,126],{"x":137,"y":138,"fill":84,"style":110,"textAnchor":111},"353.1","149.5",[87,140,46],{"x":89,"y":141,"fill":84,"style":95},"188.0",[64,143],{"x":144,"y":145,"width":120,"height":102,"rx":103,"fill":146,"stroke":147,"style":148},"551.2","170.0","#ffc300","#b8860b","fill-opacity:0.24;stroke-opacity:0.9",[87,150,153],{"x":151,"y":152,"fill":84,"style":110,"textAnchor":111},"587.1","187.5","script (idle)",[155,156],"line",{"x1":157,"y1":158,"x2":159,"y2":158,"stroke":84,"style":160},"141.0","210.0","726.0","stroke-opacity:0.4",[87,162,166],{"x":163,"y":164,"fill":165,"style":110,"textAnchor":111},"151.7","227.0","#51617a","0ms",[87,168,170],{"x":169,"y":164,"fill":165,"style":110,"textAnchor":111},"214.1","500ms",[87,172,174],{"x":173,"y":164,"fill":165,"style":110,"textAnchor":111},"287.2","1000ms",[87,176,178],{"x":177,"y":164,"fill":165,"style":110,"textAnchor":111},"360.4","1500ms",[87,180,182],{"x":181,"y":164,"fill":165,"style":110,"textAnchor":111},"433.5","2000ms",[87,184,186],{"x":185,"y":164,"fill":165,"style":110,"textAnchor":111},"506.6","2500ms",[87,188,190],{"x":189,"y":164,"fill":165,"style":110,"textAnchor":111},"579.7","3000ms",[87,192,194],{"x":193,"y":164,"fill":165,"style":110,"textAnchor":111},"652.9","3500ms",[87,196,198],{"x":197,"y":164,"fill":165,"style":110,"textAnchor":111},"712.3","4000ms",[200,201,203],"h2",{"id":202},"rapid-diagnosis","Rapid Diagnosis",[205,206,207,222,228,234],"ul",{},[208,209,210,214,215,217,218,221],"li",{},[211,212,213],"strong",{},"List third-party scripts"," and how they are loaded (",[32,216,34],{}," strategy, raw ",[32,219,220],{},"\u003Cscript>"," tags, injected by a tag manager).",[208,223,224,227],{},[211,225,226],{},"Record a load trace"," with CPU throttling; attribute long tasks to script URLs.",[208,229,230,233],{},[211,231,232],{},"Use Long Animation Frames"," in RUM to see which scripts run during slow interactions.",[208,235,236,239],{},[211,237,238],{},"Check whether each script is needed early"," (consent banners may be; chat is not).",[200,241,243],{"id":242},"root-cause-analysis","Root Cause Analysis",[15,245,246,249],{},[211,247,248],{},"1. Everything loads early."," Scripts default to early loading or are placed in the document head.",[15,251,252,255],{},[211,253,254],{},"2. Tag managers inject more scripts."," One container loads many tags at once.",[15,257,258,261],{},[211,259,260],{},"3. Heavy widgets on every page."," Chat and social embeds load for all users.",[15,263,264,267],{},[211,265,266],{},"4. beforeInteractive overuse."," Scripts delay hydration and compete with the LCP.",[200,269,271],{"id":270},"step-by-step-resolution","Step-by-Step Resolution",[273,274,276],"h3",{"id":275},"_1-assign-a-strategy-per-script","1. Assign a strategy per script",[278,279,284],"pre",{"className":280,"code":281,"language":282,"meta":283,"style":283},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","import Script from 'next\u002Fscript';\nexport default function RootLayout({ children }) {\n  return (\u003Chtml lang=\"en\">\u003Cbody>\n    {children}\n    \u003CScript src=\"https:\u002F\u002Fwww.googletagmanager.com\u002Fgtm.js?id=GTM-XXXX\" strategy=\"afterInteractive\" \u002F>\n    \u003CScript src=\"https:\u002F\u002Fwidget.example-chat.com\u002Floader.js\" strategy=\"lazyOnload\" \u002F>\n  \u003C\u002Fbody>\u003C\u002Fhtml>);\n}\n\u002F\u002F trade-off: lazyOnload delays the chat widget until idle, so users who want to\n\u002F\u002F chat immediately wait a little; a facade button removes even that cost.\n","javascript","",[32,285,286,308,331,363,375,403,426,442,447,454],{"__ignoreMap":283},[287,288,290,294,298,301,305],"span",{"class":155,"line":289},1,[287,291,293],{"class":292},"sPARh","import",[287,295,297],{"class":296},"saISM"," Script ",[287,299,300],{"class":292},"from",[287,302,304],{"class":303},"sZ8jY"," 'next\u002Fscript'",[287,306,307],{"class":296},";\n",[287,309,311,314,317,320,324,328],{"class":155,"line":310},2,[287,312,313],{"class":292},"export",[287,315,316],{"class":292}," default",[287,318,319],{"class":292}," function",[287,321,323],{"class":322},"smZ65"," RootLayout",[287,325,327],{"class":326},"sQw3B","({ children }) ",[287,329,330],{"class":296},"{\n",[287,332,334,337,340,344,348,351,354,357,360],{"class":155,"line":333},3,[287,335,336],{"class":292},"  return",[287,338,339],{"class":296}," (\u003C",[287,341,343],{"class":342},"sZBmE","html",[287,345,347],{"class":346},"sPXB4"," lang",[287,349,350],{"class":292},"=",[287,352,353],{"class":303},"\"en\"",[287,355,356],{"class":296},">\u003C",[287,358,359],{"class":342},"body",[287,361,362],{"class":296},">\n",[287,364,366,369,372],{"class":155,"line":365},4,[287,367,368],{"class":292},"    {",[287,370,371],{"class":296},"children",[287,373,374],{"class":292},"}\n",[287,376,378,381,384,387,389,392,395,397,400],{"class":155,"line":377},5,[287,379,380],{"class":296},"    \u003C",[287,382,383],{"class":342},"Script",[287,385,386],{"class":346}," src",[287,388,350],{"class":292},[287,390,391],{"class":303},"\"https:\u002F\u002Fwww.googletagmanager.com\u002Fgtm.js?id=GTM-XXXX\"",[287,393,394],{"class":346}," strategy",[287,396,350],{"class":292},[287,398,399],{"class":303},"\"afterInteractive\"",[287,401,402],{"class":296}," \u002F>\n",[287,404,406,408,410,412,414,417,419,421,424],{"class":155,"line":405},6,[287,407,380],{"class":296},[287,409,383],{"class":342},[287,411,386],{"class":346},[287,413,350],{"class":292},[287,415,416],{"class":303},"\"https:\u002F\u002Fwidget.example-chat.com\u002Floader.js\"",[287,418,394],{"class":346},[287,420,350],{"class":292},[287,422,423],{"class":303},"\"lazyOnload\"",[287,425,402],{"class":296},[287,427,429,432,434,437,439],{"class":155,"line":428},7,[287,430,431],{"class":296},"  \u003C\u002F",[287,433,359],{"class":342},[287,435,436],{"class":296},">\u003C\u002F",[287,438,343],{"class":342},[287,440,441],{"class":296},">);\n",[287,443,445],{"class":155,"line":444},8,[287,446,374],{"class":296},[287,448,450],{"class":155,"line":449},9,[287,451,453],{"class":452},"sjfSM","\u002F\u002F trade-off: lazyOnload delays the chat widget until idle, so users who want to\n",[287,455,457],{"class":155,"line":456},10,[287,458,459],{"class":452},"\u002F\u002F chat immediately wait a little; a facade button removes even that cost.\n",[273,461,463],{"id":462},"_2-load-heavy-widgets-on-interaction","2. Load heavy widgets on interaction",[15,465,466],{},"Replace chat widgets and embeds with a lightweight facade (a button or image) that loads the real script when clicked.",[273,468,470],{"id":469},"_3-audit-the-tag-manager","3. Audit the tag manager",[15,472,473],{},"Remove unused tags, set triggers to fire after load or on interaction, and avoid tags that inject synchronous scripts.",[273,475,477],{"id":476},"_4-reserve-beforeinteractive-for-genuine-needs","4. Reserve beforeInteractive for genuine needs",[15,479,480],{},"Use it only for scripts that must run before the page is interactive (some consent or bot-detection scripts). Everything else belongs later.",[15,482,483],{},[55,484,62,487,62,490,62,493,62,495,62,498,62,500,62,503,62,509,62,513,62,517,62,520,62,524,62,528,62,532,62,536,62,538,62,543,62,545,62,548,62,550,62,554,62,556,62,558,62,560,62,563,62,566,62,570,62,572,62,575,62,577,62,580,62,583,62,587,62,589,62,592,62,594,62,597,62,600,62,604,62,606,62,609,62,611,62],{"viewBox":485,"width":58,"role":59,"ariaLabel":486,"style":61},"0 0 760 274","Recommended next\u002Fscript strategy for common third-party script types.",[64,488],{"className":489,"x":68,"y":68,"width":58,"height":58,"fill":69},[67],[71,491,492],{},"Assigning strategies to common scripts",[75,494,486],{},[64,496],{"x":79,"y":79,"width":80,"height":497,"rx":82,"fill":83,"stroke":84,"style":85},"272",[87,499,492],{"x":89,"y":90,"fill":84,"style":91},[64,501],{"x":89,"y":100,"width":158,"height":502,"rx":68,"fill":84,"stroke":84,"style":134},"30.0",[87,504,508],{"x":505,"y":506,"fill":84,"style":95,"textAnchor":507},"38.0","75.5","start","Script type",[64,510],{"x":511,"y":100,"width":512,"height":502,"rx":68,"fill":84,"stroke":84,"style":134},"238.0","247.0",[87,514,516],{"x":515,"y":506,"fill":84,"style":95,"textAnchor":111},"361.5","Strategy",[64,518],{"x":519,"y":100,"width":512,"height":502,"rx":68,"fill":84,"stroke":84,"style":134},"485.0",[87,521,523],{"x":522,"y":506,"fill":84,"style":95,"textAnchor":111},"608.5","Notes",[64,525],{"x":89,"y":526,"width":158,"height":527,"rx":68,"fill":83,"stroke":84,"style":121},"86.0","46.0",[87,529,531],{"x":505,"y":530,"fill":84,"style":95,"textAnchor":507},"105.5","Consent manager (required",[87,533,535],{"x":505,"y":534,"fill":84,"style":95,"textAnchor":507},"121.5","before tracking)",[64,537],{"x":511,"y":526,"width":512,"height":527,"rx":68,"fill":84,"stroke":84,"style":134},[87,539,542],{"x":515,"y":540,"fill":84,"style":541,"textAnchor":111},"113.5","font-size:12px","beforeInteractive or afterInteractive",[64,544],{"x":519,"y":526,"width":512,"height":527,"rx":68,"fill":83,"stroke":84,"style":121},[87,546,547],{"x":522,"y":540,"fill":84,"style":541,"textAnchor":111},"keep it small",[64,549],{"x":89,"y":133,"width":158,"height":502,"rx":68,"fill":83,"stroke":84,"style":121},[87,551,553],{"x":505,"y":552,"fill":84,"style":95,"textAnchor":507},"151.5","Analytics, tag manager",[64,555],{"x":511,"y":133,"width":512,"height":502,"rx":68,"fill":104,"stroke":104,"style":105},[87,557,42],{"x":515,"y":552,"fill":84,"style":541,"textAnchor":111},[64,559],{"x":519,"y":133,"width":512,"height":502,"rx":68,"fill":83,"stroke":84,"style":121},[87,561,562],{"x":522,"y":552,"fill":84,"style":541,"textAnchor":111},"audit tags inside",[64,564],{"x":89,"y":565,"width":158,"height":502,"rx":68,"fill":83,"stroke":84,"style":121},"162.0",[87,567,569],{"x":505,"y":568,"fill":84,"style":95,"textAnchor":507},"181.5","Chat widget",[64,571],{"x":511,"y":565,"width":512,"height":502,"rx":68,"fill":104,"stroke":104,"style":105},[87,573,574],{"x":515,"y":568,"fill":84,"style":541,"textAnchor":111},"lazyOnload or on click",[64,576],{"x":519,"y":565,"width":512,"height":502,"rx":68,"fill":83,"stroke":84,"style":121},[87,578,579],{"x":522,"y":568,"fill":84,"style":541,"textAnchor":111},"facade for best results",[64,581],{"x":89,"y":582,"width":158,"height":502,"rx":68,"fill":83,"stroke":84,"style":121},"192.0",[87,584,586],{"x":505,"y":585,"fill":84,"style":95,"textAnchor":507},"211.5","Social embeds, video players",[64,588],{"x":511,"y":582,"width":512,"height":502,"rx":68,"fill":104,"stroke":104,"style":105},[87,590,591],{"x":515,"y":585,"fill":84,"style":541,"textAnchor":111},"on visibility or click",[64,593],{"x":519,"y":582,"width":512,"height":502,"rx":68,"fill":83,"stroke":84,"style":121},[87,595,596],{"x":522,"y":585,"fill":84,"style":541,"textAnchor":111},"facades",[64,598],{"x":89,"y":599,"width":158,"height":502,"rx":68,"fill":83,"stroke":84,"style":121},"222.0",[87,601,603],{"x":505,"y":602,"fill":84,"style":95,"textAnchor":507},"241.5","A\u002FB testing",[64,605],{"x":511,"y":599,"width":512,"height":502,"rx":68,"fill":84,"stroke":84,"style":134},[87,607,608],{"x":515,"y":602,"fill":84,"style":541,"textAnchor":111},"server-side preferred",[64,610],{"x":519,"y":599,"width":512,"height":502,"rx":68,"fill":83,"stroke":84,"style":121},[87,612,613],{"x":522,"y":602,"fill":84,"style":541,"textAnchor":111},"client scripts block render",[200,615,617],{"id":616},"verification","Verification",[15,619,620],{},"Record traces before and after: long tasks during hydration should shrink, and third-party script execution should move later. In the field, compare INP for early interactions and TBT-related metrics. Confirm scripts still work (analytics hits arrive, chat opens).",[200,622,624],{"id":623},"worked-example-a-saas-marketing-site","Worked Example: A SaaS Marketing Site",[15,626,627,628,630,631,633],{},"A SaaS marketing site loaded a tag manager (with 14 tags), a chat widget, a session replay tool and an A\u002FB testing script, all via raw script tags in the document head. On mobile, TBT was 1.1 seconds and INP p75 310ms. The team moved the tag manager to ",[32,629,42],{}," and removed six unused tags, switched the chat widget to a facade that loads on click, moved session replay to ",[32,632,46],{}," with 10% sampling, and moved A\u002FB testing to edge middleware so variants were rendered server-side. TBT fell to 290ms, INP p75 to 160ms, and LCP improved by 300ms because the A\u002FB script no longer hid the page while waiting.",[200,635,637],{"id":636},"the-worker-strategy","The worker Strategy",[15,639,640,641,643],{},"The experimental ",[32,642,50],{}," strategy uses Partytown to run third-party scripts in a web worker, moving their execution off the main thread. It works well for scripts that mostly send data (analytics) and poorly for scripts that need synchronous DOM access (widgets that render UI). Because DOM access from the worker is proxied, scripts that touch the DOM frequently can become slower. Test each script carefully and monitor data accuracy.",[200,645,647],{"id":646},"measuring-third-party-cost","Measuring Third-Party Cost",[15,649,650],{},"Long Animation Frames attribution reports, per long frame, which script URLs ran and for how long. Collecting this in RUM shows which third-party scripts contribute most to slow interactions in the field. Combine it with a lab trace on a throttled device to see main-thread time per script during load. A per-script cost table — main-thread time, bytes, and business owner — makes it easier to decide which scripts to defer, replace or remove.",[15,652,653],{},[55,654,62,657,62,660,62,663,62,665,62,668,62,670,62,677,62,683,62,688,62,691,62,695,62,699,62,702,62,707,62,711,62,714,62,718,62,722,62,726,62,731,62],{"viewBox":655,"width":58,"role":59,"ariaLabel":656,"style":61},"0 0 760 225","Bar chart of main-thread time during page load attributed to third-party scripts before optimisation.",[64,658],{"className":659,"x":68,"y":68,"width":58,"height":58,"fill":69},[67],[71,661,662],{},"Main-thread time during load by script (mobile profile)",[75,664,656],{},[64,666],{"x":79,"y":79,"width":80,"height":667,"rx":82,"fill":83,"stroke":84,"style":85},"223",[87,669,662],{"x":89,"y":90,"fill":84,"style":91},[87,671,676],{"x":672,"y":673,"fill":84,"style":674,"textAnchor":675},"145.0","70.0","font-size:13px","end","Tag manager + tags",[64,678],{"x":679,"y":100,"width":680,"height":681,"rx":103,"fill":83,"stroke":84,"style":682},"157.0","511.0","19","fill-opacity:0.7;stroke-opacity:0.35",[87,684,687],{"x":685,"y":673,"fill":84,"style":686},"674.0","font-size:12px;font-weight:600","420ms",[87,689,569],{"x":672,"y":690,"fill":84,"style":674,"textAnchor":675},"101.0",[64,692],{"x":679,"y":693,"width":694,"height":681,"rx":103,"fill":83,"stroke":84,"style":682},"87.0","316.4",[87,696,698],{"x":697,"y":690,"fill":84,"style":686},"479.3","260ms",[87,700,701],{"x":672,"y":133,"fill":84,"style":674,"textAnchor":675},"Session replay",[64,703],{"x":679,"y":704,"width":705,"height":681,"rx":103,"fill":104,"stroke":104,"style":706},"118.0","219.0","fill-opacity:0.55;stroke-opacity:0.9",[87,708,710],{"x":709,"y":133,"fill":84,"style":686},"382.0","180ms",[87,712,603],{"x":672,"y":713,"fill":84,"style":674,"textAnchor":675},"163.0",[64,715],{"x":679,"y":716,"width":717,"height":681,"rx":103,"fill":104,"stroke":104,"style":706},"149.0","170.3",[87,719,721],{"x":720,"y":713,"fill":84,"style":686},"333.3","140ms",[87,723,725],{"x":672,"y":724,"fill":84,"style":674,"textAnchor":675},"194.0","App hydration",[64,727],{"x":679,"y":728,"width":729,"height":681,"rx":103,"fill":84,"stroke":84,"style":730},"180.0","462.4","fill-opacity:0.7;stroke-opacity:0.4",[87,732,734],{"x":733,"y":724,"fill":84,"style":686},"625.3","380ms",[200,736,738],{"id":737},"governance-for-third-party-scripts","Governance for Third-Party Scripts",[15,740,741],{},"Third-party scripts are usually added by marketing, analytics or support teams, often through a tag manager without a code review. Agree on simple rules: every script has an owner and a purpose, a loading strategy chosen with engineering, and a periodic review to remove scripts that are no longer used. Keep a register of scripts with their measured main-thread cost. When a new script is requested, test it on a staging build with a throttled profile and add it with the latest strategy that still meets its purpose. This turns third-party performance from a recurring firefight into a routine decision.",[200,743,745],{"id":744},"common-mistakes","Common Mistakes",[205,747,748,757,763,769],{},[208,749,750,753,754,756],{},[211,751,752],{},"Raw script tags in the head."," Bypass ",[32,755,34],{}," and block parsing.",[208,758,759,762],{},[211,760,761],{},"beforeInteractive for analytics."," Delays hydration with no user benefit.",[208,764,765,768],{},[211,766,767],{},"Loading chat on every page."," Most visitors never open it.",[208,770,771,774],{},[211,772,773],{},"Ignoring tags inside the tag manager."," The container is light; its tags are not.",[200,776,778],{"id":777},"edge-cases","Edge Cases",[15,780,781,784],{},[211,782,783],{},"Consent requirements."," Some scripts must not load before consent; load them in response to the consent event.",[15,786,787,62,790,792,793,796],{},[211,788,789],{},"Inline scripts.",[32,791,34],{}," supports inline scripts with an ",[32,794,795],{},"id","; the same strategies apply.",[15,798,799,62,802,804,805,808,809,812],{},[211,800,801],{},"Pages Router.",[32,803,38],{}," scripts belong in ",[32,806,807],{},"_document","; other strategies work in pages and ",[32,810,811],{},"_app",".",[15,814,815,818,819,822,823,826],{},[211,816,817],{},"onLoad callbacks."," Use ",[32,820,821],{},"onLoad"," or ",[32,824,825],{},"onReady"," to initialise scripts after they load rather than polling.",[200,828,830],{"id":829},"faq","FAQ",[832,833,836,840],"details",{"className":834},[835],"faq-item",[837,838,839],"summary",{},"What is the default next\u002Fscript strategy?",[15,841,842,844],{},[32,843,42],{},", which loads the script after hydration begins on the client.",[832,846,848,851],{"className":847},[835],[837,849,850],{},"When should I use beforeInteractive?",[15,852,853],{},"Only for scripts that must run before the page is interactive, such as some consent or bot-protection scripts. Keep them small.",[832,855,857,860],{"className":856},[835],[837,858,859],{},"Is lazyOnload safe for analytics?",[15,861,862,863,865],{},"It delays analytics until idle, which may miss very short visits. ",[32,864,42],{}," is the usual choice for analytics.",[832,867,869,872],{"className":868},[835],[837,870,871],{},"Does the worker strategy work with all scripts?",[15,873,874],{},"No. Scripts that need synchronous DOM access may break or slow down. Test each one.",[832,876,878,881],{"className":877},[835],[837,879,880],{},"How do I load a script only on some pages?",[15,882,883,884,886],{},"Include the ",[32,885,383],{}," component in those pages or layouts instead of the root layout.",[832,888,890,893],{"className":889},[835],[837,891,892],{},"Can next\u002Fscript load scripts on interaction?",[15,894,895,896,898],{},"Not directly; render the ",[32,897,383],{}," component conditionally after the user interacts (for example, after clicking a chat facade).",[832,900,902,905],{"className":901},[835],[837,903,904],{},"How do I know which third-party script hurts INP?",[15,906,907],{},"Use Long Animation Frames attribution in RUM, or record interactions in the Performance panel and check script URLs in long tasks.",[832,909,911,914],{"className":910},[835],[837,912,913],{},"Should A\u002FB tests run client-side?",[15,915,916],{},"Server-side or edge experiments avoid blocking rendering. Client-side experiments that hide the page while loading hurt LCP.",[832,918,920,923],{"className":919},[835],[837,921,922],{},"Do scripts in the root layout load on every route?",[15,924,925],{},"Yes. Scripts rendered in the root layout load on every page; place scripts in specific layouts or pages if only some routes need them.",[832,927,929,932],{"className":928},[835],[837,930,931],{},"Can I measure each script's cost before adding it?",[15,933,934],{},"Yes. Add it on a preview deployment and record a throttled trace with and without it, comparing main-thread time and long tasks during load.",[200,936,938],{"id":937},"related","Related",[205,940,941,948,955],{},[208,942,943,947],{},[19,944,946],{"href":945},"\u002Fframework-performance\u002Fnextjs-performance\u002Freducing-nextjs-first-load-javascript\u002F","Reducing Next.js first load JavaScript"," — your own JavaScript.",[208,949,950,954],{},[19,951,953],{"href":952},"\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Freplacing-youtube-embeds-with-a-facade\u002F","Replacing YouTube embeds with a facade"," — the facade pattern.",[208,956,957,961],{},[19,958,960],{"href":959},"\u002Fimage-media-optimization\u002Flazy-loading-images-without-hurting-lcp\u002Flazy-loading-iframes\u002F","Lazy-loading iframes"," — embeds without the cost.",[126,963,965],{"type":964},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"How to Choose next\u002Fscript Loading Strategies\",\n  \"description\": \"How each next\u002Fscript strategy affects loading and main-thread time, and how to assign the right one to analytics, tag managers, chat, ads and embeds.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Assign a strategy per script\",\n      \"text\": \"Assign a strategy per script\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Load heavy widgets on interaction\",\n      \"text\": \"Replace chat widgets and embeds with a lightweight facade (a button or image) that loads the real script when clicked.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Audit the tag manager\",\n      \"text\": \"Remove unused tags, set triggers to fire after load or on interaction, and avoid tags that inject synchronous scripts.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Reserve beforeInteractive for genuine needs\",\n      \"text\": \"Use it only for scripts that must run before the page is interactive (some consent or bot-detection scripts).\"\n    }\n  ]\n}\n",[126,967,968],{"type":964},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"How to Choose next\u002Fscript Loading Strategies\",\n  \"description\": \"How each next\u002Fscript strategy affects loading and main-thread time, and how to assign the right one to analytics, tag managers, chat, ads and embeds.\",\n  \"datePublished\": \"2026-10-06\",\n  \"dateModified\": \"2026-10-06\",\n  \"author\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"mainEntityOfPage\": {\n    \"@type\": \"WebPage\",\n    \"@id\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002Fnextjs-performance\u002Fchoosing-next-script-loading-strategies\u002F\"\n  }\n}\n",[126,970,971],{"type":964},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"BreadcrumbList\",\n  \"itemListElement\": [\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 1,\n      \"name\": \"Home\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 2,\n      \"name\": \"Framework Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"Next.js Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002Fnextjs-performance\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Choosing next\u002Fscript Loading Strategies\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002Fnextjs-performance\u002Fchoosing-next-script-loading-strategies\u002F\"\n    }\n  ]\n}\n",[973,974,975],"style",{},"html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .sZ8jY, html code.shiki .sZ8jY{--shiki-default:#032563;--shiki-dark:#ADDCFF;--shiki-light:#032563}html pre.shiki code .smZ65, html code.shiki .smZ65{--shiki-default:#622CBC;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}html pre.shiki code .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}html pre.shiki code .sZBmE, html code.shiki .sZBmE{--shiki-default:#024C1A;--shiki-dark:#72F088;--shiki-light:#024C1A}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}",{"title":283,"searchDepth":310,"depth":310,"links":977},[978,979,980,986,987,988,989,990,991,992,993,994],{"id":202,"depth":310,"text":203},{"id":242,"depth":310,"text":243},{"id":270,"depth":310,"text":271,"children":981},[982,983,984,985],{"id":275,"depth":333,"text":276},{"id":462,"depth":333,"text":463},{"id":469,"depth":333,"text":470},{"id":476,"depth":333,"text":477},{"id":616,"depth":310,"text":617},{"id":623,"depth":310,"text":624},{"id":636,"depth":310,"text":637},{"id":646,"depth":310,"text":647},{"id":737,"depth":310,"text":738},{"id":744,"depth":310,"text":745},{"id":777,"depth":310,"text":778},{"id":829,"depth":310,"text":830},{"id":937,"depth":310,"text":938},"How each next\u002Fscript strategy affects loading and main-thread time, and how to assign the right one to analytics, tag managers, chat, ads and embeds.","md",{"slug":998,"type":999,"breadcrumb":1000,"datePublished":1008,"dateModified":1008},"choosing-next-script-loading-strategies","article",[1001,1004,1005,1006],{"name":1002,"url":1003},"Home","\u002F",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":1007},"\u002Fframework-performance\u002Fnextjs-performance\u002Fchoosing-next-script-loading-strategies\u002F","2026-10-06",true,"\u002Fframework-performance\u002Fnextjs-performance\u002Fchoosing-next-script-loading-strategies",{"title":1012,"description":1013},"Choosing next\u002Fscript Loading Strategies for Performance","Pick beforeInteractive, afterInteractive, lazyOnload or worker for each third-party script in Next.js, and load chat and embeds on interaction to protect INP.","framework-performance\u002Fnextjs-performance\u002Fchoosing-next-script-loading-strategies\u002Findex","tRt2uMo9t9VHtOvLRwrUzUuxhfiDXavCcIIM5rpgxgI",[1017,1020],{"title":22,"path":1018,"stem":1019,"children":-1},"\u002Fframework-performance\u002Fnextjs-performance","framework-performance\u002Fnextjs-performance\u002Findex",{"title":1021,"path":1022,"stem":1023,"children":-1},"Eliminating Font CLS with next\u002Ffont","\u002Fframework-performance\u002Fnextjs-performance\u002Feliminating-font-cls-with-next-font","framework-performance\u002Fnextjs-performance\u002Feliminating-font-cls-with-next-font\u002Findex",1791308074633]