Skip to content

upstream-sync: sync Prebid.js 11.26.0 → 11.27.0 - #111

Merged
khang-vu-ttd merged 14 commits into
masterfrom
prebid-sync-11.27.0
Aug 14, 2026
Merged

upstream-sync: sync Prebid.js 11.26.0 → 11.27.0#111
khang-vu-ttd merged 14 commits into
masterfrom
prebid-sync-11.27.0

Conversation

@openads-sync-bot

@openads-sync-bot openads-sync-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Prebid.js Sync: 11.26.011.27.0

📊 Run summary

This PR was auto-generated by the Sync with Upstream Prebid.js workflow.
Prebid 11.27.0 Release Page

Upstream diff: prebid/Prebid.js@11.26.0...11.27.0

✅ Applied Commits

  • 2e2d80422 | Mantis RTD: New RTD Module Added #15315
  • 0ab1ae0d4 | userId: Refactor PPID validation logic with official regex #15411
  • d587d7759 | Build system: turn off webpack's experiments.typescript #15412
  • 0e9138038 | Tercept Analytics Adapter: fix page view tracking for in-page (SPA) navigation #15383 (auto-resolved)
  • 48439f9b9 | Core: escape values interpolated into generated VAST XML #15407
  • 7329ea0c3 | Don't use group for listed browser #15345
  • ac8f4d9dc | Core: escape HTML-unsafe characters in encodeMacroURI macro names #15406
  • 952d08389 | Bump github/codeql-action from 4 to 4.37.3 #15424
  • 62c7c0a | Prebid Version Update (OpenAds Upstream Sync Bot)
  • 5738ac743 | dgkeywordsRtdProvider and sonobiBidAdapter: fix direct access to storage rule violations #15249 (bid adapter change) (only dgkeywordRtdProvider.js cherry-picked; sonobiBidAdapter.js not shipped)

⏭️ Skipped Commits

These commits were intentionally skipped because they made changes to files matching BidAdapter:

  • 80aa9516f | Increment version to 11.27.0-pre (unneeded changes)
  • b0415a964 | MGID Bid Adapter: populate bid request with MGID session props #15006 (bid adapter change)
  • 0b020c15f | Yieldmo Bid Adapter: remove dead Topics handling #15414 (bid adapter change)
  • 3073fbf9d | Teads Bid Adapter: forward the COPPA flag #15419 (bid adapter change)
  • 58c258b49 | Yieldmo Bid Adapter: guard getFloor, unmatched video imps, empty response body #15417 (bid adapter change)
  • ccd625038 | Adkernel Bid Adapter: remove obsolete aliases #15409 (bid adapter change)
  • 8b74ffa62 | AdSpirit Bid Adapter: fix Native ORTB handling #15420 (bid adapter change)
  • 6ff40de3b | Reklamup Bid Adapter: update adapter #15361 (bid adapter change)
  • ea36e5eb6 | Prebid 11.27.0 release (will cause merge conflicts)

❌ Conflicting Commits (require manual resolution)

  • c4c72d48e | Build system: clean up runtime dependencies #15413
  • b1ebe342b | Gam integration: propagate viewurl from creatives #15318
  • 92441dfbf | CI: use bundled Safari for browser tests #15422
  • 72159ad09 | Build Dependencies: patch brace-expansion and js-yaml #15423

mantissolutions and others added 9 commits August 14, 2026 19:03
* Mantis RTD: New RTD Module Added

* Mantis RTD: Removed the use of window.location.href for page url

* Mantis RTD: Documentation improvements and segtax fix

* Mantis RTD: Documentation improvements

* Mantis RTD: Documentation improvements

* Mantis RTD: Updated Taxonomies for All Segment Groups

---------

Co-authored-by: Pramod Kumar <pramod.kumar@reachplc.com>
Co-authored-by: Patrick McCann <patmmccann@gmail.com>
* Refactor PPID validation logic with regex

Updated PPID validation to use regex for length and character checks.

* Remove trailing space

