You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Image parser uses a data: placeholder from data-src as the image URL, so the real src misses srcset enhancement #1186
When an image has a lazy-load attribute that holds a data: placeholder before its real src, the image parser takes the placeholder as the image's URL. The tag replacer then works on that placeholder instead of the real image, so the image never gets the page profiler's missing-srcset / sizes entries.
The same image with src first, or without the data-src, is enhanced normally.
Found by the QA agent while testing #1184 / #1185. It also happens on development, so it isn't caused by #1185.
What happens
Optml_Manager::parse_images_from_html() (inc/manager.php) matches the first src or possible_src_attributes() attribute it finds and returns its value as img_url. Here that's data-src, so img_url is data:image/gif.
Optml_Tag_Replacer::process_image_tags() goes ahead with that URL: can_replace_tag( 'data:image/gif' ) returns true.
The "optimized" URL for data:image/gif is the placeholder itself, so add_missing_srcset_attributes() builds every candidate from it. esc_url() turns each one into an empty string, and nothing is added.
The real src is still moved to the CDN by the later URL replacement pass. Only the tag-level work is done against the wrong URL.
The image also gets data-opt-id computed from the placeholder URL (get_id_by_url( 'data:image/gif' )) instead of the real image. So every image with that placeholder shares one profiler ID.
Reproduction
PHPUnit, with profiler data seeded for the image (keyed by the real src ID and by the data-opt-id the browser profiler reports, assets/js/modules/srcset-detector.js:139):
Images whose markup puts a lazy-load data: placeholder attribute before src miss the profiler's responsive srcset / sizes.
Other per-tag work that uses img_url (crop and dimension handling, profiler IDs, possibly lazy-load decisions) runs against the placeholder. This needs checking.
Possible fix
When picking an image's URL, skip attributes whose value is a data: URI, so a real src is used. This changes what parse_images_from_html() returns, which feeds every image replacement. It needs its own tests across the replacer and lazy-load suites, and a check against possible_src_attributes() integrations.
When an image's lazy-load attribute holds a data: placeholder and comes before the real src, Optimole treats the placeholder as the image. Every such image gets the same data-opt-id, so the page profiler can't give it its own width, height or responsive srcset.
Requires: a site connected to Optimole, for the steps outside the links.
✅ Fixed: Images 1 and 2 have different IDs (443598161, 1527998280), Images 1 and 3 share one
In the links:
Steps 1 to 3 are already done, and the links open on the test page.
Optimole is connected with a placeholder account, so the images show as broken. Check the HTML, not the pictures.
The PR build still shows Optimole 4.2.17 on the Plugins screen.
Tools → QA Logs shows debug.log.
Reproduce on Optimole 4.2.17:
Pages → Add New Page, title it "Optimole placeholder test".
Add a Custom HTML block with three images, using any two image URLs from your Media Library (A and B) and this placeholder: data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
Right-click each image → Inspect, and note its data-opt-id.
Bug: Images 1 and 2 have the same data-opt-id (771715633), although they are different files. Image 3 has another ID, although it is the same file as Image 1.
Fixed: Images 1 and 2 have different IDs, and Images 1 and 3 have the same ID.
Edge cases
Optimole lazy load on: Images 1 and 2 lazy-load from their real photo, and the data-src placeholder is kept.
<img src="PLACEHOLDER" data-lazy-src="URL-A"> (another lazy-load plugin owns the image): same output as on 4.2.17, with no extra <noscript> copy.
<img data-src="PLACEHOLDER"> with no src: the page renders normally and the tag is left alone.
Upper case DATA-SRC="DATA:image/gif...": behaves like Image 1.
Live site, after a few logged-out visits: Image 1 gets the profiler's width, height and srcset, like an image without the placeholder.
QA agent — 🟢 Passing checks · Placeholder-first images now receive responsive metadata and real-image profiler IDs.
Placeholder-first images now receive srcset, sizes, dimensions, and IDs based on the real photo. The same pages reproduce the missing attributes and shared IDs on the base build. Lazy-load targets and existing third-party noscript structures also behaved as expected, and all four new tests passed on PHP 7.4 and 8.3. This used seeded connection and profile data; live profiler collection and CDN delivery were not verified.
Worth a human look
Review whether query-string variants should have distinct profiler IDs: exploratory parsing of photo-a.jpg?version=7&qa=1 returned the base URL while preserving the complete tag. The same src-first capture occurs on the base build; exact query capture is not specified by this
Checks (5 passed)
✅ On a published page with profiler measurements for the real image, a data: lazy-load placeholder before src does not prevent the image from receiving the real image's responsive srcset and sizes.
✅ Placeholder-first images receive dimensions from the real image's profiler record and a data-opt-id for that real image: different files have different IDs, and the same file has the same ID regardless of attribute order.
✅ With Optimole lazy load enabled, both placeholder-first src and placeholder-first data-lazy-src images are lazy-loaded from their real image URL while the original data-src placeholder is retained.
✅ Images owned by another lazy loader, with a data: src and a real data-lazy-src, retain their placeholder source and existing noscript structure without an extra Optimole noscript copy.
✅ The parser selects the real URL and preserves the whole tag for double quotes, single quotes, data-lazy-src, src-first and uppercase DATA-SRC/DATA: markup and supported source-attribute integrations; a tag containing only data: lazy attributes and no real source is left alone.
Activity
kushh23 commentedon Oct 20, 2026
🧪 QA steps and test links
When an image's lazy-load attribute holds a
data:placeholder and comes before the realsrc, Optimole treats the placeholder as the image. Every such image gets the samedata-opt-id, so the page profiler can't give it its own width, height or responsive srcset.Requires: a site connected to Optimole, for the steps outside the links.
data-opt-id="771715633", Image 3 (same file as Image 1) has a different onea9f9857443598161,1527998280), Images 1 and 3 share oneIn the links:
debug.log.Reproduce on Optimole 4.2.17:
data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==<img data-src="PLACEHOLDER" src="URL-A" alt="Image 1"><img data-src="PLACEHOLDER" src="URL-B" alt="Image 2"><img src="URL-A" data-src="PLACEHOLDER" alt="Image 3">data-opt-id.data-opt-id(771715633), although they are different files. Image 3 has another ID, although it is the same file as Image 1.Edge cases
data-srcplaceholder is kept.<img src="PLACEHOLDER" data-lazy-src="URL-A">(another lazy-load plugin owns the image): same output as on 4.2.17, with no extra<noscript>copy.<img data-src="PLACEHOLDER">with nosrc: the page renders normally and the tag is left alone.DATA-SRC="DATA:image/gif...": behaves like Image 1.Fix: #1190 (open)
pirate-bot commentedon Oct 20, 2026
QA agent — 🟢 Passing checks · Placeholder-first images now receive responsive metadata and real-image profiler IDs.
Placeholder-first images now receive srcset, sizes, dimensions, and IDs based on the real photo. The same pages reproduce the missing attributes and shared IDs on the base build. Lazy-load targets and existing third-party noscript structures also behaved as expected, and all four new tests passed on PHP 7.4 and 8.3. This used seeded connection and profile data; live profiler collection and CDN delivery were not verified.
Worth a human look
Checks (5 passed)
Full report, evidence and session trail
Don't take a data: placeholder in a lazy-load attribute as the image …