Releases: nrdmartinezz/CoreBoost
Release list
CoreBoost v3.3.10
🐛 Fixed - wp-core-shim Script Delayed Preload Discovery
- Moved
inject_wp_core_shims()hook fromwp_headpriority0to priority3 - The shim script was the first element output in
<head>, pushing all preload/preconnect<link>tags lower in the HTML and delaying browser preload scanner discovery - New head order: preloads + preconnects (priority 1) → jQuery/font preloads (priority 2) → shim script (priority 3) →
wp_print_scripts(priority 8) - Shim still fires well before after-inline-scripts (priority 8), preserving
wp.i18n/wp.hooks/wp.domReadyqueue behaviour
CoreBoost v3.3.9
🔄 Reworked - cb-lcp Strategy: Preload-Only (Remove <img> Injection)
Root Cause Analysis
The <img> injection approach was based on a false premise. Elementor's video background
fallback image is applied as style="background: url(...) 50% 50%; background-size: cover;"
via server-side PHP (Group_Control_Background selectors). This means:
- The CSS background paints immediately without JS — it is not lazy-loaded or gated
on Elementor adding.e-lazyloaded. - The PSI "resource load delay" metric measures image discovery time, not paint-blocking
JS. The browser only discovers CSSbackground-imageURLs after downloading and parsing
the stylesheet — this is what causes the delay. - A
<link rel="preload" fetchpriority="high">in<head>is the direct and correct fix —
the preload scanner finds it during initial HTML tokenisation, before any CSS is fetched. - Injecting a
<img>as a child of the Elementor section was fighting Elementor's flex
layout unnecessarily, causing double-height sections on desktop and size/overlap issues
on mobile, with no benefit to the LCP metric.
Changes
inject_lcp_foreground_image()(Resource_Remover): removed<img>construction and
injection entirely. The function now only extracts the image URL (via the 4-level cascade)
and emits a<link rel="preload" as="image" fetchpriority="high">before</head>. The
section's opening tag is returned unmodified. No DOM changes, no layout impact.output_lcp_img_styles()(Hero_Optimizer): removed method andwp_headhook — no
<img>element exists to style.define_hooks(): removedoutput_lcp_img_stylesregistration.get_foreground_conversion_css():.cb-lcp-imgblock updated to note removal.
What Still Fires
preload_video_hero()atwp_headpriority 1 (via bothpreload_methoddispatch and the
unconditionalenable_lcp_foreground_injectionguard added in v3.3.7) — reads
_elementor_datafrom DB and emits the preload tag early.- Output-buffer preload fallback in
inject_lcp_foreground_image()— covers cases where
preload_video_hero()misses the URL (e.g. non-standard Elementor structures).
Files Modified
includes/public/class-resource-remover.php—inject_lcp_foreground_image()img injection removedincludes/public/class-hero-optimizer.php—output_lcp_img_styles()removed;define_hooks()updated
CoreBoost v3.3.8
🐛 Fixed - cb-lcp-img Causing Double Height on Desktop / Wrong Size on Mobile
Root Cause
enqueue_optimization_styles() registered .cb-lcp-img CSS via
wp_add_inline_style('wp-block-library', ...). On Elementor sites wp-block-library is
typically never enqueued, so WordPress silently discarded the inline style. Without
position: absolute; inset: 0; width: 100%; height: 100% the injected <img> rendered
as a normal block element — adding its full intrinsic dimensions to the section height
(doubling it on desktop) and appearing as an overlaid, under-sized image on mobile.
Additionally, the parent element needed an explicit position: relative guarantee. Elementor
sections are usually position: relative, but without an enforced rule the absolute positioning
had no reliable containing block.
Changes
output_lcp_img_styles()added (Hero_Optimizer) — newwp_headpriority-1 method that
outputs a<style id="coreboost-cb-lcp">tag directly into the document<head>. Bypasses
wp_enqueue_scriptsentirely, so the CSS is always delivered regardless of which stylesheets
are registered. Only runs whenenable_lcp_foreground_injectionis on and not in admin/preview.- CSS rules:
.cb-lcp { position: relative !important; overflow: hidden; }and
.cb-lcp-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; pointer-events: none; display: block; }. The!importantonposition: relative
prevents any theme or Elementor rule from stripping the containing-block guarantee. define_hooks()— wiredoutput_lcp_img_stylesatwp_headpriority 1.get_foreground_conversion_css()—.cb-lcp-imgblock emptied (styles now owned by
output_lcp_img_styles; legacy.hero-foreground-image/.heroimgrules unchanged).
Files Modified
includes/public/class-hero-optimizer.php—define_hooks(), newoutput_lcp_img_styles(),get_foreground_conversion_css()
CoreBoost v3.3.7
🐛 Fixed - LCP Preload Not Firing When preload_method Is Not video_hero
Root Cause
preload_video_hero() — which reads _elementor_data from the database and emits a
<link rel="preload" fetchpriority="high"> at wp_head priority 1 — was only called when
preload_method was explicitly set to video_hero or video_fallback. Sites using any
other preload method (e.g. automatic, css_class) received no <head> preload for the
video fallback image, causing the LCP resource load delay to remain.
Additionally, inject_lcp_foreground_image() Levels 1–3 could all miss when Elementor
applies the fallback background as an inline style via JavaScript (client-side) rather than
server-side PHP — so no URL was ever found and cb-lcp-img was not injected.
Changes
preload_hero_images()(Hero_Optimizer): after the normalpreload_methoddispatch,
always callspreload_video_hero()whenenable_lcp_foreground_injectionis on. This
implements Method A from the Manus AI research: an unconditionalwp_headpriority-1 preload
tied to theenable_lcp_foreground_injectionfeature flag.output_preload_tag()deduplication
prevents a double tag ifvideo_herois also the activepreload_method.inject_lcp_foreground_image()— Level 4 added (Resource_Remover): when Levels 1–3 all
fail, reads_elementor_datapost meta directly and scans the first 5 top-level Elementor
elements forbackground_video_fallback.url(thenbackground_image.url). This is the same
database-level lookup used bypreload_video_hero()and is immune to whether Elementor applies
the inline style via PHP or JS. Result cached in closure scope — DB query runs at most once
per page even when multiplecb-lcpelements are present.
Files Modified
includes/public/class-hero-optimizer.php—preload_hero_images()secondary dispatchincludes/public/class-resource-remover.php—inject_lcp_foreground_image()Level 4
CoreBoost v3.3.6
🐛 Fixed - LCP Foreground Injection (cb-lcp) Not Firing
Root Cause
inject_lcp_foreground_image() used a subcapture group for attribute extraction:
([^>]*\bclass=["\'][^"\']*\bcb-lcp\b[^"\']*["\'][^>]*). PCRE backtracking on the trailing
[^>]* could cause attributes such as data-coreboost-deferred-youtube or the inline style
to fall outside $matches[2], resulting in the function finding no image URL and silently
returning the original tag — so cb-lcp-img never appeared in the source.
A second cascading failure: even when smart_youtube_blocking was ON, the image URL was not being
found because Elementor applies the fallback as an inline CSS background on the wrapper element
(not in data-settings) and that path was never checked.
A third latent bug: start_output_buffer() only ran the output buffer when smart_youtube_blocking
or a script/CSS defer feature was active. If only enable_lcp_foreground_injection was on,
the buffer never started and injection never ran.
Changes
inject_lcp_foreground_image()fully rewritten. Outer regex simplified to
/<[a-z][a-z0-9]*\s[^>]*\bcb-lcp\b[^>]*>/i— no subcapture groups. All four attribute
extractions run directly on$matches[0](the full opening tag string), eliminating the
PCRE backtracking failure mode entirely.- 3-level image URL cascade:
data-settingsJSON →background_video_fallback.urlthenbackground_image.url
(present when smart_youtube_blocking is OFF).data-coreboost-deferred-youtubeJSON →fallback.url/fallback(string)
(present when smart_youtube_blocking has stripped data-settings).- Inline
styleattribute — per Elementor's architecture, the video fallback is
rendered asstyle="background: url('...') 50% 50%; background-size: cover;"on the
wrapper element by theGroup_Control_BackgroundCSS selector. This level is always
present in the rendered HTML and was previously never read.
<link rel="preload">now injected directly frominject_lcp_foreground_image(). After
thepreg_replace_callbackpass, the first resolved image URL is injected as a
<link rel="preload" fetchpriority="high">before</head>. This makes the head preload
independent ofHero_Optimizer::preload_video_hero()and thepreload_methodsetting —
so it fires correctly regardless of which hero detection method is configured.start_output_buffer()gate extended to include
!empty($this->options['enable_lcp_foreground_injection']). Previously the output buffer
only ran when a script/CSS defer or smart_youtube_blocking feature was also active; disabling
those features would silently prevent LCP injection from running at all.
Files Modified
includes/public/class-resource-remover.php—inject_lcp_foreground_image()full rewrite;start_output_buffer()buffer-start condition
CoreBoost v3.3.5
🐛 Fixed - LCP Resource Load Delay & Critical Request Chain
LCP Resource Load Delay (cb-lcp + YouTube video backgrounds)
inject_lcp_foreground_image()now reads the fallback URL fromdata-coreboost-deferred-youtubewhendata-settingshas been cleared.process_inline_assets()callsremove_youtube_background_iframes()first, which stripsbackground_video_fallbackout ofdata-settingsand moves it into thedata-coreboost-deferred-youtubeattribute. The subsequentinject_lcp_foreground_image()call then saw only{"background_background":"video"}indata-settings— no image URL — so no<img fetchpriority="high">was injected into the LCP element. Without that native<img>the browser had no early signal to start fetching the fallback image, resulting in the 1,260 ms LCP resource load delay reported by PageSpeed Insights. The fix adds a secondary lookup: whendata-settingsyields no image URL, the function decodesdata-coreboost-deferred-youtubeand reads itsfallback.urlfield. This ensures the high-priority LCP<img>is always injected on video-background containers that carry thecb-lcpclass, moving LCP time from "resource load delay" into "resource load duration" where it belongs.
Critical Request Chain (dist/i18n.min.js)
wp.i18n/wp.hooks/wp.domReadycompatibility shim injected atwp_headpriority 0. Whenenable_wp_core_deferis on, thewp-i18n,wp-hooks, andwp-dom-readyscripts are deferred, but plugins like Elementor attachafter-inline-scripts (viawp_set_script_translations()/wp_add_inline_script(..., 'after')) that call e.g.wp.i18n.setLocaleData()synchronously — before the deferred modules execute — causing a TypeError. The newinject_wp_core_shims()method (hooked atwp_headpriority 0) installs aObject.definePropertysetter-based proxy on each global (wp.i18n,wp.hooks,wp.domReady). Inline callers see a lightweight stub that queues their calls; when the deferred module writes the real implementation to the property the setter fires, replays every queued call, then removes itself so the property behaves normally from that point.- Removed the
has_inline_scripts()guard from theenable_wp_core_deferdefer path. Previously, the presence of ANY inline script attached towp-i18n(including just localized data) blocked deferral entirely, leavingdist/i18n.min.jsas a render-blocking resource in the critical request chain. The shim now handles the safety concern, so the guard is removed and the scripts are always deferred whenenable_wp_core_deferis enabled. /dist/i18n,/dist/hooks,/dist/dom-readyremoved from URL-level skip list inget_url_exclusions(). The old broad patterns accidentally prevented Elementor's owndist/i18n.min.js(served under/plugins/elementor/) from being deferred bydefer_scripts_by_url. Replaced with full/wp-includes/js/dist/paths so only the actual WordPress core files are skipped at the URL level; Elementor's i18n bundle is now correctly deferred by the/elementor/pattern inshould_defer./wp-includes/js/dist/i18n,/wp-includes/js/dist/hooks,/wp-includes/js/dist/dom-readyremoved from the hard-coded$critical_wp_scriptsarray inprocess_inline_script_callback(). With the shim in place these scripts are safe to defer; the URL-level guard was redundant and was preventing URL-based deferral when the handle-based path didn't fire.
Files Modified
includes/public/class-resource-remover.php—inject_lcp_foreground_image(): fallback lookup fromdata-coreboost-deferred-youtube;get_url_exclusions(): tightened/dist/i18n|hooks|dom-readyskip patterns;process_inline_script_callback(): removedwp-i18n/wp-hooks/wp-dom-readyfrom$critical_wp_scriptsincludes/public/class-script-optimizer.php—define_hooks(): newwp_headpriority-0 hook; newinject_wp_core_shims()method;defer_scripts(): removedhas_inline_scripts()guard forenable_wp_core_deferhandles
CoreBoost v3.3.4
🐛 Fixed - Tag Manager Plain Text Output & GTM Detection Failure
document.importNode(template.content, true)replacestemplate.innerHTML+div.innerHTMLround-trip inoutput_delay_script(). Reading.innerHTMLfrom a<template>element serializes its inert DocumentFragment back to an HTML string. Re-assigning that string to adiv.innerHTMLre-parses it in the live (scripting-enabled) document, where<noscript>is treated as a raw-text element — its child<iframe>becomes a literal text node that renders as visible markup on the page.document.importNode(template.content, true)clones nodes directly from the inert fragment with no serialization, preserving<noscript>structure correctly. Applied to all three tag blocks (head, body, footer)..textContentreplaces.innerHTMLfor inline script content copies. When recreating<script>elements in the delay injector, content was read/written via.innerHTML. The HTML serializer encodes characters such as&(present in GTM's'&l='+lsnippet) to&, corrupting the script and causing Google Tag Assistant to fail to detect the tag. Switching to.textContentbypasses HTML serialization entirely.
Files Modified
includes/public/class-tag-manager.php—output_delay_script()head, body, and footer tag injection blocks
CoreBoost v3.3.3
🐛 Fixed - Tag Manager Breaking Google Analytics & Third-Party Scripts
<script type='text/template'>wrapper replaced with<template>for delayed head/body/footer tags. The HTML spec treats every<script>element as raw text terminated by the first</script>string it encounters, regardless of thetypeattribute. This caused the CoreBoost delay wrapper to be prematurely closed by the first</script>present inside a stored snippet (e.g. a GA4 / GTM tag that contains its own</script>). All content after that closing tag was emitted as loose, malformed HTML — breaking Google Analytics and any other multi-tag tracking snippets. Replacing the wrapper with a<template>element resolves this because<template>content is parsed as real HTML (not raw text), so inner</script>tags do not terminate the container.<template>is valid in<head>, its content is inert until explicitly moved, and it is universally supported.- Inline delay script updated to read
innerHTMLfrom<template>elements. The threeloadCoreBoostTags()content reads (headTags,bodyTags,footerTags) previously used.textContent || .innerText, which is the correct API for<script>raw text.<template>exposes its parsed document fragment via.innerHTML, so all three reads are updated accordingly.
Files Modified
includes/public/class-tag-manager.php—output_head_tags(),output_body_tags(),output_footer_tags()PHP wrappers;output_delay_script()JS content reads
CoreBoost v3.3.2
✨ Added - LCP Foreground Injection (cb-lcp)
cb-lcpCSS class convention for Elementor sections. Addcb-lcpto any Elementor section or container's Advanced → CSS Classes field. CoreBoost detects the class in the output buffer and injects an<img fetchpriority="high" loading="eager" class="cb-lcp-img">as the first child of that element. This gives the browser a native<img>LCP target, bypassing Elementor's lazy-load CSS gate (background-image: none !importantuntil.e-lazyloadedis added by deferred JS).- Image URL resolved from Elementor
data-settings. The injected<img>uses the element'sbackground_video_fallback.url(preferred — the image shown before/during video load) falling back tobackground_image.url. The<link rel="preload">emitted byHero_Optimizeris also updated to prefer the video fallback URL whencb-lcpis present, so preload and LCP element always point to the same file. .cb-lcp-imgCSS — absolutely positioned,inset: 0,width/height: 100%,object-fit: cover,z-index: 0,pointer-events: none. Sits behind Elementor's overlay (::before) and the video container without interfering with layout or interaction.- New setting:
enable_lcp_foreground_injection— checkbox under Hero Image & LCP Optimization. Off by default.
🐛 Fixed - Remove Unused CSS/JS Pattern Matching
remove_unused_styles()andremove_unused_scripts()now support the same pattern syntax as CSS/JS defer. Previously both methods did a strictwp_style_is()/wp_script_is()exact-handle lookup, so patterns likewidget-,elementor-post-, orswiper(which work in the defer fields) silently matched nothing. The methods now iterate$wp_styles->registered/$wp_scripts->registeredand apply the same four-tier matching: exact, trailing-dash prefix, wildcard (*), and partial/contains. Extracted into a sharedhandle_matches_pattern()helper.
Files Modified
includes/public/class-hero-optimizer.php—search_elementor_hero_advanced()cb-lcp detection;get_foreground_conversion_css().cb-lcp-imgrules;enqueue_optimization_styles()gateincludes/public/class-resource-remover.php—inject_lcp_foreground_image()new method + call inprocess_inline_assets();remove_unused_styles()/remove_unused_scripts()pattern matching rewrite; newhandle_matches_pattern()helperincludes/core/class-config.php—enable_lcp_foreground_injectionfield configincludes/class-coreboost.php—enable_lcp_foreground_injectionruntime defaultincludes/class-activator.php—enable_lcp_foreground_injectioninstall defaultincludes/core/class-migration.php—enable_lcp_foreground_injectionmigration defaultincludes/admin/class-settings-registry.php— LCP Foreground Injection field registeredincludes/admin/class-settings-sanitizer.php— added to boolean list and hero field mapincludes/admin/class-settings-page.php— added to hidden-fields preservation listincludes/admin/class-cache-page.php— added to preserved fields list
CoreBoost v3.3.1
🐛 Fixed - Smart YouTube Blocking Never Activating & Video Hero Ignoring Page-Specific Images
smart_youtube_blockingruntime defaults corrected. The v3.3.0 fix only updatedclass-config.php, which drives the admin settings UI field default — not the actual option values used at runtime.class-activator.php(fresh installs),class-coreboost.php(runtime merge fallback), andclass-migration.php(merge_option_defaults()) all still hadfalse. Becausearray_replace($defaults, $saved_options)always lets the saved DB value win, any site installed before the option existed hadfalsepersisted in the database and the feature never ran despite appearing enabled. All three runtime defaults are nowtrue, and a newmigrate_to_3_3_1()step explicitly writestrueintocoreboost_optionsfor every site upgrading from < 3.3.1.- Page-specific image overrides now respected in
video_heropreload mode.preload_video_hero()went straight to Elementor data detection without first consulting thespecific_pagessetting, so any manual override entered in the page-specific images field was silently skipped. The method now checksspecific_pagesfirst — emitting the override preload and returning early — before falling through to Elementor fallback detection. Matches the behaviour ofpreload_automatic().
Files Modified
includes/class-activator.php—smart_youtube_blockingdefaultfalse→trueincludes/class-coreboost.php—smart_youtube_blockingdefaultfalse→trueincludes/core/class-migration.php—smart_youtube_blockingdefaultfalse→true; newmigrate_to_3_3_1()migration stepincludes/public/class-hero-optimizer.php—preload_video_hero()now checksspecific_pagesoverrides before Elementor detection