* Updated expected message in test
…avigation (#15383)

* Tercept Analytics Adapter: fix page view tracking for in-page (SPA) navigation

The adapter marked a page view (is_pl) only on the first auction after a
hard page load, using a firstSent flag that never reset. Sites that
navigate between articles or slides via history.pushState (SPA routing,
slideshow-style pagination) never trigger a new page load, so every
auction after the first was miscounted as a repeat view of the same page.

Replace firstSent with a lastPageUrl comparison in flush(): a page view is
now counted whenever the current URL differs from the URL of the last
counted auction, which correctly detects in-page navigations without
requiring a reload.

Also guard against an auction flushing with zero bids consuming the
page-load flag — an auction with no bids should not block the next real
auction on the same page from being counted as the page view.

* Tercept Analytics Adapter: bump version to v2.3.1

* Tercept Analytics Adapter: capture page URL at auction start, not at flush time

flush() read the current page URL when it ran, not when the auction was
created. With a delayed flush (analyticsBatchTimeout, or simply the
natural gap between AUCTION_INIT and AUCTION_END) an in-page navigation
could happen before an auction's beacon goes out, so the URL comparison
used to detect a new page view was reading the wrong page. Depending on
flush order across concurrent auctions this could drop a real page view
outright.

Capture the URL on the auction object when it is initialized instead, and
compare/store that value in flush(), so each auction is always attributed
to the page it actually ran on regardless of when — or in what order — it
flushes.

* Tercept Analytics Adapter: guard page-view tracking against out-of-order auction flushes

Auctions can flush in a different order than they started in (independent
batch timers), so a slow auction from a page the visitor has since
navigated away from could flush after a newer page's auction and rewind
lastPageUrl, causing the current page to be double-counted or the stale
page to be wrongly credited with a page view. Each auction now records a
monotonic sequence number at AUCTION_INIT, and only an auction at least as
new as the most recently applied page state can update the tracked URL or
be marked as a page view.

Also stopped deriving auctionInit.host/path/search from the live window
location at send time — an in-page navigation between an auction starting
and its (possibly delayed) flush could attribute the auction to the wrong
page. These fields are now derived from the same URL captured at auction
start that drives the is_pl decision.
* Core: escape values interpolated into generated VAST XML

Prebid builds VAST XML by string concatenation in two places, and both placed
untrusted values into the document without escaping them.

`wrapURI` in src/videoCache.ts and `getUrlNode` in vastXmlBuilder.js wrapped
tracker and ad tag URLs in `<![CDATA[...]]>`. A CDATA section ends at the first
`]]>`, so a URL containing that sequence closed the section early and the rest
of it was parsed as markup - enough to add a sibling element, for instance a
second `<Impression>` pointing somewhere else. `getOpeningLabel` in
vastXmlBuilder.js interpolated attribute values with no escaping at all, so a
value containing a double quote closed the attribute and could add another.
`wrapURI` had the same problem for the `event` attribute of `<Tracking>`.

Add `cdata` and `attributeValue` to a new src/utils/xml.ts and use them at both
sites. `cdata` splits `]]>` across two adjacent sections, which a parser reads
back as the original text, so no tracker is dropped or altered. Values that
contain none of these characters are emitted exactly as before, which keeps the
generated documents byte for byte identical for ordinary input; building the
documents with DOM APIs instead would have been safe by construction but changes
the serialised form, since empty elements collapse to `<Creatives/>`.

Attribute names are not escaped. Every name in these builders is a literal, and
a name taken from input would need validating against the XML Name grammar,
which escaping cannot do; the constraint is noted where the names are assembled.

Also drop the comment in wrapURI that discounted this, which reasoned that the
VAST URL is bidder controlled in any case. That covers the URL it was written
for, but not the tracker values, which can come from analytics modules through
`registerVastTrackers`.

npx eslint src/utils/xml.ts src/videoCache.ts
libraries/video/shared/vastXmlBuilder.js and both changed specs - clean.
npx tsc --noEmit --strict src/utils/xml.ts - clean.
npx gulp test --nolint --file, all passing: videoCache_spec 33, vastXmlBuilder
19, vastXmlEditor 11, videoImpressionVerifier 3, vastTrackers 22,
gamAdServerVideo 94. Each set of added tests was confirmed to fail with its
source change reverted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Tests: cover structural injection in DOM-built VAST XML

The VAST builders that use DOM APIs rather than string concatenation cannot
have their document structure altered by the values they place in it, but
nothing asserted that, so rewriting one of them with string templates would
have passed every existing test.

`insertVastTrackers` gets six tests. Four place a value containing `]]>` or a
double quote in an impression url, an error url, a tracking event url and a
tracking event name, and check that no element or attribute appears beyond the
one the tracker describes. Two cover the fallback: vastXml with no Wrapper or
InLine element, and vastXml that cannot be parsed, are both returned unchanged.

The assertions read the parsed document rather than matching strings, so they
hold for any implementation that keeps the property. A value that cannot be
represented may be left out - which is what happens today, since
createCDATASection rejects `]]>` and the whole insertion is abandoned - so the
element count is asserted as at most one rather than exactly one. They were
checked by replacing insertVastTrackers with a string template implementation,
which failed all four of the injection tests.

gamAdServerVideo gets one test for the locally cached branch, where a bid's own
vastXml arrives through vastLocalCache as a blob and is placed in a CDATA
section. Note it does not fail if only the base64 encoding is dropped from
getBase64BlobContent, because createCDATASection then rejects the sequence on
its own; it covers the two steps together rather than either one.

The mock server responds to one request per call, and the second of the two
requests getVastXml makes is only issued once the first resolves, so responding
to both needs a wait. That was repeated inline in two tests and is now
respondToAdServerThenBlob.

npx eslint on both changed specs - clean.
npx gulp test --nolint --file: vastTrackers_spec 28, gamAdServerVideo_spec 95.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Core: note bot authorship of the VAST XML escaping helpers

Required by the repo guidelines in CLAUDE.md for changes proposed to
prebid/Prebid.js.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: dmytro-po <dmytro.po@intentiq.com>
…5406)

