RTB Architecture
Dynamic creative optimization in HTML5: build pipelines, IAB specs, rendering and QA
Published · Last updated
Next scheduled review:
Dynamic creative optimization (DCO) in HTML5 means one template per ad size, filled at serve time from a data feed by rules. The engineering work is the pipeline around it: templates, feeds, file-weight budgets, IAB Tech Lab specs such as SIMID and Open Measurement, rendering checks in each ad server and automated QA.
Contents
Key facts
- The IAB budget for a 300x250 is 150 kB. The IAB New Ad Portfolio sets 150 kB for the initial load and 300 kB for the subload of a medium rectangle, gzipped. It allows at most ten file requests during the initial load (IAB Tech Lab, Fixed Size Ad Specifications, 2017).
- Chrome removes heavy ads. It unloads an ad the user has not touched once it uses more than 4 megabytes of network. The same happens above 15 seconds of main-thread time in any 30-second window, or 60 seconds in total (Chrome for Developers, updated 7 January 2026).
- DSPs add their own ceilings. Display & Video 360 caps an HTML5 ad at 5 MB of total download, 100 HTTP calls and 25 cookies, and limits animation to 30 seconds (Google, DV360 Help, accessed 9 November 2026).
- SIMID 1.2 is in the repository. IAB Tech Lab added a SIMID 1.2 document on 23 July 2026; the last tagged releases are 1.1 (25 January 2022) and 1.0 (28 June 2019) (IAB Tech Lab, SIMID repository).
- Open Measurement keeps shipping. The Open Measurement SDK JavaScript clients reached version 1.6.12 on 2 November 2026 (IAB Tech Lab, Open-Measurement-JSClients changelog).
- VAST 4.4 is still a draft. The VAST 4.4 text in IAB Tech Lab's repository says "Publication Date TBD"; VAST 4.3 is dated December 2022 (IAB Tech Lab, VAST4.x repository).
Definition
DCO HTML5 pipeline: the build, data and release process that turns one HTML5 creative template per size into many ad variations by binding template slots to rows of a content feed through targeting rules. It also tests every variation against publisher, platform and browser limits before the ad serves.
Dynamic creative optimization (DCO) as a marketing method, with strategy and examples, is covered in dynamic creative optimization strategies. This page is the engineering view and sits in the RTB architecture hub. It assumes you know what an ad server and a demand-side platform (DSP) do.
How a DCO pipeline works: template, feed, rules, render
A DCO system has four parts. The template is an HTML5 shell with named slots for text, images, prices and links. The feed is a table of content, one row per variation. Rules pick a row for each impression from signals such as location, audience or placement. The renderer fills the slots and shows the ad.
Google's Studio, which serves dynamic creatives through Campaign Manager 360 (CM360), uses the same split. A dynamic creative is "an HTML creative file" that frames the content, plus a Studio profile holding the rules and the mapping between creative elements and content (Google, Studio Help, accessed 9 November 2026). Google states that these dynamic creatives are available for CM360 users and not for Google Ad Manager.
The split matters for testing. A template is code, so it gets code checks once per release. A feed is data, so every update needs data checks, because one long product name can break a layout across thousands of impressions.
Templates: an HTML5 shell that survives every ad server
Build each template as a small, self-contained web page. The IAB's ad portfolio guidance says HTML5 ads "are like mini web pages" and that the number of file requests has a big effect on load performance (IAB Tech Lab, 2017). The same document recommends inline styles, asynchronous scripts inside a sandboxed iframe and no animation while the ad is out of view.
Four rules keep a template portable across ad servers and DSPs:
- One package per size. DV360 expects a ZIP of HTML, CSS, JS, image and font files, up to 100 files (Google, DV360 Help).
- A readable clickTag. DV360 requires click tags for the landing page and warns, "Don't use a code minifier on the click tag." The landing page must open in a new tab or window.
- Polite loading. Load only what the first frame needs before the page's
loadevent. Fetch the rest afterwards, as the LEAN rules require. - No reliance on the host page. The ad runs in a cross-origin iframe in most environments, so it cannot read the publisher's DOM or cookies.
Shared libraries need a decision. The IAB lets publishers exempt named shared libraries from the weight count, up to 50 kB combined in the initial load. Any library a publisher has not named counts in full (IAB Tech Lab, 2017). Bundle a small library rather than gamble on an exemption you have not confirmed.
Feeds and rules: the data contract
A feed is a contract between the people who write content and the template that displays it. Write the contract down: field names, types, maximum lengths, image sizes and the default row. The row below is our illustrative format, not a Google Studio or vendor schema.
{
"row_id": "sku-48213-uk",
"is_default": false,
"active_from": "2026-11-10T00:00:00Z",
"active_to": "2026-11-30T23:59:59Z",
"targeting": { "country": "GB", "audience_segment": "returning_visitor", "placement_size": "300x250" },
"headline": "Winter boots, 30% off",
"headline_max_chars": 28,
"price": { "amount": 69.0, "currency": "GBP", "display": "£69" },
"image": { "url": "https://cdn.example.com/dco/boots-600x500.webp", "width": 600, "height": 500, "max_kb": 45 },
"cta_text": "Shop now",
"exit_url": "https://shop.example.com/boots?utm_source=display",
"reporting_label": "boots_winter_returning"
}7 of 7 rows
| One row must be marked default. It serves when no rule matches. |
| Prices and offers expire; the rules engine must not serve stale rows |
| The signals the rules engine matches; keep keys identical to the ad server's targeting keys |
| The template's real limit, tested at build time against every row |
| Twice the display size for high-density screens, as DV360 recommends for images |
| Each row's weight counts toward the ad's load budget |
| Lets reports show which variation won without decoding row IDs |
is_default
- Why it exists
One row must be marked default. It serves when no rule matches.
active_from, active_to
- Why it exists
Prices and offers expire; the rules engine must not serve stale rows
targeting
- Why it exists
The signals the rules engine matches; keep keys identical to the ad server's targeting keys
headline_max_chars
- Why it exists
The template's real limit, tested at build time against every row
image.width, image.height
- Why it exists
Twice the display size for high-density screens, as DV360 recommends for images
image.max_kb
- Why it exists
Each row's weight counts toward the ad's load budget
reporting_label
- Why it exists
Lets reports show which variation won without decoding row IDs
Table by AdSovereign, CC BY 4.0.
Google's QA checklist for Studio shows why the default row matters. If the feed has no default column and no location matches, there is "no eligible content to serve", and CM360 picks another creative in the rotation (Google, Studio Help, accessed 9 November 2026). The same page warns that test IDs may work in preview "however they won't work when the creative is live". It tells teams to replace them, retransform the feed and republish the profile.
File-weight and load limits, side by side
Three bodies set limits on the same ad: the IAB recommends, browsers enforce and platforms reject. Your build budget must satisfy the strictest number at each point.
9 of 9 rows
Initial load, 300x250 | 150 kB gzipped | n/a | n/a |
Subload, 300x250 | 300 kB gzipped, after the page | n/a | n/a |
Initial load, 970x250 billboard | 250 kB, subload 500 kB | n/a | n/a |
Total network | Unlimited after user interaction | Ad unloaded above 4 MB without interaction | 5 MB maximum download |
File or HTTP requests | 10 in the initial load | n/a | 100 HTTP calls; 100 files in the ZIP |
CPU | 30% of average CPU per active ad | 15 s of main thread in any 30 s window, or 60 s in total | n/a |
Animation | Stop when complete; none while out of view | n/a | 30 seconds maximum |
Slow networks | 30% lighter on 3G or slower | n/a | n/a |
Not counted | Ad server, measurement and verification files | All resources of child frames count | n/a |
Initial load, 300x250
- IAB New Ad Portfolio (2017)
150 kB gzipped
- Chrome Heavy Ad Intervention
n/a
- DV360 HTML5 display
n/a
Subload, 300x250
- IAB New Ad Portfolio (2017)
300 kB gzipped, after the page
loadevent- Chrome Heavy Ad Intervention
n/a
- DV360 HTML5 display
n/a
Initial load, 970x250 billboard
- IAB New Ad Portfolio (2017)
250 kB, subload 500 kB
- Chrome Heavy Ad Intervention
n/a
- DV360 HTML5 display
n/a
Total network
- IAB New Ad Portfolio (2017)
Unlimited after user interaction
- Chrome Heavy Ad Intervention
Ad unloaded above 4 MB without interaction
- DV360 HTML5 display
5 MB maximum download
File or HTTP requests
- IAB New Ad Portfolio (2017)
10 in the initial load
- Chrome Heavy Ad Intervention
n/a
- DV360 HTML5 display
100 HTTP calls; 100 files in the ZIP
CPU
- IAB New Ad Portfolio (2017)
30% of average CPU per active ad
- Chrome Heavy Ad Intervention
15 s of main thread in any 30 s window, or 60 s in total
- DV360 HTML5 display
n/a
Animation
- IAB New Ad Portfolio (2017)
Stop when complete; none while out of view
- Chrome Heavy Ad Intervention
n/a
- DV360 HTML5 display
30 seconds maximum
Slow networks
- IAB New Ad Portfolio (2017)
30% lighter on 3G or slower
- Chrome Heavy Ad Intervention
n/a
- DV360 HTML5 display
n/a
Not counted
- IAB New Ad Portfolio (2017)
Ad server, measurement and verification files
- Chrome Heavy Ad Intervention
All resources of child frames count
- DV360 HTML5 display
n/a
Table by AdSovereign, CC BY 4.0.
Sources: IAB Tech Lab, Fixed Size Ad Specifications, 2017; Chrome for Developers, updated 7 January 2026; Google, DV360 Help, accessed 9 November 2026.
The IAB numbers changed over time. The 2015 display guidelines allowed 200 KB for a 300x250 and 15 file requests, with subload starting one second after domContentLoadedEventEnd (IAB, Display and Mobile Creative Guidelines, last updated 29 September 2015). The 2017 portfolio tightened both and moved the trigger to the window load event. Publishers' own specifications still differ, so the 2015 document's advice stands: check each publisher's requirements.
Worked budget for a 300x250 dynamic banner
The file sizes below are an illustrative build, not measurements. The target is the IAB's 150 kB gzipped initial load (IAB Tech Lab, 2017).
10 of 10 rows
| Initial | 6 kB |
Template script, bundled and minified | Initial | 24 kB |
Feed row JSON | Initial | 2 kB |
Product image, 600x500 WebP | Initial | 45 kB |
Logo SVG | Initial | 3 kB |
Web font subset | Initial | 18 kB |
Initial total | 98 kB in 6 requests | |
Animation sprite sheet | Subload | 120 kB |
Second product image | Subload | 45 kB |
Subload total | 165 kB |
index.html with inline CSS
- Load phase
Initial
- Gzipped size (illustrative)
6 kB
Template script, bundled and minified
- Load phase
Initial
- Gzipped size (illustrative)
24 kB
Feed row JSON
- Load phase
Initial
- Gzipped size (illustrative)
2 kB
Product image, 600x500 WebP
- Load phase
Initial
- Gzipped size (illustrative)
45 kB
Logo SVG
- Load phase
Initial
- Gzipped size (illustrative)
3 kB
Web font subset
- Load phase
Initial
- Gzipped size (illustrative)
18 kB
Initial total
- Load phase
- Gzipped size (illustrative)
98 kB in 6 requests
Animation sprite sheet
- Load phase
Subload
- Gzipped size (illustrative)
120 kB
Second product image
- Load phase
Subload
- Gzipped size (illustrative)
45 kB
Subload total
- Load phase
- Gzipped size (illustrative)
165 kB
Table by AdSovereign, CC BY 4.0.
The initial load leaves 52 kB of headroom for a heavier feed row. The subload stays under 300 kB. Note that the feed image counts against the IAB budget, so the max_kb field in the feed is a build-time check, not a suggestion.
Video and CTV: VAST, SIMID and the end of VPAID
Video ads arrive through the Video Ad Serving Template (VAST). For interactivity, the old answer was VPAID, which let ad code run inside the player. Its successor is the Secure Interactive Media Interface Definition (SIMID). The SIMID text says it "is part of a broader effort to replace the older VPAID standard", with Open Measurement taking over verification (IAB Tech Lab, SIMID 1.2).
6 of 6 rows
Where the ad code runs | In the player's page, with access to its DOM | In a cross-origin iframe, no player DOM access |
Who plays the video file | The creative | The player |
Communication | Direct function calls |
|
Server-side ad insertion | Not possible | Possible |
Verification | Done by the creative | Left to Open Measurement |
Resource MIME type |
|
|
Where the ad code runs
- VPAID
In the player's page, with access to its DOM
- SIMID
In a cross-origin iframe, no player DOM access
Who plays the video file
- VPAID
The creative
- SIMID
The player
Communication
- VPAID
Direct function calls
- SIMID
postMessagemessages
Server-side ad insertion
- VPAID
Not possible
- SIMID
Possible
Verification
- VPAID
Done by the creative
- SIMID
Left to Open Measurement
Resource MIME type
- VPAID
application/javascript- SIMID
text/html
Table by AdSovereign, CC BY 4.0.
Source: the comparison table in SIMID 1.2. That separation is why SIMID works with server-side ad insertion (SSAI): the player keeps control of the stream. A VAST response points to the SIMID file with an <InteractiveCreativeFile> element of type text/html and apiFramework="SIMID". The VAST 4.4 draft extends that element to non-linear ads such as pause and squeeze-back units (IAB Tech Lab, VAST 4.4 draft). CTV delivery is covered in SSAI and CTV ad serving.
SIMID 1.2 adds guidance on L-shaped squeeze-back ads, a value of -1 for unknown sizes and a rule that session IDs must be cryptographically secure (SIMID 1.2, section 2.3). Its signalling lags behind. The AdCOM 1.0 list of API frameworks has values for SIMID 1.0 (8) and SIMID 1.1 (9) but none for 1.2 (IAB Tech Lab, AdCOM 1.0). Until a value appears, bid requests can only say "SIMID 1.1". In apps, the MRAID 3.0 framework (value 6) plays the equivalent role for rich display ads.
Measurement: Open Measurement inside the creative
Viewability and verification vendors measure through the Open Measurement SDK (OM SDK). Its JavaScript clients have two parts: a verification client that vendor scripts use, and a session client that integration partners include in ad HTML at build time (IAB Tech Lab, Open-Measurement-JSClients). Version 1.6.12 shipped on 2 November 2026 with no changes from 1.6.11, which fixed stale element positions after resizes (changelog).
The bid stream has to say that OM is available and required. IAB Tech Lab's note on OpenRTB support for OMSDK puts value 7 in the api list of the Banner, Video or Native object. It adds omidpn and omidpv for the integration partner's name and version (IAB Tech Lab, OpenRTB support for OMSDK). The bid then lists 7 in apis, the array that replaced api in OpenRTB 2.6. The fragment below shows a DSP's bid carrying HTML5 markup that requires OMID; values are illustrative.
{
"id": "auction-7f3a",
"seatbid": [
{
"seat": "buyer-seat-12",
"bid": [
{
"id": "bid-1",
"impid": "1",
"price": 2.35,
"adm": "<div id=\"dco\" data-row=\"sku-48213-uk\"><script src=\"https://cdn.example.com/dco/300x250/v14/ad.js\"></script></div>",
"adomain": ["shop.example.com"],
"crid": "dco-300x250-v14",
"w": 300,
"h": 250,
"mtype": 1,
"apis": [7]
}
]
}
]
}4 of 4 rows
| The markup the ad server or SDK will render; here, a container that loads the DCO template |
| The creative ID buyers and sellers use for approvals; one ID per template version keeps audits simple |
| 1 means banner markup in OpenRTB 2.6 |
| 7 tells the seller this ad needs OMID 1.0 in the rendering environment |
adm
- Meaning
The markup the ad server or SDK will render; here, a container that loads the DCO template
crid
- Meaning
The creative ID buyers and sellers use for approvals; one ID per template version keeps audits simple
mtype
- Meaning
1 means banner markup in OpenRTB 2.6
apis
- Meaning
7 tells the seller this ad needs OMID 1.0 in the rendering environment
Table by AdSovereign, CC BY 4.0.
Field meanings come from OpenRTB 2.6 and the OMSDK note above. Every field is walked through in OpenRTB 2.6 explained. Viewability metrics themselves are defined in viewability, attention and brand safety.
Rendering in DSPs and ad servers
The same template renders differently depending on who serves it. Plan for each path before launch.
5 of 5 rows
DSP with HTML5 upload (for example DV360) | The DSP's ad server returns your ZIP's HTML | clickTag, 5 MB download, 100 HTTP calls, 30 s animation |
Third-party ad server tag in a DSP | A creative wrapper or tag calls your ad server, which calls the DCO platform | Extra hop latency; macros for click and impression tracking passed through |
Publisher ad server after header bidding | Prebid Universal Creative pulls the winning ad from Prebid's cache | SafeFrame or iframe path; correct size; |
In-app | SDK web view, often MRAID | MRAID version support; OM SDK integration |
CTV and video players | Player loads VAST, then the SIMID file if supported | SIMID support on the device; fallback to linear video |
DSP with HTML5 upload (for example DV360)
- What renders the ad
The DSP's ad server returns your ZIP's HTML
- What to check
clickTag, 5 MB download, 100 HTTP calls, 30 s animation
Third-party ad server tag in a DSP
- What renders the ad
A creative wrapper or tag calls your ad server, which calls the DCO platform
- What to check
Extra hop latency; macros for click and impression tracking passed through
Publisher ad server after header bidding
- What renders the ad
Prebid Universal Creative pulls the winning ad from Prebid's cache
- What to check
SafeFrame or iframe path; correct size;
hb_formatkey-value
In-app
- What renders the ad
SDK web view, often MRAID
- What to check
MRAID version support; OM SDK integration
CTV and video players
- What renders the ad
Player loads VAST, then the SIMID file if supported
- What to check
SIMID support on the device; fallback to linear video
Table by AdSovereign, CC BY 4.0.
For header bidding, the Prebid Universal Creative is a set of rendering routines that pull a given ad ID from Prebid's cache. Since Prebid.js 10.11.0 the library sets an hb_ver key-value that ad servers can use to load a specific version (Prebid.org, Prebid Universal Creative). In SafeFrames it asks Prebid.js for the winning ad over postMessage and draws it in a new iframe. The wrapper side is covered in the Prebid.js guide, and day-to-day trafficking in ad ops explained.
Testing and QA: a ten-step pipeline
Automate everything that has a number. Leave people to judge what only a human can see: copy, brand fit and the odd feed row that reads badly.
- Lint and build. Bundle, minify and gzip each template; fail the build on any external call to an unapproved domain.
- Check the weight budget. Measure gzipped kB per load phase and file requests against the strictest limit for each size.
- Check the clickTag. Confirm the variable exists, is not minified and opens a new window, as DV360 requires.
- Validate the feed. Every row against the field contract: lengths, image sizes, dates, a single default row.
- Render every row. Screenshot each feed row in each size; flag text overflow and missing images.
- Test the heavy ad limits deterministically. Chrome adds noise to its thresholds for privacy. Set
chrome://flags/#heavy-ad-privacy-mitigationsto Disabled to apply them exactly in testing (Chrome for Developers). - Listen for interventions in production. Chrome reports heavy ad removals through the Reporting API with the ID
HeavyAdIntervention, which aReportingObserverin the ad frame can capture. - Verify Open Measurement. Run the OM SDK compliance verification script; since version 1.6.9 the project documents how to self-host it (changelog).
- Preview targeting rules. Test at least three values per rule plus the empty case. Google's checklist asks for three locations or IDs and a default test (Google, Studio Help).
- Freeze during QA. Turn off scheduled feed uploads while testing, as Google advises, so the content you approve is the content that ships.
The first four steps fit a continuous integration (CI) job. The file below is our illustrative budget format; a build script reads it and fails if any limit is exceeded.
{
"template": "boots-300x250",
"version": "v14",
"limits": {
"initial_load_kb_gzip": 150,
"subload_kb_gzip": 300,
"initial_file_requests": 10,
"total_download_mb": 4,
"http_calls": 100,
"animation_seconds": 30
},
"checks": {
"clicktag_present": true,
"clicktag_not_minified": true,
"subload_after_window_load_event": true,
"no_audio_autoplay": true,
"omid_session_client_included": true
},
"feed": {
"required_fields": ["row_id", "is_default", "headline", "image", "exit_url"],
"max_headline_chars": 28,
"max_image_kb": 45,
"exactly_one_default_row": true
}
}The total_download_mb value is set to 4, not 5, on purpose. DV360 allows 5 MB, but Chrome unloads an ad above 4 MB of network use without interaction, so the browser is the binding limit.
Common mistakes
- Testing the template, not the feed. Most DCO failures come from data: a long name, a missing image, an expired price.
- No default row. Without one, unmatched impressions fall back to other creatives or nothing at all.
- Minifying the clickTag. The ad server cannot find the variable and clicks go nowhere.
- Loading everything before the page's
loadevent. It breaks the LEAN initial-load budget and slows the publisher's page. - Trusting a shared-library exemption you never confirmed. Unnamed libraries count in full.
- Building to the DSP's limit instead of the browser's. A 5 MB ad passes DV360 and gets unloaded by Chrome.
- Shipping VPAID for interactivity. Use SIMID for interactive video and OM SDK for verification.
- Changing feed IDs without republishing. Rules keep pointing at old IDs and serve the default everywhere.
FAQ
What is the file size limit for HTML5 banners?
What is the difference between SIMID and VPAID?
postMessage and leaves video playback to the player. That makes SIMID usable with server-side ad insertion, which VPAID was not (SIMID 1.2).How does clickTag work in an HTML5 ad?
clickTag variable holding the landing page URL and opens it on click. The ad server replaces the value with its own click-tracking URL at serve time. DV360 requires click tags, warns against minifying them and requires the landing page to open in a new tab or window (Google, DV360 Help).Can Google Ad Manager serve dynamic creatives built in Studio?
How do I test for Chrome's heavy ad intervention?
chrome://flags/#heavy-ad-privacy-mitigations so Chrome applies the thresholds exactly, then use DevTools CPU and network throttling to mimic slow devices. In production, capture intervention reports through the Reporting API (Chrome for Developers, updated 7 January 2026).How this works on owned infrastructure
A DCO pipeline is only as current as its feed, and the rules engine needs audience and product data at serve time. When the DCO platform, the ad server and the measurement sit with separate vendors, that data is copied into each of them and every feed update waits for their sync. AdSovereign includes an HTML5 creative and DCO layer that runs inside the same stack as the bidder and ad server, deployed in the customer's own cloud account or data centre. Feed rows, rules and render logs then stay in one place the team controls, and a variation's performance joins the bid logs without an export. The HTML5 DCO demo shows a template being filled from a feed, and the architecture page shows where the rules engine sits.
Sources
- IAB Technology Laboratory, "IAB New Ad Portfolio: Fixed Size Ad Specifications" with LEAN load guidance (2017; file hosted April 2019). https://www.iab.com/wp-content/uploads/2019/04/IABNewAdPortfolio_LW_FixedSizeSpec.pdf
- IAB, "Display & Mobile Advertising Creative Format Guidelines, updated for HTML5" (last updated 29 September 2015). https://www.iab.com/wp-content/uploads/2015/11/IAB_Display_Mobile_Creative_Guidelines_HTML5_2015.pdf
- Chrome for Developers, "Understand Chrome's Heavy Ad Interventions" (published 22 September 2025, last updated 7 January 2026). https://developer.chrome.com/docs/web-platform/heavy-ads-intervention
- Google, Display & Video 360 Help, "Guidelines for HTML5 display creatives" (accessed 9 November 2026). https://support.google.com/displayvideo/answer/10261241?hl=en
- Google, Studio Help, "About dynamic creatives" (accessed 9 November 2026). https://support.google.com/richmedia/answer/2691686?hl=en
- Google, Studio Help, "Dynamic creatives with feeds" QA checklist (accessed 9 November 2026). https://support.google.com/richmedia/answer/6310576?hl=en
- IAB Tech Lab, "Secure Interactive Media Interface Definition (SIMID) 1.2" (file added 23 July 2026; releases 1.1 of 25 January 2022 and 1.0 of 28 June 2019). https://github.com/InteractiveAdvertisingBureau/SIMID/blob/master/SIMID%201.2.md
- IAB Tech Lab, VAST4.x repository: VAST 4.3 (December 2022) and VAST 4.4 draft ("Publication Date TBD", commits July to September 2026). https://github.com/InteractiveAdvertisingBureau/VAST4.x
- IAB Tech Lab, "Advertising Common Object Model (AdCOM) v1.0", List: API Frameworks (accessed 9 November 2026). https://github.com/InteractiveAdvertisingBureau/AdCOM/blob/main/AdCOM%20v1.0%20FINAL.md
- IAB Tech Lab, "OpenRTB support for OMSDK" (AdCOM repository, accessed 9 November 2026). https://github.com/InteractiveAdvertisingBureau/AdCOM/blob/main/OpenRTB%20support%20for%20OMSDK.md
More sources (2)
- IAB Tech Lab, Open-Measurement-JSClients repository and changelog (version 1.6.12, 2 November 2026). https://github.com/InteractiveAdvertisingBureau/Open-Measurement-JSClients/blob/master/CHANGELOG.md
- Prebid.org, "Prebid Universal Creative" (accessed 9 November 2026). https://docs.prebid.org/overview/prebid-universal-creative.html