Skip to content

Core: add public removeUserSyncs() to remove user sync iframes - #15380

Open
Pubstream wants to merge 3 commits into
prebid:masterfrom
Click-Performance-GmbH:master
Open

Core: add public removeUserSyncs() to remove user sync iframes#15380
Pubstream wants to merge 3 commits into
prebid:masterfrom
Click-Performance-GmbH:master

Conversation

@Pubstream

Copy link
Copy Markdown
Contributor

Type of change

  • Feature

Description of change

User sync iframes are appended to and never cleaned up, so in a single page application they keep accumulating for as long as the user stays on the page without a reload.

Every sync iframe is now marked with a data-pb-usersync attribute when it is inserted, and pbjs.removeUserSyncs() removes all of them from the document, returning how many were removed. As insertUserSyncIframe is the single entry point for sync iframes, this also covers the syncs fired by the Prebid Server adapter and by modules inserting their own frames.

Removal is a pure DOM cleanup: the sync queue and the userSync config are left untouched, so syncs registered afterwards insert new iframes as usual and the call can be repeated on every route change. Image pixels are unaffected, they never enter the DOM.

@barecheck

barecheck Bot commented Jul 23, 2026

Copy link
Copy Markdown

Barecheck - Code coverage report

Total: 96.59%

Your code coverage diff: 0.00% ▴

Uncovered files and lines
FileLines
src/prebid.ts146, 186, 189, 212-215, 251, 306-311, 351-352, 359-360, 413, 582, 590-591, 631-633, 636-637, 935, 944-946, 950-951, 980, 1035, 1052-1053, 1055, 1063-1064, 1066, 1071, 1156, 1207, 1275, 1325-1326
src/userSync.ts136, 176, 196, 275
src/utils.js48, 85, 392, 408-409, 421, 457, 482, 542, 575, 584, 601-602, 630-631, 705, 741, 745, 844-846, 925, 973, 1014, 1019, 1023-1024, 1174, 1210, 1215, 1242, 1248
test/spec/utils_spec.js337-338, 672, 1300, 1339, 1356

@patmmccann

Copy link
Copy Markdown
Collaborator

in a single page application they keep accumulating for as long as the user stays on the page without a reload.

we set our sync frame limits to one, do you do the same? it seems like a bug they are accumulating indefinitely

do you think we should automatically clean up the dom?

@patmmccann
patmmccann requested a review from dgirardi July 23, 2026 14:37
Comment thread src/utils.js Outdated
* @return {Number} the number of iframes that were removed
*/
export function removeUserSyncIframes() {
const iframes = document.querySelectorAll(`iframe[${USERSYNC_ATTR}]`);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will cause side effects when multiple pbjs instances are on the same page.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sync iframes are now tagged with the name of the Prebid global that inserted them
(data-pb-usersync="pbjs"), and removeUserSyncs() only removes iframes matching its own
instance, so pbjs and pbjs2 no longer interfere with each other. Test added for it.

Tag each sync iframe with the name of the Prebid global that inserted it, so
that removeUserSyncs() only removes its own iframes when several instances run
on the same page.
@patmmccann patmmccann changed the title add pbjs.removeUserSyncs() to remove user sync iframes Corey: add public removeUserSyncs() to remove user sync iframes Aug 4, 2026
@patmmccann patmmccann changed the title Corey: add public removeUserSyncs() to remove user sync iframes Core: add public removeUserSyncs() to remove user sync iframes Aug 4, 2026
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

This PR introduces changes that may not work on all browsers. According to Babel, the following polyfills may be needed, and they are not automatically included:

  • Changes to test/spec/utils_spec.js may need:
    • es.iterator.filter
    • es.set.difference.v2
    • es.set.intersection.v2
    • es.set.is-disjoint-from.v2
    • es.set.is-subset-of.v2
    • es.set.is-superset-of.v2
    • es.set.symmetric-difference.v2
    • es.set.union.v2
    • esnext.iterator.filter
    • esnext.set.difference.v2
    • esnext.set.intersection.v2
    • esnext.set.is-disjoint-from.v2
    • esnext.set.is-subset-of.v2
    • esnext.set.is-superset-of.v2
    • esnext.set.symmetric-difference.v2
    • esnext.set.union.v2

The best way to address this is to provide good test coverage, as normal PR checks run unit tests on older browsers.

@Pubstream
Pubstream requested a review from derdeka August 4, 2026 14:21
Comment thread src/utils.js Outdated
// the attribute value is not necessarily a valid CSS identifier, so it's matched here instead of
// in the selector
const iframes = Array.from(document.querySelectorAll(`iframe[${USERSYNC_ATTR}]`))
.filter(iframe => iframe.getAttribute(USERSYNC_ATTR) === getGlobalVarName());

@dgirardi dgirardi Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's possible for this to remove the wrong frames - if one builds prebid with defineGlobal: false, getGlobalVarName() still returns something - most likely the default pbjs - which could be used by another prebid instance on the page.

Would keeping track of the iframe elements themselves with a WeakSet work? if not, it'd be safer to generate a random identifier on startup to use as a tag.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, changed to WeakSet which track the real iframe elements

@patmmccann

Copy link
Copy Markdown
Collaborator

please pull master, your e2e tests ran on the wrong safari

@Pubstream

Copy link
Copy Markdown
Contributor Author

please pull master, your e2e tests ran on the wrong safari

I’m not sure what you mean by "wrong Safari", how can I control that? And which one would be the “right” Safari?

@patmmccann

Copy link
Copy Markdown
Collaborator

if you pull master, the e2e tests will run on a different version of safari bc the location of the safari binary it was trying to download for test runs failed

@patmmccann

Copy link
Copy Markdown
Collaborator

see #15422

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants