[{"data":1,"prerenderedAt":962},["ShallowReactive",2],{"content:\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Freducing-consent-management-platform-cost":3,"surroundings:\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Freducing-consent-management-platform-cost":953},{"id":4,"title":5,"body":6,"description":932,"extension":933,"meta":934,"navigation":946,"path":947,"seo":948,"stem":951,"__hash__":952},"content\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Freducing-consent-management-platform-cost\u002Findex.md","Reducing Consent Management Platform Cost",{"type":7,"value":8,"toc":916},"minimark",[9,14,29,37,182,187,221,225,231,237,243,249,367,371,376,379,508,511,515,518,521,525,528,646,651,655,658,742,746,752,756,759,763,789,793,799,805,811,817,821,833,849,858,867,876,880,902,906,909,912],[10,11,13],"h1",{"id":12},"how-to-reduce-the-performance-cost-of-your-consent-management-platform","How to Reduce the Performance Cost of Your Consent Management Platform",[15,16,17,18,23,24,28],"p",{},"This guide addresses a compliance-driven third party within ",[19,20,22],"a",{"href":21},"\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002F","Third-Party Script Performance",", part of ",[19,25,27],{"href":26},"\u002Fjavascript-bundle-optimization-code-splitting\u002F","JavaScript Bundle Optimization & Code Splitting",". A consent management platform (CMP) must run early — tags cannot fire until consent is known — on every page, for every visitor. That makes it one of the most performance-sensitive scripts on a site, and many CMPs are not built with that in mind: they load a configuration file from their own CDN, render the banner with a client-side framework, and, when the user accepts, synchronously release a backlog of tags in the same task as the click.",[15,30,31,32,36],{},"Each of those behaviours maps to a Core Web Vital. A slow CMP load delays the banner, which can become the LCP element on mobile. A client-rendered banner inserted into document flow shifts layout. And the accept click — often the first interaction of the visit — can exceed ",[33,34,35],"code",{},"200ms"," because of everything that runs in its handler.",[15,38,39],{},[40,41,47,48,47,55,47,59,47,62,47,71,47,77,47,88,47,93,47,102,47,109,47,113,47,119,47,123,47,127,47,131,47,136,47,142,47,146,47,150,47,154,47,156,47,160,47,164,47,168,47,172,47,176,47],"svg",{"viewBox":42,"width":43,"role":44,"ariaLabel":45,"style":46},"0 0 760 162","100%","img","Timeline of a consent accept click whose handler writes consent, fires queued tags and initialises analytics in one long task.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[49,50],"rect",{"className":51,"x":53,"y":53,"width":43,"height":43,"fill":54},[52],"svg-canvas","0","#ffffff",[56,57,58],"title",{},"The accept click on a typical CMP",[60,61,45],"desc",{},[49,63],{"x":64,"y":64,"width":65,"height":66,"rx":67,"fill":68,"stroke":69,"style":70},"1","758","160","10","none","currentColor","stroke-opacity:0.18",[72,73,58],"text",{"x":74,"y":75,"fill":69,"style":76},"28.0","34.0","font-size:16px;font-weight:700",[78,79],"line",{"x1":80,"y1":81,"x2":80,"y2":82,"stroke":83,"strokeWidth":84,"strokeDashArray":85,"style":87},"378.7","72.0","118.0","#b8860b","1.5",[86,86],"4","stroke-opacity:0.9",[72,89,92],{"x":74,"y":90,"fill":69,"style":91},"96.0","font-size:12.5px;font-weight:700","Click task",[49,94],{"x":95,"y":96,"width":97,"height":98,"rx":99,"fill":100,"stroke":100,"style":101},"101.6","78.0","40.2","26.0","3","#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[72,103,108],{"x":104,"y":105,"fill":69,"style":106,"textAnchor":107},"121.7","95.5","font-size:10.5px","middle","handler",[49,110],{"x":111,"y":96,"width":97,"height":98,"rx":99,"fill":69,"stroke":69,"style":112},"143.3","fill-opacity:0.06;stroke-opacity:0.4",[49,114],{"x":115,"y":96,"width":116,"height":98,"rx":99,"fill":117,"stroke":83,"style":118},"184.9","387.5","#ffc300","fill-opacity:0.24;stroke-opacity:0.9",[72,120,122],{"x":80,"y":105,"fill":69,"style":121,"textAnchor":107},"font-size:11.5px","fire queued tags",[49,124],{"x":125,"y":96,"width":126,"height":98,"rx":99,"fill":100,"stroke":100,"style":101},"573.9","81.9",[72,128,130],{"x":129,"y":105,"fill":69,"style":121,"textAnchor":107},"614.9","hide banner",[78,132],{"x1":133,"y1":82,"x2":134,"y2":82,"stroke":69,"style":135},"100.8","726.0","stroke-opacity:0.4",[72,137,141],{"x":138,"y":139,"fill":140,"style":121,"textAnchor":107},"111.5","135.0","#51617a","0ms",[72,143,145],{"x":144,"y":139,"fill":140,"style":121,"textAnchor":107},"170.3","50ms",[72,147,149],{"x":148,"y":139,"fill":140,"style":121,"textAnchor":107},"239.8","100ms",[72,151,153],{"x":152,"y":139,"fill":140,"style":121,"textAnchor":107},"309.2","150ms",[72,155,35],{"x":80,"y":139,"fill":140,"style":121,"textAnchor":107},[72,157,159],{"x":158,"y":139,"fill":140,"style":121,"textAnchor":107},"448.1","250ms",[72,161,163],{"x":162,"y":139,"fill":140,"style":121,"textAnchor":107},"517.6","300ms",[72,165,167],{"x":166,"y":139,"fill":140,"style":121,"textAnchor":107},"587.1","350ms",[72,169,171],{"x":170,"y":139,"fill":140,"style":121,"textAnchor":107},"656.5","400ms",[72,173,175],{"x":174,"y":139,"fill":140,"style":121,"textAnchor":107},"715.3","450ms",[72,177,181],{"x":80,"y":178,"fill":179,"style":180,"textAnchor":107},"68.0","#8a6608","font-size:12px;font-weight:700","INP 200ms",[183,184,186],"h2",{"id":185},"rapid-diagnosis","Rapid Diagnosis",[188,189,190,198,204,210],"ul",{},[191,192,193,197],"li",{},[194,195,196],"strong",{},"Measure CMP load timing."," Network panel: CMP script and configuration requests, their origins and when they finish relative to FCP\u002FLCP.",[191,199,200,203],{},[194,201,202],{},"Check the LCP element on mobile first visits."," If it is the banner's text, the CMP's timing is your LCP.",[191,205,206,209],{},[194,207,208],{},"Record the accept click."," In a throttled trace, the interaction's processing duration and what runs inside it.",[191,211,212,215,216,220],{},[194,213,214],{},"Check banner layout."," Is it fixed-position or in flow? See ",[19,217,219],{"href":218},"\u002Fcore-web-vitals-measurement\u002Freducing-cumulative-layout-shift-cls\u002Ffixing-cls-from-cookie-consent-banners\u002F","fixing CLS from cookie consent banners",".",[183,222,224],{"id":223},"root-cause-analysis","Root Cause Analysis",[15,226,227,230],{},[194,228,229],{},"1. Third-party loading chain."," CMP loader → configuration JSON → banner template → vendor list, each from the CMP's CDN, each a round trip.",[15,232,233,236],{},[194,234,235],{},"2. Client-side banner rendering."," The banner appears only after the chain completes and a framework renders it.",[15,238,239,242],{},[194,240,241],{},"3. Synchronous tag release."," On accept, the CMP notifies listeners, which fire every queued tag synchronously inside the click task.",[15,244,245,248],{},[194,246,247],{},"4. Large vendor lists."," IAB TCF-based CMPs may load the global vendor list (hundreds of KB) to render detailed preference screens, sometimes eagerly.",[15,250,251],{},[40,252,47,255,47,258,47,261,47,263,47,280,47,283,47,285,47,290,47,295,47,299,47,302,47,306,47,309,47,312,47,316,47,320,47,324,47,327,47,331,47,334,47,337,47,341,47,344,47,348,47,355,47,359,47,363,47],{"viewBox":253,"width":43,"role":44,"ariaLabel":254,"style":46},"0 0 760 150","Sequential requests a typical consent management platform makes before the banner can appear.",[49,256],{"className":257,"x":53,"y":53,"width":43,"height":43,"fill":54},[52],[56,259,260],{},"Typical CMP loading chain",[60,262,254],{},[264,265,266],"defs",{},[267,268,275],"marker",{"id":269,"viewBox":270,"refX":271,"refY":272,"markerWidth":273,"markerHeight":273,"orient":274},"faf010683e","0 0 10 10","9","5","7","auto-start-reverse",[276,277],"path",{"d":278,"fill":69,"style":279},"M0 0 L10 5 L0 10 z","fill-opacity:0.7",[49,281],{"x":64,"y":64,"width":65,"height":282,"rx":67,"fill":68,"stroke":69,"style":70},"148",[72,284,260],{"x":74,"y":75,"fill":69,"style":76},[49,286],{"x":74,"y":287,"width":288,"height":81,"rx":289,"fill":100,"stroke":100,"style":101},"56.0","108.8","6",[72,291,294],{"x":292,"y":96,"fill":69,"style":293,"textAnchor":107},"82.4","font-size:13px;font-weight:700","Loader script",[72,296,298],{"x":292,"y":90,"fill":69,"style":297,"textAnchor":107},"font-size:12px","CMP CDN",[49,300],{"x":301,"y":287,"width":288,"height":81,"rx":289,"fill":100,"stroke":100,"style":101},"176.8",[72,303,305],{"x":304,"y":96,"fill":69,"style":293,"textAnchor":107},"231.2","Config JSON",[72,307,308],{"x":304,"y":90,"fill":69,"style":297,"textAnchor":107},"per domain",[49,310],{"x":311,"y":287,"width":288,"height":81,"rx":289,"fill":100,"stroke":100,"style":101},"325.6",[72,313,315],{"x":314,"y":96,"fill":69,"style":293,"textAnchor":107},"380.0","Banner",[72,317,319],{"x":314,"y":318,"fill":69,"style":293,"textAnchor":107},"95.0","template",[72,321,323],{"x":314,"y":322,"fill":69,"style":297,"textAnchor":107},"113.0","+ translations",[49,325],{"x":326,"y":287,"width":288,"height":81,"rx":289,"fill":117,"stroke":83,"style":118},"474.4",[72,328,330],{"x":329,"y":96,"fill":69,"style":293,"textAnchor":107},"528.8","Render banner",[72,332,333],{"x":329,"y":90,"fill":69,"style":297,"textAnchor":107},"client framework",[49,335],{"x":336,"y":287,"width":288,"height":81,"rx":289,"fill":100,"stroke":100,"style":101},"623.2",[72,338,340],{"x":339,"y":96,"fill":69,"style":293,"textAnchor":107},"677.6","Vendor list",[72,342,343],{"x":339,"y":90,"fill":69,"style":297,"textAnchor":107},"if preferences",[72,345,347],{"x":339,"y":346,"fill":69,"style":297,"textAnchor":107},"112.0","opened",[78,349],{"x1":350,"y1":351,"x2":352,"y2":351,"stroke":69,"strokeWidth":84,"style":353,"markerEnd":354},"136.8","92.0","174.8","stroke-opacity:0.6","url(#faf010683e)",[78,356],{"x1":357,"y1":351,"x2":358,"y2":351,"stroke":69,"strokeWidth":84,"style":353,"markerEnd":354},"285.6","323.6",[78,360],{"x1":361,"y1":351,"x2":362,"y2":351,"stroke":69,"strokeWidth":84,"style":353,"markerEnd":354},"434.4","472.4",[78,364],{"x1":365,"y1":351,"x2":366,"y2":351,"stroke":69,"strokeWidth":84,"style":353,"markerEnd":354},"583.2","621.2",[183,368,370],{"id":369},"step-by-step-resolution","Step-by-Step Resolution",[372,373,375],"h3",{"id":374},"_1-self-host-or-proxy-the-cmp-and-inline-its-configuration","1. Self-host or proxy the CMP and inline its configuration",[15,377,378],{},"Serve the loader from your origin (if the vendor allows) and inline the configuration in the HTML, removing at least two round trips.",[380,381,386],"pre",{"className":382,"code":383,"language":384,"meta":385,"style":385},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u003Cscript>window.__cmpConfig = {\"lang\":\"en\",\"purposes\":[1,2,3,4],\"vendorsUrl\":\"\u002Fcmp\u002Fvendors.json\"};\u003C\u002Fscript>\n\u003Cscript src=\"\u002Fcmp\u002Floader.3e9a.js\" async>\u003C\u002Fscript>\n\u003C!-- trade-off: self-hosted CMP code must be updated when the vendor ships\n     legal or bug fixes. Proxy with a short TTL instead of mirroring if the\n     vendor updates frequently. -->\n","html","",[33,387,388,464,489,496,502],{"__ignoreMap":385},[389,390,392,396,400,403,407,410,414,417,420,423,426,429,432,434,437,439,441,443,445,448,451,453,456,459,461],"span",{"class":78,"line":391},1,[389,393,395],{"class":394},"saISM","\u003C",[389,397,399],{"class":398},"sZBmE","script",[389,401,402],{"class":394},">window.__cmpConfig ",[389,404,406],{"class":405},"sPARh","=",[389,408,409],{"class":394}," {",[389,411,413],{"class":412},"sZ8jY","\"lang\"",[389,415,416],{"class":394},":",[389,418,419],{"class":412},"\"en\"",[389,421,422],{"class":394},",",[389,424,425],{"class":412},"\"purposes\"",[389,427,428],{"class":394},":[",[389,430,64],{"class":431},"sPXB4",[389,433,422],{"class":394},[389,435,436],{"class":431},"2",[389,438,422],{"class":394},[389,440,99],{"class":431},[389,442,422],{"class":394},[389,444,86],{"class":431},[389,446,447],{"class":394},"],",[389,449,450],{"class":412},"\"vendorsUrl\"",[389,452,416],{"class":394},[389,454,455],{"class":412},"\"\u002Fcmp\u002Fvendors.json\"",[389,457,458],{"class":394},"};\u003C\u002F",[389,460,399],{"class":398},[389,462,463],{"class":394},">\n",[389,465,467,469,471,474,476,479,482,485,487],{"class":78,"line":466},2,[389,468,395],{"class":394},[389,470,399],{"class":398},[389,472,473],{"class":431}," src",[389,475,406],{"class":394},[389,477,478],{"class":412},"\"\u002Fcmp\u002Floader.3e9a.js\"",[389,480,481],{"class":431}," async",[389,483,484],{"class":394},">\u003C\u002F",[389,486,399],{"class":398},[389,488,463],{"class":394},[389,490,492],{"class":78,"line":491},3,[389,493,495],{"class":494},"sjfSM","\u003C!-- trade-off: self-hosted CMP code must be updated when the vendor ships\n",[389,497,499],{"class":78,"line":498},4,[389,500,501],{"class":494},"     legal or bug fixes. Proxy with a short TTL instead of mirroring if the\n",[389,503,505],{"class":78,"line":504},5,[389,506,507],{"class":494},"     vendor updates frequently. -->\n",[15,509,510],{},"Expected outcome: the banner appears hundreds of milliseconds earlier on mobile.",[372,512,514],{"id":513},"_2-server-render-the-banner-markup","2. Server-render the banner markup",[15,516,517],{},"Render the banner HTML on the server when the consent cookie is absent, as a fixed-position overlay with its final size. Let the CMP script attach behaviour to existing markup rather than creating it.",[15,519,520],{},"Expected outcome: the banner paints with the page (no late insertion, no CLS), and its text is never a late LCP candidate.",[372,522,524],{"id":523},"_3-release-tags-after-the-clicks-paint","3. Release tags after the click's paint",[15,526,527],{},"Wrap tag release in a task scheduled after the next paint, so the click's interaction ends as soon as the banner hides.",[380,529,533],{"className":530,"code":531,"language":532,"meta":385,"style":385},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","function onConsentAccepted(consent) {\n  hideBanner();                                            \u002F\u002F visible response first\n  requestAnimationFrame(() => setTimeout(() => {           \u002F\u002F after the next paint\n    window.dataLayer.push({ event: 'consent_update', ...consent });\n  }, 0));\n}\n\u002F\u002F trade-off: tags fire a frame or two later than before. If a page unload\n\u002F\u002F follows the click immediately (rare), some tags may not fire; send critical\n\u002F\u002F conversion signals with sendBeacon instead.\n","javascript",[33,534,535,554,565,589,612,622,628,634,640],{"__ignoreMap":385},[389,536,537,540,544,547,551],{"class":78,"line":391},[389,538,539],{"class":405},"function",[389,541,543],{"class":542},"smZ65"," onConsentAccepted",[389,545,546],{"class":394},"(",[389,548,550],{"class":549},"sQw3B","consent",[389,552,553],{"class":394},") {\n",[389,555,556,559,562],{"class":78,"line":466},[389,557,558],{"class":542},"  hideBanner",[389,560,561],{"class":394},"();                                            ",[389,563,564],{"class":494},"\u002F\u002F visible response first\n",[389,566,567,570,573,576,579,581,583,586],{"class":78,"line":491},[389,568,569],{"class":542},"  requestAnimationFrame",[389,571,572],{"class":394},"(() ",[389,574,575],{"class":405},"=>",[389,577,578],{"class":542}," setTimeout",[389,580,572],{"class":394},[389,582,575],{"class":405},[389,584,585],{"class":394}," {           ",[389,587,588],{"class":494},"\u002F\u002F after the next paint\n",[389,590,591,594,597,600,603,606,609],{"class":78,"line":498},[389,592,593],{"class":394},"    window.dataLayer.",[389,595,596],{"class":542},"push",[389,598,599],{"class":394},"({ event: ",[389,601,602],{"class":412},"'consent_update'",[389,604,605],{"class":394},", ",[389,607,608],{"class":405},"...",[389,610,611],{"class":394},"consent });\n",[389,613,614,617,619],{"class":78,"line":504},[389,615,616],{"class":394},"  }, ",[389,618,53],{"class":431},[389,620,621],{"class":394},"));\n",[389,623,625],{"class":78,"line":624},6,[389,626,627],{"class":394},"}\n",[389,629,631],{"class":78,"line":630},7,[389,632,633],{"class":494},"\u002F\u002F trade-off: tags fire a frame or two later than before. If a page unload\n",[389,635,637],{"class":78,"line":636},8,[389,638,639],{"class":494},"\u002F\u002F follows the click immediately (rare), some tags may not fire; send critical\n",[389,641,643],{"class":78,"line":642},9,[389,644,645],{"class":494},"\u002F\u002F conversion signals with sendBeacon instead.\n",[15,647,648,649,220],{},"Expected outcome: accept-click INP falls from several hundred milliseconds to well under ",[33,650,35],{},[372,652,654],{"id":653},"_4-load-the-vendor-list-only-when-needed","4. Load the vendor list only when needed",[15,656,657],{},"Load detailed vendor and purpose data only when the user opens the preferences screen, not with the initial banner.",[15,659,660],{},[40,661,47,664,47,667,47,670,47,672,47,675,47,677,47,681,47,687,47,691,47,696,47,699,47,702,47,705,47,708,47,711,47,714,47,717,47,721,47,723,47,727,47,729,47,732,47,734,47,737,47,739,47],{"viewBox":662,"width":43,"role":44,"ariaLabel":663,"style":46},"0 0 760 228","Comparison of a consent management platform setup before and after self-hosting, server rendering and deferred tag release.",[49,665],{"className":666,"x":53,"y":53,"width":43,"height":43,"fill":54},[52],[56,668,669],{},"CMP before and after optimisation",[60,671,663],{},[49,673],{"x":64,"y":64,"width":65,"height":674,"rx":67,"fill":68,"stroke":69,"style":70},"226",[72,676,669],{"x":74,"y":75,"fill":69,"style":76},[49,678],{"x":74,"y":287,"width":679,"height":680,"rx":289,"fill":117,"stroke":83,"style":118},"340.0","150.0",[72,682,686],{"x":683,"y":684,"fill":69,"style":685},"42.0","82.0","font-size:14px;font-weight:700","Before",[72,688,690],{"x":683,"y":689,"fill":69,"style":91},"108.0","•",[72,692,695],{"x":287,"y":689,"fill":69,"style":693,"textAnchor":694},"font-size:12.5px","start","3 requests to CMP CDN before banner",[72,697,690],{"x":683,"y":698,"fill":69,"style":91},"132.0",[72,700,701],{"x":287,"y":698,"fill":69,"style":693,"textAnchor":694},"Banner rendered client-side, in flow",[72,703,690],{"x":683,"y":704,"fill":69,"style":91},"156.0",[72,706,707],{"x":287,"y":704,"fill":69,"style":693,"textAnchor":694},"Tags released inside accept click",[72,709,690],{"x":683,"y":710,"fill":69,"style":91},"180.0",[72,712,713],{"x":287,"y":710,"fill":69,"style":693,"textAnchor":694},"Accept INP 340ms, CLS 0.12",[49,715],{"x":716,"y":287,"width":679,"height":680,"rx":289,"fill":100,"stroke":100,"style":101},"392.0",[72,718,720],{"x":719,"y":684,"fill":69,"style":685},"406.0","After",[72,722,690],{"x":719,"y":689,"fill":69,"style":91},[72,724,726],{"x":725,"y":689,"fill":69,"style":693,"textAnchor":694},"420.0","Self-hosted loader, inline config",[72,728,690],{"x":719,"y":698,"fill":69,"style":91},[72,730,731],{"x":725,"y":698,"fill":69,"style":693,"textAnchor":694},"Server-rendered fixed overlay",[72,733,690],{"x":719,"y":704,"fill":69,"style":91},[72,735,736],{"x":725,"y":704,"fill":69,"style":693,"textAnchor":694},"Tags released after next paint",[72,738,690],{"x":719,"y":710,"fill":69,"style":91},[72,740,741],{"x":725,"y":710,"fill":69,"style":693,"textAnchor":694},"Accept INP 70ms, CLS 0",[183,743,745],{"id":744},"verification","Verification",[15,747,748,749,751],{},"As a first-time visitor on a throttled mobile profile: the banner should appear with the first paint (or very shortly after), produce no layout shift, and the accept click should complete under ",[33,750,149],{}," in the Interactions track. Confirm in your tag debugger that tags still fire after consent and not before. In RUM, segment INP and CLS by first visit versus returning visit (consent stored); the first-visit penalty should shrink substantially.",[183,753,755],{"id":754},"worked-example-a-publishers-tcf-banner","Worked Example: A Publisher's TCF Banner",[15,757,758],{},"A publisher's IAB TCF CMP made four sequential requests before rendering, loaded the 300KB vendor list eagerly, and released 23 ad and analytics tags inside the accept click. First-visit metrics on mobile: banner LCP 3.4s for 40% of first visits, accept INP 520ms. After proxying the loader, inlining config, server-rendering the banner overlay, lazy-loading the vendor list and deferring tag release by one frame, banner-related LCP fell below 2s and accept INP to 90ms. Consent rates were unchanged, and ad revenue per first visit rose slightly because ads began loading sooner after consent.",[183,760,762],{"id":761},"common-mistakes","Common Mistakes",[188,764,765,771,777,783],{},[191,766,767,770],{},[194,768,769],{},"Treating the CMP as untouchable."," Many configuration and loading changes are compliant and supported by vendors.",[191,772,773,776],{},[194,774,775],{},"Delaying the CMP itself."," It must remain early; the goal is to make it fast, not late.",[191,778,779,782],{},[194,780,781],{},"Firing tags before consent to \"speed things up\"."," That breaks compliance; only scheduling changes are acceptable.",[191,784,785,788],{},[194,786,787],{},"Forgetting returning visitors."," With consent stored, the CMP should do almost nothing — check that it does not still load the full UI.",[183,790,792],{"id":791},"edge-cases","Edge Cases",[15,794,795,798],{},[194,796,797],{},"Geo-specific banners."," Showing banners only in regulated regions requires a server-side or edge decision; doing it client-side means loading the CMP everywhere just to decide.",[15,800,801,804],{},[194,802,803],{},"Consent mode for analytics."," Some analytics tools support modelling without cookies before consent, which lets a minimal tag run early and the full one after consent.",[15,806,807,810],{},[194,808,809],{},"Single-page apps."," The CMP should initialise once per session, not per route.",[15,812,813,816],{},[194,814,815],{},"Accessibility."," A server-rendered banner must still manage focus correctly; test with keyboard and screen readers.",[183,818,820],{"id":819},"faq","FAQ",[822,823,826,830],"details",{"className":824},[825],"faq-item",[827,828,829],"summary",{},"Is it compliant to render the banner server-side?",[15,831,832],{},"Rendering the banner is presentation; compliance depends on not setting non-essential cookies or firing non-essential tags before consent, and on recording choices correctly. Server rendering does not change those obligations. Confirm specifics with your legal team and CMP vendor.",[822,834,836,839],{"className":835},[825],[827,837,838],{},"Can the CMP be loaded with defer instead of async?",[15,840,841,844,845,848],{},[33,842,843],{},"defer"," runs scripts after parsing, in order — fine for a self-hosted, small loader whose banner markup is already in the HTML. ",[33,846,847],{},"async"," runs as soon as downloaded, which suits a loader that must run as early as possible. Choose based on whether the banner depends on the script to appear.",[822,850,852,855],{"className":851},[825],[827,853,854],{},"How do I measure the CMP's effect on INP specifically?",[15,856,857],{},"Filter INP attribution to the accept and reject button selectors, or collect LoAF script attribution and look for the CMP and tag scripts in the accept interaction's frame.",[822,859,861,864],{"className":860},[825],[827,862,863],{},"Does a lighter CMP make a difference?",[15,865,866],{},"Yes. CMPs vary widely in size and behaviour, from a few kilobytes to several hundred. If yours resists optimisation, compare alternatives on bundle size, rendering approach and tag-release behaviour.",[822,868,870,873],{"className":869},[825],[827,871,872],{},"Does the reject button need the same treatment?",[15,874,875],{},"Yes. Rejecting often runs less work than accepting, but CMPs may still write cookies, notify listeners and update consent signals synchronously. Measure both buttons; whichever handler is slower determines the worst first interaction for that user group.",[183,877,879],{"id":878},"related","Related",[188,881,882,888,895],{},[191,883,884,887],{},[19,885,886],{"href":218},"Fixing CLS from cookie consent banners"," — the layout side in detail.",[191,889,890,894],{},[19,891,893],{"href":892},"\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Fauditing-google-tag-manager-container-weight\u002F","Auditing Google Tag Manager container weight"," — the tags the CMP releases.",[191,896,897,901],{},[19,898,900],{"href":899},"\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Fself-hosting-third-party-scripts\u002F","Self-hosting third-party scripts"," — proxying the CMP loader.",[399,903,905],{"type":904},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"How to Reduce the Performance Cost of Your Consent Management Platform\",\n  \"description\": \"How consent management platforms affect LCP, INP and CLS, and the loading, rendering and tag-release changes that reduce their cost without compromising compliance.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Self-host or proxy the CMP and inline its configuration\",\n      \"text\": \"Serve the loader from your origin (if the vendor allows) and inline the configuration in the HTML, removing at least two round trips.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Server-render the banner markup\",\n      \"text\": \"Render the banner HTML on the server when the consent cookie is absent, as a fixed-position overlay with its final size.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Release tags after the click's paint\",\n      \"text\": \"Wrap tag release in a task scheduled after the next paint, so the click's interaction ends as soon as the banner hides.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Load the vendor list only when needed\",\n      \"text\": \"Load detailed vendor and purpose data only when the user opens the preferences screen, not with the initial banner.\"\n    }\n  ]\n}\n",[399,907,908],{"type":904},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"How to Reduce the Performance Cost of Your Consent Management Platform\",\n  \"description\": \"How consent management platforms affect LCP, INP and CLS, and the loading, rendering and tag-release changes that reduce their cost without compromising compliance.\",\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\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Freducing-consent-management-platform-cost\u002F\"\n  }\n}\n",[399,910,911],{"type":904},"\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\": \"JavaScript Bundle Optimization & Code Splitting\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fjavascript-bundle-optimization-code-splitting\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"Third-Party Script Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Reducing Consent Management Platform Cost\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Freducing-consent-management-platform-cost\u002F\"\n    }\n  ]\n}\n",[913,914,915],"style",{},"html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .sZBmE, html code.shiki .sZBmE{--shiki-default:#024C1A;--shiki-dark:#72F088;--shiki-light:#024C1A}html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .sZ8jY, html code.shiki .sZ8jY{--shiki-default:#032563;--shiki-dark:#ADDCFF;--shiki-light:#032563}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);}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}",{"title":385,"searchDepth":466,"depth":466,"links":917},[918,919,920,926,927,928,929,930,931],{"id":185,"depth":466,"text":186},{"id":223,"depth":466,"text":224},{"id":369,"depth":466,"text":370,"children":921},[922,923,924,925],{"id":374,"depth":491,"text":375},{"id":513,"depth":491,"text":514},{"id":523,"depth":491,"text":524},{"id":653,"depth":491,"text":654},{"id":744,"depth":466,"text":745},{"id":754,"depth":466,"text":755},{"id":761,"depth":466,"text":762},{"id":791,"depth":466,"text":792},{"id":819,"depth":466,"text":820},{"id":878,"depth":466,"text":879},"How consent management platforms affect LCP, INP and CLS, and the loading, rendering and tag-release changes that reduce their cost without compromising compliance.","md",{"slug":935,"type":936,"breadcrumb":937,"datePublished":945,"dateModified":945},"reducing-consent-management-platform-cost","article",[938,941,942,943],{"name":939,"url":940},"Home","\u002F",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":944},"\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Freducing-consent-management-platform-cost\u002F","2026-10-06",true,"\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Freducing-consent-management-platform-cost",{"title":949,"description":950},"Reducing Consent Management Platform (CMP) Cost","Consent banners load early, block tags and run on every page. Self-host the CMP, render the banner server-side and defer tag release to keep LCP and INP healthy.","javascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Freducing-consent-management-platform-cost\u002Findex","wJw1zLvCvzTKMhGXn2X-HrhXDmfQDoKM0uPMtx5spAo",[954,958],{"title":955,"path":956,"stem":957},"Partytown vs Async Script Loading for Tag Managers","\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Fpartytown-vs-async-script-loading-for-tag-managers","javascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Fpartytown-vs-async-script-loading-for-tag-managers\u002Findex",{"title":959,"path":960,"stem":961},"Replacing YouTube Embeds with a Facade","\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Freplacing-youtube-embeds-with-a-facade","javascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Freplacing-youtube-embeds-with-a-facade\u002Findex",1791308076525]