* Core: escape HTML-unsafe characters in encodeMacroURI macro names

encodeMacroURI located each already-encoded `${...}` span by building a search
needle with encodeURIComponent, then replaced it with the raw macro text. That
restored every character in the macro name, so a name containing `"`, `<`, `>`
or whitespace was emitted unescaped into the `src="..."` attribute built by
createTrackPixelHtml, which is enough to terminate the attribute and inject
another attribute or tag.

Emit the braces literally, as before, but percent-encode only the characters
that can break out of a double-quoted attribute value, leaving the rest of the
name byte-identical. Because the needle matching is gone, the encodeURI vs
encodeURIComponent divergence that decided which spans were restored no longer
applies; the macro pattern now excludes the characters those two encode
differently, so brace expressions that are not macros keep their current
encoded form.

Tests cover each unsafe character both inside and outside a macro, and assert
at the DOM level that the markup createTrackPixelHtml produces with this
encoder yields no extra element or attribute.

npx eslint src/utils.js test/spec/utils_spec.js - clean.
npx gulp test --nolint --file, all passing: utils_spec 207, ortbConverter
banner_spec 14, kimberlite 12, trustx 38/43, adkernel 45, deltaprojects 31,
taboola 95/101.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Core: encode macro names as UTF-8 in encodeMacroURI

HTML_UNSAFE_CHARS used `\s`, which matches 20 non-ASCII whitespace code
points in addition to ASCII whitespace, and percentEncode escaped them
with charCodeAt, i.e. per UTF-16 code unit rather than per UTF-8 byte.
The resulting escapes are well-formed but decode to something else: a
macro name containing U+2000 came out as `%2000`, which decodes to a
space followed by a literal `00`, while U+00A0 and U+FEFF produced `%A0`
and `%FEFF`, which throw URIError on decode.

Spell the ASCII whitespace out instead. None of the non-ASCII whitespace
can terminate a double-quoted attribute value, so leaving it alone keeps
a macro name byte-for-byte wherever escaping is not required. Replace
percentEncode with encodeURIComponent so that the escape is correct for
any character, and the character class stays a policy knob.

Also correct the comment above the class: encodeURI does not leave these
characters alone, it encodes all of them. They need explicit handling
because a macro name bypasses encodeURI, its braces being emitted
literally so that downstream substitution can find them.

Tests cover six representative non-ASCII whitespace code points, each
asserting passthrough inside a macro and that the output survives
decodeURIComponent unchanged, and add vertical tab to the HTML_UNSAFE
table, which listed nine of the ten characters the class covers.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Core: match encodeMacroURI macros without shared regex state

The macro pattern is a module-level /g regex, and exec advances lastIndex
on the object it is called on. The loop was self-cleaning on the happy
path, since the final exec returns null and resets lastIndex to 0, but a
call that could not finish left the offset behind: encodeURI throws
URIError on a lone surrogate, and when one sits before a macro the throw
happens after exec has already advanced. The next call then began its
scan mid-URL, missed its macro, and percent-encoded the braces, so
${AUCTION_PRICE} came out as $%7BAUCTION_PRICE%7D and price substitution
silently stopped working.

buildBidResponse catches and logs per bid, so the throwing bid was
skipped loudly while every later banner bid carrying an nurl was
corrupted with no further error logged.

Iterate with matchAll, which matches against a copy, so the shared
pattern is never mutated and there is no offset to carry over. This also
leaves no defensive line whose removal would quietly reintroduce the
problem.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Core: assert encodeMacroURI escapes exactly, and cover the macro pattern

The escaping tests asserted only that the unsafe character was absent
from the output, which any transform that removes it satisfies. Escaping
a tab as '%9' instead of '%09' passed, even though the following
character is then read as part of the escape and `${A<tab>B}` collapses
to the single byte 0x9B; so did deleting the character outright. Assert
the escape exactly instead.

The set of characters excluded from a macro name had no coverage at all,
though it is what keeps a brace expression that is not a macro encoded
the way it was before macro names were escaped. Widening it to `[^}]+`
passed the whole suite. Add a case per excluded character.

Drop the six round-trip cases over non-ASCII whitespace: the URLs they
build contain no percent sign, so decodeURIComponent is the identity over
them and the assertion held whenever the exact-output assertion above it
did.

Correct two comments. Of the characters escaped inside a macro name only
the double quote can close the attribute value createTrackPixelHtml
writes; the others are escaped because the URL is not guaranteed to land
in a double-quoted attribute, and because they do not belong in a URI.
The macro name is passed through except for HTML_UNSAFE_CHARS, which is
narrower than "characters that are unsafe in HTML markup" - the single
quote and ampersand are not escaped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Patrick McCann <patmmccann@gmail.com>
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4 to 4.37.3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@v4...v4.37.3)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.37.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

This PR includes an adapter whose code does not match its file name. Bid adapter modules should be named <bidderCode>BidAdapter, userId <userIdCode>IdSystem, RTD <rtdCode>RtdProvider, and analytics <analyticsCode>AnalyticsAdapter.

@github-actions

Copy link
Copy Markdown
Contributor

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 modules/mantisRtdProvider.ts may need:
    • es.array.push
    • es.iterator.constructor
    • es.iterator.filter
    • es.iterator.map
    • es.iterator.reduce
    • esnext.iterator.constructor
    • esnext.iterator.filter
    • esnext.iterator.map
    • esnext.iterator.reduce
    • esnext.json.parse
    • web.url-search-params.delete
    • web.url-search-params.has
    • web.url-search-params.size
  • Changes to test/spec/libraries/vastTrackers_spec.js may need:
    • es.iterator.constructor
    • es.iterator.for-each
    • esnext.iterator.constructor
    • esnext.iterator.for-each
  • Changes to test/spec/modules/mantisRtdProvider_spec.js may need:
    • es.array.with
    • es.iterator.constructor
    • es.iterator.find
    • es.iterator.for-each
    • es.iterator.map
    • es.json.stringify
    • esnext.array.with
    • esnext.iterator.constructor
    • esnext.iterator.find
    • esnext.iterator.for-each
    • esnext.iterator.map
  • Changes to test/spec/utils_spec.js may need:
    • es.iterator.map
    • esnext.iterator.map

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

@khang-vu-ttd

Copy link
Copy Markdown
Contributor

Moved `b3ce02a9f` (upstream `5738ac743`, `#15249`) from Skipped to Applied — it was auto-classified as adapter-only (bundled with a `sonobiBidAdapter.js` change, which isn't shipped here), but it also fixes a real storage-compliance gap in our shipped `dgkeywordRtdProvider.js`: replaces a raw `window.localStorage.getItem(...)` call (flagged with its own `TODO: use storageManager` / `eslint-disable-next-line no-restricted-properties`) with the proper `storageManager.getDataFromLocalStorage(...)` API. Cherry-picked just the `dgkeywordRtdProvider.js` hunk; the `sonobiBidAdapter.js` modify/delete conflict resolved by keeping our side's deletion (adapter not shipped).

patmmccann and others added 4 commits August 14, 2026 12:35
* Support GAM view tracking URL (viewUrl) end-to-end and add API to fire it

- Add support for a GAM-provided view tracking URL (`viewUrl`) so creatives can pass a view impression endpoint to Prebid for later firing.
- Provide a public API to trigger firing of the stored `viewUrl` by ad unit code or ad ID.

- Cross-domain renderer: added `parseRenderArgs` and updated `renderer` to accept `viewUrl` (supports both object-style and positional GAM args) and send `viewUrl` in the `Prebid Request` options.
- Examples/build: updated `integrationExamples/gpt/x-domain/creative.html` to include `viewUrl` in the generated creative payload and support the new positional argument parsing.
- Data model/types: added `viewUrl?: string` to bid response interface in `bidfactory.ts` so the URL can be stored on bids.
- Rendering pipeline: propagate `viewUrl` from `render` options into the `bidResponse` in `adRendering.ts` so it is available post-render, and include it when calling `handleRender`.
- Public API: added `pbjs.fireViewUrlForAdUnitCode` which locates the matching winning bid by ad unit code or ad ID and fires `viewUrl` using the internal pixel trigger helper (`utils.internal.triggerPixel`).
- Tests and examples: updated and added unit tests and cross-domain creative tests to verify `viewUrl` is included in outgoing messages, stored on the bid, and fired via the new API.

- Updated unit and integration tests (`test/spec/creative/crossDomainCreative_spec.js`, `test/spec/unit/adRendering_spec.js`, `test/spec/unit/pbjs_api_spec.js`) were run and pass in the test suite.
- Existing rendering and message handling tests were exercised to ensure no regressions in creative rendering and messaging; all automated tests succeeded.

* Add support for GAM viewUrl: propagate from creatives and allow firing via API

- Allow GAM creatives to supply a view tracking URL (`viewUrl`) that needs to be passed from cross-domain creatives into the renderer and stored on the winning bid for later firing.
- Support both object and legacy positional argument forms of `pbRender` so `viewUrl` can be supplied by existing publishers.
- Provide a small API to let publishers fire the stored GAM view URL on demand (by ad unit code or ad id).

- Cross-domain renderer: added `parseRenderArgs` to accept either an object or positional args, and include `viewUrl` in the message `options` sent to the parent (`creative/crossDomain.js` and minified integration example).
- Rendering pipeline: added optional `viewUrl` to render option types and propagate `viewUrl` into the `bidResponse` before render hooks run in `handleRender`, and pass `viewUrl` through calls that originate rendering (`adRendering.ts`).
- Types and models: added `viewUrl?: string` to the base bid response interface (`bidfactory.ts`).
- Public API: added `pbjs.fireViewUrlForAdUnitCode` which locates the current winning bid by ad unit code or ad id and fires the stored `viewUrl` using the internal `triggerPixel` helper (`prebid.ts`).
- Tests and examples: updated integration example and unit tests to cover `viewUrl` propagation, positional argument support, and firing behavior.

- Unit tests updated and run: `cross-domain creative` spec (`test/spec/creative/crossDomainCreative_spec.js`), `adRendering` spec (`test/spec/unit/adRendering_spec.js`), and `pbjs_api` spec (`test/spec/unit/pbjs_api_spec.js`) which include new cases for `viewUrl` handling and `pbjs.fireViewUrlForAdUnitCode` behavior, and all passed.
- Existing test suite was executed and the modified test cases succeeded.

* Add support for GAM viewUrl on bids

* pass every extra argument (not positionally)

* Update generated x-domain example

---------

Co-authored-by: Demetrio Girardi <dgirardi@prebid.org>
* Build system: do not publish compiled tests

* Build system: move unnecessary runtime dependencies to devDependencies

* Build system: lint for undeclared runtime dependencies

* Build system: make eslint aware of typescripts resolution logic
* CI: use bundled Safari for browser tests

* CI: align native Safari configuration
* Update package-lock.json

* Update package-lock.json
@khang-vu-ttd

Copy link
Copy Markdown
Contributor

Conflicting commits resolved

b1ebe342b — Gam integration: propagate viewurl from creatives (#15318) → 9da6e069d

Source (creative/crossDomain.js, src/prebid.ts, src/adRendering.ts, src/bidfactory.ts, and their specs) merged cleanly — upstream changed the render-options destructuring from an explicit { adId, pubUrl, clickUrl } to a rest-spread { adId, pubUrl, ...rest } so any additional properties (like the new viewUrl) pass through instead of being silently dropped.

The only conflict was in the checked-in, autogenerated integrationExamples/gpt/x-domain/creative.html — its inline <script> is a minified bundle embedding the OpenAds-renamed strings ("OpenAds Event", "OpenAds Request", etc.), which don't exist upstream, so the two versions' minified output couldn't merge textually. Rather than hand-editing minified JS, I regenerated it the way the project's own build-release gulp task does (updateCreativeExample): ran npx gulp precompile to rebuild build/creative/creative.js from the merged source, then wrote that output back into the example file. Confirmed the regenerated bundle carries both the OpenAds naming and the new rest-spread/viewUrl behavior.

c4c72d48e — Build system: clean up runtime dependencies (#15413) → 9cbe972ee

eslint.config.js, gulpfile.js, package.json, and src/types/local/gpt.d.ts merged cleanly. Only package-lock.json conflicted — resolved with the standard lockfile pattern (git checkout --theirs + npm install to reconcile), which also picked up the import/no-extraneous-dependencies ESLint rule and eslint-import-resolver-typescript dependency this commit adds.

92441dfbf — CI: use bundled Safari for browser tests (#15422) → 8b94c6275

.github/workflows/browser-tests.yml, .github/workflows/browser_testing.json, and wdio.local.conf.js merged cleanly (renaming install-safariconfigure-safari, safari technology previewsafari). The only conflict was in .github/workflows/run-tests.yml's "Configure Safari" step, where our fork's brew install --cask safari-technology-preview lines no longer apply — removed them to match upstream's move to CI-bundled Safari, keeping the defaults write/safaridriver --enable lines that still apply regardless of which Safari is used.

Note: upstream's own PR description says "Do not merge" even though it was in fact merged upstream — flagging that here in case it affects how this is reviewed. Also worth noting this is directly related to the Safari E2E timing bug fixed in PR #110 (permutiveCombined_spec.js expiry-freezing issue) — using bundled Safari instead of Safari Technology Preview may also reduce flakiness from that class of issue on real CI runners.

72159ad09 — Build Dependencies: patch brace-expansion and js-yaml (#15423) → 087ff316c

package-lock.json-only change (security patch versions for transitive brace-expansion/js-yaml). Resolved with the same lockfile pattern as above.

@khang-vu-ttd
khang-vu-ttd merged commit 20612e4 into master Aug 14, 2026
103 checks passed
@khang-vu-ttd
khang-vu-ttd deleted the prebid-sync-11.27.0 branch August 14, 2026 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants