Online Resource 5: Full results
Online Resource 5 to "Do Open-Source Video Ad Clients Follow VAST 4.3? An Empirical Study of Player Conformance" (Prashant Chaudhary, October 2026). This document holds the results that are too long for the paper: the requirement catalog with the obligation sentence behind every requirement, the full macro grid split by macro set, pointers to two generated views that list every verdict, once by client and once by duty group, with the oracle detail of each deviating cell, and the sensitivity of the must-level counts to strength labels for each configuration. Paths are relative to the root of the replication repository. Nothing here was rerun; each part is copied from the file named at its head, with section signs written as "Sec." and typographic quotation marks as plain ones.
1. The requirement catalog with the obligation sentence behind every requirement
Source: generated from code/harness/suite/requirements.mjs, the VAST 4.3 text (sources/iab-vast-spec/VAST4.x/4.3.md) and the IAB macro list (sources/iab-vast-spec/vast/vast4macros/data/macros-data.json, commit 99d5d51); both are fetched and hash-checked by code/tools/fetch-sources.sh and are not stored in the replication package. Rows are sorted by ID in the order W, E, T, M, X, P, A, I, S, R, then by number. Appendix A of the paper gives the same requirements with their basis and literal modal; this table adds the sentence of the specification that carries each duty.
What the catalog records. Each entry has an ID, an area, a section reference, a strength, a duty and a one-line claim in the author's words. It records no sentence from the specification. Every obligation sentence below was therefore located in the VAST 4.3 text (or the macro list) for this table and is marked "located"; the generating script checks that each quoted fragment occurs verbatim on the cited line. "Where" is the line number in sources/iab-vast-spec/VAST4.x/4.3.md.
Literal modal. must, should or may as written; "required" where the text says "required" or "is required to" (treated as must); "imperative" for an instruction with no modal verb; "descriptive" for a definition or statement with no modal; "macro-list-required" where the only basis is the macro list's support label "Required"; "none" for robustness observations, which are not VAST clauses. Where several sentences are cited, the modal is the one that carries the graded duty (the note says which).
Flag. "differs" where the graded strength is not the literal modal (must against must or required; should against should; may against may; observation against none).
Catalog strengths: must 58, should 39, may 2, observation 9. Literal modals: must 32, required 22, should 22, descriptive 16, none 8, macro-list-required 5, may 2, imperative 1.
1.1 All 108 requirements
Table R5.1. All 108 requirements
| W01 | wrappers | Sec. 2.2; Sec. 2.3.5 | Follows a Wrapper to its InLine ad. | "VAST-compliant media players and SSAI systems must be able to play the ad in a VAST response" / "including those of any subsequent ad servers called in a chain of VAST Wrapper responses" | line 470; line 472 | located | must | must | |
|---|---|---|---|---|---|---|---|---|---|
| W02 | wrappers | Sec. 2.2; The Ad Element (sequence); Ad Pods | Follows a lone Wrapper that carries sequence="1" (a one-ad pod) to its InLine ad, or declines it with an error (pod support is optional). | "must be able to play the ad in a VAST response" / "Required (Ad Pod support is optional)" | line 470; line 975 | located | must | must | |
| W03 | wrappers | Sec. 3.19.1 | Accepts a chain of five Wrappers before the InLine ad (players are required to accept five). | "In VAST 4 the player is only required to accept five wrappers ads." | line 2258 | located | required | must | |
| W04 | wrappers | Sec. 2.3.5.1; Sec. 3.19.1 | With six Wrappers the player may reject; if it does, it determines 302 (and, with a tracker, reports it to the Error URI of every Wrapper it received). | "the player may reject any subsequent responses in the chain" / "Error codes should be sent for all wrappers in the chain where provided." | line 691; line 691 | located | should | should | |
| W05 | wrappers | Sec. 2.3.5.1 | Terminates a Wrapper that points to itself (stops requesting it). | "an infinite loop is possible where a chain of Wrappers never results in a final InLine VAST response" / "the player may reject any subsequent responses in the chain" | line 688; line 691 | located | descriptive | should | differs |
| W06 | wrappers | Sec. 2.3.5.1; Error Reporting table (302) | Reports 302 (wrapper limit) for a self-referencing Wrapper loop. | "Error codes should be sent for all wrappers in the chain where provided." / "Wrapper limit reached, as defined by the media player." | line 691; line 754 | located | should | should | |
| W07 | wrappers | Error Reporting (Media Player Details; table 301) | When the VASTAdTagURI is unavailable (HTTP 404), determines error 301. | "If an error occurs while trying to load an Ad and the <Error> element is provided, the media" / "Replace the [ERRORCODE] macro, if provided, with the appropriate error code" / "URI was either unavailable or reached a timeout" | line 730; line 733; line 753 | located | must | must | |
| W08 | wrappers | Error Reporting (table 301) | When the VASTAdTagURI times out, determines error 301. | "Replace the [ERRORCODE] macro, if provided, with the appropriate error code" / "Timeout of VAST URI provided in Wrapper element" | line 733; line 753 | located | must | must | |
| W09 | wrappers | Error Reporting (No Ad Response); Error (VAST) | When a Wrapper leads to a no-ad response and the player determines a code, the code is 303. | "If an [ERRORCODE] macro is included, the media player should substitute with error code 303." | line 793 | located | should | should | |
| W10 | wrappers | Sec. 3.2.1 Error (VAST); Error Reporting (No Ad Response) | Requests the VAST-level Error URI of a no-ad response reached through a Wrapper (with 303 for [ERRORCODE]). | "the media player must send a request to the URI provided when the VAST response returns an empty InLine response after a chain of one or more wrappers" | line 793 | located | must | must | |
| W11 | wrappers | Error Reporting (table 100); Sec. 2.3.2 (well-formed XML) | When the Wrapper target is not well-formed XML, determines error 100 (and does not use an ad from it). | "Replace the [ERRORCODE] macro, if provided, with the appropriate error code" / "XML parsing error." / "every attempt should be made to provide an error code that maps to the error that occurred" | line 733; line 742; line 1176 | located | must | must | |
| W12 | wrappers | Error Reporting (Media Player Details) | Requests the Wrapper Error URI when its VASTAdTagURI fails. | "Request the error source file using the URI provided." / "the media player must also return error details as listed above for each Wrapper response" | line 732; line 735 | located | must | must | |
| W13 | wrappers | Error Reporting (Media Player Details); Sec. 3.4.11 | An InLine error after a chain of Wrappers is reported to the InLine and to every Wrapper Error URI, with the same code (403 here). | "the media player must also return error details as listed above for each Wrapper response" / "will produce an error for each of the Wrappers used to serve the Inline Ad" | line 735; line 712 | located | must | must | |
| W14 | wrappers | Sec. 3.4.4; Sec. 2.3.4 | At impression time, requests the Impression URIs of the InLine ad and of every Wrapper before it. | "the media player is required to request all impressions at the same time or as close as possible to the same time" / "should be triggered at the same time when the impression for the ad occurs" | line 669; line 1052 | located | required | must | |
| W15 | wrappers | Sec. 3.19 (tracking elements in Wrappers) | Fires the Wrapper's Linear tracking events (start, quartiles, complete) together with the InLine ones. | "The media player is required to request the resource file for any included tracking elements" / "the Wrapper may contain tracking elements that provide tracking for the InLine ad" | line 663; line 2240 | located | required | must | |
| W16 | wrappers | Sec. 2.3.5.2 | When both the InLine and a Wrapper carry a ClickThrough, the InLine one is used. | "if the inLine response includes a ClickThrough element then this must be favored over ClickThrough element(s) specified in calling Wrappers" | line 703 | located | must | must | |
| W17 | wrappers | Sec. 2.3.5.2 | When the InLine has no ClickThrough (no VideoClicks), the ClickThrough of the Wrapper closest to the InLine is used. | "then the ClickThrough element closest to the InLine response must be favored" | line 703 | located | must | must | |
| W18 | wrappers | Sec. 3.10.2 ClickTracking; Sec. 3.19 | On a click, requests the ClickTracking URIs of the InLine and of every Wrapper. | "The media player is required to request the resource file for any included tracking elements" | line 663 | located | required | must | |
| W19 | wrappers | Sec. 3.19 (followAdditionalWrappers) | With followAdditionalWrappers="false", a Wrapper received next is ignored rather than followed. | "If false, any Wrappers received (i.e. not an Inline VAST response) should be ignored." | line 2251 | located | should | should | |
| W20 | wrappers | Sec. 3.19 (allowMultipleAds) | With allowMultipleAds="false", only the first stand-alone Ad of the response is used (pod ads are dropped). | "If false, only the first stand-alone Ad (with no sequence values) in the requested VAST response is allowed." | line 2251 | located | descriptive | should | differs |
| W21 | wrappers | Sec. 3.19 (allowMultipleAds default false) | Without the attribute, allowMultipleAds defaults to false, so only the first stand-alone Ad is used. | "Default value is “false.”" | line 2251 | located | descriptive | should | differs |
| W22 | wrappers | Sec. 3.19.2 BlockedAdCategories | Optional: rejects an InLine whose Category is blocked upstream; a player that does reject it must report 205. | "can also be used by the player to reject InLine ads" / "the client must notify the ad server using the <Error> URI, if provided (error code 205)" | line 2270; line 2270 | located | may | may | |
| E01 | errors | Sec. 3.2.1 Error (VAST) | For a no-ad response, requests the VAST-level Error URI. | "the media player must use the URI provided to notify the server that no ad was returned" | line 932 | located | must | must | |
| E02 | errors | Sec. 3.2.1 Error (VAST), bounded 0+ | Requests every VAST-level Error URI when several are given. | "the media player must use the URI provided" / "Multiple <Error> elements may be provided to notify multiple parties" | line 932; line 932 | located | must | must | |
| E03 | errors | Sec. 3.4.11; Error Reporting (table 403) | With no supported MediaFile, requests every InLine Error URI with 403. | "Replace the [ERRORCODE] macro, if provided, with the appropriate error code" / "Couldn’t find MediaFile that is supported by this media player" | line 733; line 760 | located | must | must | |
| E04 | errors | Error Reporting (Media Player Details); macro list ERRORCODE | Replaces [ERRORCODE] in Error URIs with a numeric code. | "Replace the [ERRORCODE] macro, if provided, with the appropriate error code" / "the media player must populate the macro with an error code" | line 733; line 1174 | located | must | must | |
| T01 | tracking | Sec. 2.3.4; Sec. 3.4.4 | Requests every Impression URI of the ad. | "The media player is required to request the resource file for any included tracking elements" / "the media player must use to notify the ad server when the impression occurs" | line 663; line 1060 | located | required | must | |
| T02 | tracking | Sec. 3.4.4 (about:blank) | Does not dispatch an Impression whose URI is about:blank. | "The player should disregard dispatching the tracking URI if it is set to "about:blank"" | line 1060 | located | should | should | |
| T03 | tracking | Sec. 3.14.1 (Linear metrics) | Fires start, firstQuartile, midpoint, thirdQuartile and complete exactly once each, in that order. | "the media player is required to trigger the tracking resource URI provided in the nested <Tracking> element" / "firstQuartile: The creative played continuously for at least 25%" | line 1972; line 1948 | located | required | must | |
| T04 | tracking | Sec. 3.14.3 (multiple Tracking elements per event) | Fires every Tracking element for the same event (two start trackers for two parties). | "the media player is required to trigger the tracking resource URI" / "may also be used to track events of the same type for multiple parties" | line 1972; line 1984 | located | required | must | |
| T05 | tracking | Sec. 3.14.1 (progress, HH:MM:SS offset) | Fires a progress tracker with an HH:MM:SS offset. | "the media player is required to trigger the tracking resource URI" / "Values can be time in the format HH:MM:SS or HH:MM:SS.mmm or a percentage value in the format n%." | line 1972; line 1953 | located | required | must | |
| T06 | tracking | Sec. 3.14.1 (progress, HH:MM:SS.mmm offset) | Fires a progress tracker with an HH:MM:SS.mmm offset. | "the media player is required to trigger the tracking resource URI" / "Values can be time in the format HH:MM:SS or HH:MM:SS.mmm" | line 1972; line 1953 | located | required | must | |
| T07 | tracking | Sec. 3.14.1 (progress, n% offset) | Fires progress trackers with percentage offsets (10% and 80%). | "the media player is required to trigger the tracking resource URI" / "or a percentage value in the format n%" / "If the duration is not known when the offset is set to a percentage value, the progress event may be ignored." | line 1972; line 1953; line 2003 | located | required | must | |
| T08 | tracking | Sec. 3.14.1 (thirdQuartile, complete definitions) | Stopping at 60% fires midpoint but neither thirdQuartile nor complete. | "the media player is required to trigger the tracking resource URI" / "thirdQuartile: The creative played continuously for at least 75% of the duration at normal speed." | line 1972; line 1950 | located | required | must | |
| T09 | tracking | Sec. 2.3.4; Sec. 3.4.4 (same time) | Spread between the first and last Impression request at impression time (ms, measured at the server). | "the media player is required to request all impressions at the same time or as close as possible to the same time" | line 669 | located | required | observation | differs |
| M01 | macros | IAB macro list: CACHEBUSTING (required) | Replaces [CACHEBUSTING] with a random 8-digit integer. | "Required" / "Random 8-digit integer." | macro list, CACHEBUSTING; macro list, CACHEBUSTING | located | macro-list-required | must | differs |
| M02 | macros | IAB macro list: TIMESTAMP (required) | Replaces [TIMESTAMP] with an ISO 8601 date-time (milliseconds and zone as in the macro list example 2016-01-17T8:15:07.127-05). | "Required" / "formatting conventions of ISO 8601" | macro list, TIMESTAMP; macro list, TIMESTAMP | located | macro-list-required | must | differs |
| M03 | macros | IAB macro list: LIMITADTRACKING (required) | Replaces [LIMITADTRACKING] with 0 or 1 (the harness also accepts -1/-2, since a browser has no device advertising ID; see detail). | "Required" / "with “1” indicating that a user has opted for limited ad tracking" | macro list, LIMITADTRACKING; macro list, LIMITADTRACKING | located | macro-list-required | must | differs |
| M04 | macros | Sec. 6.1 (encodeURIComponent on values) | Percent-encodes macro values (the colons in TIMESTAMP). | "make sure to apply encodeURIComponent to any value" / "the encoded version must always be used as a macro substitution" | line 2483; line 2489 | located | must | must | |
| M05 | macros | Sec. 6.1 (do not replace unknown macros with -1) | Does not write -1 into a macro it does not know ([NOTAREALMACRO]). | "do not replace all unknown macros with -1, only do this for macros specifically mentioned in this section" | line 2477 | located | imperative | should | differs |
| X01 | xml | Sec. 2.3.3 (whitespace around a CDATA-wrapped URI) | Trims the whitespace around a CDATA-wrapped Impression URI before handing it to the network (checked on the client side, since URL parsers also strip it). | "<![CDATA[http://ad.server.com/impression/dot.gif]]>" / "Correct and backwards compatible." | line 578; line 581 | located | descriptive | should | differs |
| X02 | xml | Sec. 2.2 (XML comments) | Ignores XML comments inside an element when reading its URI. | "must be able to play the ad in a VAST response" / "acknowledge VAST comments in the standard XML syntax" | line 470; line 475 | located | must | must | |
| X03 | xml | Sec. 2.3.2 (character entities should be honored) | Decodes character entities (&) in a URI given as plain text (a document that breaks Sec. 2.3.3's CDATA rule, which real tags still do). | "standard XML requirements such as character entities and <!--XML comments--> should be honored" | line 516 | located | should | should | |
| X04 | xml | (robustness; a 4.x document without the VAST namespace is not schema-valid) | Parses a document that omits xmlns="http://www.iab.com/VAST". | (no VAST clause) | - | - | none | observation | |
| X05 | xml | Sec. 3.7.1 (UniversalAdId 1+; 4.2 XSD unbounded) | Accepts a Creative with two UniversalAdId elements. | "must be able to play the ad in a VAST response" / "A required element for the purpose of tracking ad creative" | line 470; line 1283 | located | must | must | |
| X06 | xml | Sec. 2.2 (play the ad in a VAST response); Sec. 3.9.5 (ClosedCaptionFile 0+) | Accepts two ClosedCaptionFile elements. | "must be able to play the ad in a VAST response" | line 470 | located | must | must | |
| P01 | pods | Ad Pods and Stand-Alone Ads | Orders pod ads by their sequence attribute (document order is 3, 1, 2): the ad with sequence 1 comes first (or the pod is declined with an error; pod support is optional). | "the media player must play the ads in the Pod in the prescribed sequence" / "sequenced ads are played in numerical order" | line 958; line 948 | located | must | must | |
| R01 | robustness | (engineering; not a VAST clause) | A timed-out Wrapper request does not escape as an uncaught exception (which terminates a Node process). | (no VAST clause) | - | - | none | observation | |
| R02 | robustness | (engineering; not a VAST clause) | A failed Wrapper request does not escape as an uncaught exception. | (no VAST clause) | - | - | none | observation | |
| W23 | wrappers | Sec. 3.19 (fallbackOnNoAd) | With fallbackOnNoAd="true", when the Wrapper's target returns no ad, a stand-alone ad from the response is used. | "If true, the media player should select from any stand-alone ads available." | line 2252 | located | should | should | |
| E05 | errors | Error Reporting (table 401) | When the MediaFile URI returns HTTP 404, requests the InLine Error URI with 401 (file not found). | "Replace the [ERRORCODE] macro, if provided, with the appropriate error code" / "File not found. Unable to find Linear/MediaFile from URI." | line 733; line 758 | located | must | must | |
| E06 | errors | Error Reporting (table 405) | When a MediaFile of a supported type cannot be decoded, requests the InLine Error URI with 405. | "Replace the [ERRORCODE] macro, if provided, with the appropriate error code" / "Media player found a MediaFile with supported type but couldn’t display it." | line 733; line 761 | located | must | must | |
| E07 | errors | Error Reporting (table 402) | When the MediaFile URI answers only after 30 s, requests the InLine Error URI with 402 (media timeout). | "Replace the [ERRORCODE] macro, if provided, with the appropriate error code" / "Timeout of MediaFile URI." | line 733; line 759 | located | must | must | |
| E08 | errors | Sec. 3.4.11 (Error is for ads that cannot be served) | Does not request the Error URI when the ad plays without a problem. | "The <Error> element enables the media player to provide feedback to ad servers when an Ad cannot be served." / "This error-tracking resource is called when the media player is unable to display the Ad." | line 707; line 714 | located | descriptive | should | differs |
| E09 | errors | Sec. 2.3.1; Error Reporting (table 200, 201) | Given a NonLinear-only ad, either displays it (impression or creativeView) or reports 200/201 (unexpected ad type or linearity). | "Replace the [ERRORCODE] macro, if provided, with the appropriate error code" / "Media player received an Ad type that it was not expecting and/or cannot play." / "it can decline from loading the ad resources and use the error URI" | line 733; line 745; line 954 | located | must | must | |
| T10 | tracking | Sec. 2.3.4 (IAB Digital Video Measurement Guidelines); Sec. 3.4.4 | Does not request the Impression of an ad whose media never plays (no supported MediaFile). | "compliance with the IAB Digital Video Measurement Guidelines" / "when the impression occurs" | line 673; line 1060 | located | descriptive | should | differs |
| T11 | tracking | Sec. 3.4.4 (notify when the impression occurs); Sec. 2.3.4 | Requests the Impression exactly once across pause, resume, mute and unmute. | "the media player must use to notify the ad server when the impression occurs" | line 1060 | located | descriptive | should | differs |
| T12 | tracking | Sec. 3.14.1 (pause) | Fires the pause tracker once when the user pauses. | "the media player is required to trigger the tracking resource URI" / "pause: the user clicked the pause control and stopped the creative." | line 1972; line 1937 | located | required | must | |
| T13 | tracking | Sec. 3.14.1 (resume) | Fires the resume tracker once when the user resumes. | "the media player is required to trigger the tracking resource URI" / "resume: the user activated the resume control after the creative had been stopped or paused." | line 1972; line 1938 | located | required | must | |
| T14 | tracking | Sec. 3.14.1 (mute) | Fires the mute tracker once when the user mutes. | "the media player is required to trigger the tracking resource URI" / "mute: the user activated the mute control and muted the creative." | line 1972; line 1935 | located | required | must | |
| T15 | tracking | Sec. 3.14.1 (unmute) | Fires the unmute tracker when the user unmutes. | "the media player is required to trigger the tracking resource URI" / "unmute: the user activated the mute control and unmuted the creative." | line 1972; line 1936 | located | required | must | |
| T23 | tracking | Sec. 3.14.1 (unmute: the user unmuted) | A volume change that is not an unmute (0.5 while unmuted) does not fire unmute. | "unmute: the user activated the mute control and unmuted the creative." | line 1936 | located | descriptive | should | differs |
| T20 | tracking | Sec. 3.14.1 (loaded) | Fires the loaded tracker once when the media is ready to play. | "This event should be used to indicate when the player considers that it has loaded" | line 1946 | located | should | should | |
| T16 | tracking | Sec. 2.3.1 (Skippable Linear); Sec. 3.8 skipoffset; Sec. 3.14.1 (skip) | Skipping at 6 s (skipoffset 00:00:03) fires skip and neither thirdQuartile nor complete (skippable support is an optional ad type). | "the media player is required to trigger the tracking resource URI" / "skip: the user activated a skip control to skip the creative." | line 1972; line 1940 | located | required | must | |
| T17 | tracking | Sec. 3.8 (skipoffset: when skip controls are made available) | The skip control is not available at 1.5 s and is available at 6 s (skipoffset 00:00:03). | "Time value that identifies when skip controls are made available to the end user" | line 1351 | located | descriptive | should | differs |
| T18 | tracking | Sec. 3.8 skipoffset; VAST 4.2 XSD (skipoffset pattern allows n%) | A percentage skipoffset (30% of 10 s) makes skip available at 3 s, and skipping fires skip. | "Time value that identifies when skip controls are made available to the end user" | line 1351 | located | descriptive | should | differs |
| T19 | tracking | Sec. 3.14.3 (progress counts a view even if the ad is skipped) | Progress offsets passed before the skip (2 s and 5 s) are fired. | "When skippable ads are supported, the progress event is used to identify when the ad counts as a view even if the ad is skipped." | line 1986 | located | descriptive | should | differs |
| T21 | tracking | Sec. 3.14.1 (rewind) | Fires the rewind tracker when the user seeks back 2 s (from 60% to 40%). | "the media player is required to trigger the tracking resource URI" / "rewind: the user activated the rewind control" | line 1972; line 1939 | located | required | must | |
| T22 | tracking | Sec. 3.14.1 (quartiles: played continuously) | After rewinding from 6 s to 4 s, midpoint and the 5 s progress tracker are not fired a second time when playback passes them again. | "midpoint: The creative played continuously for at least 50% of the total duration at normal speed." | line 1949 | located | descriptive | should | differs |
| A01 | verification | Sec. 3.17; Sec. 3.17.4 (verificationNotExecuted) | When it does not execute the InLine's verification resource (a JavaScript resource with an apiFramework it does not implement), requests its verificationNotExecuted URI. | "The player must request each associated verificationNotExecuted tracking event URI" / "any appropriate tracking events listed under the <Verification> element must be fired" | line 841; line 2090 | located | must | must | |
| A02 | verification | Sec. 3.17.4 [REASON]; IAB macro list: REASON (required) | Fills [REASON] in verificationNotExecuted with a reason code (1, 2 or 3). | "with the [REASON] macro filled with reason code 1" / "Required" / "The following macros should be supported specifically in URIs for this event type" | line 841; macro list, REASON; line 2164 | located | must | must | |
| A03 | verification | Viewability with Ad Verification Services (resources from intermediary Wrappers) | Handles the Wrapper's verification too: requests its verificationNotExecuted URI. | "All verification resources listed in the VAST should be executed, including those from any intermediary <Wrapper> VASTs" | line 839 | located | should | should | |
| A04 | verification | Sec. 3.17.4 (reason code 2); Sec. 3.17.1; Viewability with Ad Verification Services | Reports a verification resource whose apiFramework it does not implement with reason 2 (verification not supported). | "the player must trigger any provided verificationNotExecuted tracking events with reason code 2" | line 2109 | located | must | must | |
| A05 | verification | Sec. 3.17.4 (reason code 3: 404 or other failed response codes); Viewability with Ad Verification Services | When an OMID verification resource fails to load (HTTP 404), requests its verificationNotExecuted URI with reason 3 (error during resource load). | "any included verificationNotExecuted tracking events URIs must be sent with the appropriate reason code" / "404 or other failed response codes" | line 843; line 2171 | located | must | must | |
| S01 | media | MediaFiles (choose by attributes, not document order) | Skips a MediaFile of an unsupported type listed first (video/x-flv) and plays a supported one. | "the publisher should decide which file to play based on attributes of the MediaFile nodes and not the structure of the document" | line 1391 | located | should | should | |
| S02 | media | Sec. 1.4; Sec. 3.4 (adType="audio") | Optional: plays an audio ad (adType="audio", Opus WebM and AAC files). | "organizations may be compliant with VAST while only supporting a selected subset of the ad types" / "all ad types are relevant for “audio only” ads except NonLinear ads" | line 500; line 512 | located | may | may | |
| M06 | macros | Sec. 6.1 (unprovided optional macros must become -1 or -2) | Replaces each of eight listed optional macros ([ADPLAYHEAD], [ADSERVINGID], [UNIVERSALADID], [PODSEQUENCE], [ASSETURI], [BREAKPOSITION], [IFA], [CLIENTUA]) with a plausible value or -1/-2; none left as macro or empty. | "the following special values must be inserted into the macro to indicate the reason for not providing the information" | line 2470 | located | must | must | |
| M07 | macros | Sec. 3.4.3 (player fills [ADSERVINGID] from AdServingId) | Fills [ADSERVINGID] with the ad's AdServingId (in-serving). | "The player is responsible for parsing this value and using it to fill the associated macro (see section 6) on tracking pixels." | line 1034 | located | descriptive | should | differs |
| M08 | macros | IAB macro list: ADPLAYHEAD (HH:MM:SS.mmm) | When it fills [ADPLAYHEAD], the midpoint value is HH:MM:SS.mmm and about 5 s. | "Optional" / "{HH:MM:SS.mmm}" | macro list, ADPLAYHEAD; macro list, ADPLAYHEAD | located | descriptive | should | differs |
| M09 | macros | Sec. 6.1 (Array values: encode each value, commas unencoded); IAB macro list: UNIVERSALADID | Fills [UNIVERSALADID] with one or more of the Creative's IDs as "registry value" pairs, each percent-encoded; several IDs are joined by a raw comma. | "the value should be rendered as a set of values separated by a comma" / "encoding should be applied to individual values only" | line 2481; line 2483 | located | should | should | |
| M10 | macros | IAB macro list: ASSETURI (the media file being played) | When it fills [ASSETURI], the value is the MediaFile actually chosen (an unsupported FLV is listed first). | "Optional" / "The URI of the ad asset currently being played." | macro list, ASSETURI; macro list, ASSETURI | located | descriptive | should | differs |
| M11 | macros | IAB macro list: CACHEBUSTING, TIMESTAMP (contexts: all tracking pixels, including Error) | Replaces [CACHEBUSTING] and [TIMESTAMP] in an Error URI as in any other tracking URI. | "All tracking pixels" / "All tracking pixels" / "both for VAST URLs and tracking pixel URLs, this would be the video player" | macro list, CACHEBUSTING; macro list, TIMESTAMP; line 2465 | located | macro-list-required | must | differs |
| M12 | macros | IAB macro list: CACHEBUSTING, TIMESTAMP (contexts: VAST request URIs) | Replaces [CACHEBUSTING] and [TIMESTAMP] in a Wrapper's VASTAdTagURI before requesting it. | "VAST request URIs" / "VAST request URIs" / "The responsibility to properly replace macros with their proper values lies with the party that will perform the HTTP request." / "both for VAST URLs and tracking pixel URLs, this would be the video player" / "the VAST macro concept will be expanded to apply not just to tracking URIs, but to AdTagURIs in Wrapper creatives" | macro list, CACHEBUSTING; macro list, TIMESTAMP; line 2463; line 2465; line 401 | located | macro-list-required | must | differs |
| P06 | pods | Ad Pods (play the pod in sequence; play as many ads as possible) | Plays all three ads of a pod. | "all ads in the Pod should be played to the best of the player's ability" / "should play as many of the ads as possible" / "all ads in the Pod must be played to the best of the player's ability" | line 948; line 958; line 967 | located | should | should | |
| P03 | pods | Sec. 2.3.4 (fire each tracker at the appropriate time); Ad Pods | Playing a three-ad pod, each ad gets one impression and one complete, fired between its own impression and the next ad's. | "required to request the resource file for any included tracking elements from the URI provided at the appropriate times" / "the same impression and tracking URIs in the VAST <Wrapper> are called as each ad in the Pod is played" | line 663; line 960 | located | required | must | |
| P02 | pods | Ad Pods (an ad fails: move on) | When the second pod ad cannot play, playback continues with another ad (the stand-alone ad or the third pod ad). | "If stand-alone ads are unavailable, the player should move on to the next ad in the Ad Pod." | line 962 | located | should | should | |
| P05 | pods | Ad Pods (substitute an un-played stand-alone ad) | The failed pod ad is replaced by the stand-alone ad from the response, after the first pod ad and before the third. | "the media player should substitute an un-played stand-alone ad from the response" | line 962 | located | should | should | |
| I01 | icons | Industry Icon Support; Sec. 3.11.2 IconViewTracking | Displays the Icon after the ad starts and requests its IconViewTracking URI. | "the media player must display the object as an overlay on top of the Linear Ad with which the icon is served and after the ad has started" / "The player uses the included URI to notify the icon server when the icon has been displayed." | line 815; line 1617 | located | must | must | |
| I03 | icons | Sec. 3.11.1 Icon (offset, duration) | Displays an Icon with offset 00:00:01 and duration 00:00:08 once playback passes 1 s, requesting its IconViewTracking URI. | "The time of delay from when the associated linear creative begins playing to when the icon should be displayed" / "The duration the icon should be displayed unless clicked or ad is finished playing" | line 1609; line 1608 | located | should | should | |
| I02 | icons | Sec. 3.11.5 IconClickTracking | On a click on the Icon, requests its IconClickTracking URI. | "The media player is required to request the resource file for any included tracking elements" / "is used to track click activity within the icon" | line 663; line 1653 | located | required | must | |
| X07 | xml | Sec. 2.3.3; Sec. 3.19.1 VASTAdTagURI | Follows a VASTAdTagURI whose CDATA is surrounded by whitespace and line breaks (on the wire; URL parsers also strip the whitespace). | (no VAST clause) | - | - | none | observation | |
| X08 | xml | Sec. 3.14.3 (event values are an enumeration) | Never requests a Tracking element whose event name is not a VAST event (notARealEvent). | "A string that defines the event being tracked. Accepted values are listed in section" | line 2001 | located | descriptive | should | differs |
| X09 | xml | Sec. 3.18 Extensions (custom XML for the publisher, not VAST elements) | Does not request Impression or Tracking URIs that appear inside an Extension. | "custom XML should fall under the nested <Extension> (singular) element so that custom XML can be separated from VAST elements" | line 2200 | located | should | should | |
| X10 | xml | Sec. 2.3.2 (XML 1.0: a UTF-8 byte order mark is allowed) | Parses a document that starts with a UTF-8 byte order mark. | "must be able to play the ad in a VAST response" / "compliant with XML 1.0" | line 470; line 516 | located | must | must | |
| X11 | xml | Sec. 2.3.3 (a URI containing "]]>" split across CDATA sections) | Reassembles an Impression URI split across two CDATA sections (query s=x]]>x). | "The media player is required to request the resource file for any included tracking elements from the URI provided" / "will be concatenated with the other two URI components" | line 663; line 561 | located | required | must | |
| X12 | xml | Sec. 3.7.1 (VAST 4.0 idValue attribute: players should not fail) | Accepts a UniversalAdId that still carries the VAST 4.0 idValue attribute. | "Media players should not fail if this attribute is present" | line 1289 | located | should | should | |
| X13 | xml | Sec. 3.4.4 (Impression) | An empty Impression element does not stop the other Impression from being requested. | "The media player is required to request the resource file for any included tracking elements" | line 663 | located | required | must | |
| X14 | xml | Sec. 4.3 Media Players (accept older VAST versions) | Accepts a VAST 3.0 InLine document. | "VAST 4 players should continue to accept ads on older versions of VAST" | line 2308 | located | should | should | |
| X15 | xml | Sec. 4.3 Media Players (accept older VAST versions) | Accepts a VAST 2.0 InLine document. | "VAST 4 players should continue to accept ads on older versions of VAST" | line 2308 | located | should | should | |
| X16 | xml | Sec. 4.3 Media Players (accept older VAST versions) | Follows a VAST 3.0 Wrapper to a VAST 4.3 InLine. | "VAST 4 players should continue to accept ads on older versions of VAST" | line 2308 | located | should | should | |
| R03 | robustness | (HTTP; not a VAST clause) | Follows an HTTP 302 redirect on a VASTAdTagURI. | (no VAST clause) | - | - | none | observation | |
| R04 | robustness | (HTTP; not a VAST clause) | Parses a VAST response sent with Content-Encoding: gzip. | (no VAST clause) | - | - | none | observation | |
| R05 | robustness | (HTTP; not a VAST clause) | Parses a VAST response served as text/plain rather than an XML media type. | (no VAST clause) | - | - | none | observation | |
| R06 | robustness | (HTTP; not a VAST clause) | A tracking URI that answers HTTP 500 does not stop later trackers (quartiles, complete). | (no VAST clause) | - | - | none | observation | |
| X17 | xml | Sec. 2.2 (acknowledge XML comments); Sec. 2.3.2 | Does not request an Impression element that sits entirely inside an XML comment (next to a real Impression). | "must be able to play the ad in a VAST response" / "acknowledge VAST comments in the standard XML syntax" | line 470; line 475 | located | must | must | |
| X18 | xml | Sec. 2.3.2 (character entities should be honored); Sec. 3.19.1 VASTAdTagURI | Requests a VASTAdTagURI written as escaped text, with & between query parameters, with all parameters intact (a=1, b=2, c=3). | "character entities and <!--XML comments--> should be honored" | line 516 | located | should | should | |
| X19 | xml | Sec. 2.3.2 (character entities should be honored); Sec. 3.19.1 VASTAdTagURI | Requests a VASTAdTagURI written as escaped text, with the character reference & between query parameters, with all parameters intact (a=1, b=2, c=3). | "character entities and <!--XML comments--> should be honored" | line 516 | located | should | should | |
| P07 | pods | Ad Pods and Stand-Alone Ads (play the pod in the prescribed sequence); Sec. 3.19 | Orders the pod ads of a Wrapper's target by their sequence attribute (document order 3, 1, 2; the Wrapper sets allowMultipleAds="true"): the ad with sequence 1 comes first (or the pod is declined with an error; pod support is optional). | "the media player must play the ads in the Pod in the prescribed sequence" | line 958 | located | must | must |
1.2 Flagged rows (23)
Graded strength differs from the literal modal. Grouped by direction.
Graded must, text weaker or not modal (5)
- M01 (graded must, text macro-list-required). Rests on the macro list's support label "Required", not on a modal verb in the 4.3 text; the 8-digit format is the list's description.
- M02 (graded must, text macro-list-required). Rests on the macro list label "Required" and the list's ISO 8601 description.
- M03 (graded must, text macro-list-required). Rests on the macro list label "Required"; the 0/1 values are the list's description.
- M11 (graded must, text macro-list-required). Rests on the macro list label "Required" with context "All tracking pixels", plus Sec. 6.1 (line 2465, descriptive).
- M12 (graded must, text macro-list-required). Rests on the macro list label "Required" with context "VAST request URIs", Sec. 6.1's responsibility sentence (line 2463, descriptive) and Sec. 1.5 (line 401, which extends macros to Wrapper AdTagURIs); the basis is the same as M11's, so grading M12 should while M01 to M03 and M11 stay must would be inconsistent.
Graded should, text has no modal (17)
- W05 (graded should, text descriptive). Graded should: Sec. 2.3.5.1 describes loops and lets a player reject after five, but no sentence obliges the player to end a loop; no client deviates.
- W20 (graded should, text descriptive). Attribute definition with no modal ("is allowed"); should is the author's floor, which is defensible and only affects should counts.
- W21 (graded should, text descriptive). Attribute default with no modal; graded should as for W20.
- M05 (graded should, text imperative). An imperative instruction with no modal ("do not replace all unknown macros with -1"); should is a reading, and no reference cell deviates.
- X01 (graded should, text descriptive). Whitespace around a CDATA URI appears only in examples marked correct; there is no player sentence.
- E08 (graded should, text descriptive). The text says what the Error element is for ("when an Ad cannot be served") without a modal; should is an inference.
- T10 (graded should, text descriptive). When an impression "occurs" is defined by the IAB Measurement Guidelines, not by a modal in VAST.
- T11 (graded should, text descriptive). "Exactly once" is not stated; the must at line 1060 covers notifying when the impression occurs.
- T23 (graded should, text descriptive). Read from the unmute definition; no modal.
- T17 (graded should, text descriptive). skipoffset is defined ("identifies when skip controls are made available") without a modal.
- T18 (graded should, text descriptive). As T17; the percentage form is in the 4.2 XSD pattern, not in the 4.3 text.
- T19 (graded should, text descriptive). Descriptive ("the progress event is used to identify when the ad counts as a view").
- T22 (graded should, text descriptive). Read from the quartile definitions ("played continuously"); no modal.
- M07 (graded should, text descriptive). A responsibility statement ("The player is responsible for ...") on an optional macro; should is an inference.
- M08 (graded should, text descriptive). The macro list gives a format for an optional macro but no modal.
- M10 (graded should, text descriptive). The macro list describes an optional macro ("the ad asset currently being played") but has no modal.
- X08 (graded should, text descriptive). The event attribute definition lists accepted values without a modal.
Graded observation (1)
- T09 (graded observation, text required). The text requires simultaneous impressions (required, line 669) but sets no threshold, so the catalog measures instead of grading; by design.
2. The full macro grid, split by set
Source: macro-grid.jsonl in the archive's macro-grid results, split by macro set. A literal or empty value deviates (Section 4.4 of the paper); "Deviating" is literal plus empty or absent; delegated cells are iab-vast-loader's pixels. Paper Table 7 condenses this grid: its "value", "-1 or -2" and "literal" columns are the 4.3 rows below for the tracking pixel, and its "4.x" column is the "other" pixel rows.
Set: "4.3" is the graded 4.3 set of paper Section 4.2, the macros whose introduction version on the IAB macro list is 3.0, 4.0, 4.1 or 4.2 (40 pixel macros, 41 request-URI macros); "other" is the macros outside the graded set, whose introduction version is "4.x" or "Next VAST release" (5 pixel macros, 9 request-URI macros). Of these nine, four were on the list, marked "Next VAST release", when VAST 4.3 was published (STOREID, STOREURL, PLAYBACKMETHODS, CONTENTCAT), and five were added in 2023 and 2024 (GPPSTRING, GPPSECTIONID and three DSA macros) (paper Section 4.2). The five pixel macros are those marked "4.x".
Table R5.2. The full macro grid, split by set
| vast-client-js 6.5.0 | Tracking pixel | 4.3 | 40 | 6 | 34 | 0 | 0 | 0 | 0 |
|---|---|---|---|---|---|---|---|---|---|
| vast-client-js 6.5.0 | Tracking pixel | other | 5 | 0 | 0 | 5 | 0 | 0 | 5 |
| vast-client-js 6.5.0 | VAST request URI, CDATA | 4.3 | 41 | 0 | 0 | 41 | 0 | 0 | 41 |
| vast-client-js 6.5.0 | VAST request URI, CDATA | other | 9 | 0 | 0 | 9 | 0 | 0 | 9 |
| vast-client-js 6.5.0 | VAST request URI, escaped text | 4.3 | 41 | 0 | 0 | 41 | 0 | 0 | 41 |
| vast-client-js 6.5.0 | VAST request URI, escaped text | other | 9 | 0 | 0 | 9 | 0 | 0 | 9 |
| video-ad-sdk 4.0.1 | Tracking pixel | 4.3 | 40 | 2 | 0 | 38 | 0 | 0 | 38 |
| video-ad-sdk 4.0.1 | Tracking pixel | other | 5 | 0 | 0 | 5 | 0 | 0 | 5 |
| video-ad-sdk 4.0.1 | VAST request URI, CDATA | 4.3 | 41 | 0 | 0 | 41 | 0 | 0 | 41 |
| video-ad-sdk 4.0.1 | VAST request URI, CDATA | other | 9 | 0 | 0 | 9 | 0 | 0 | 9 |
| video-ad-sdk 4.0.1 | VAST request URI, escaped text | 4.3 | 41 | 0 | 0 | 41 | 0 | 0 | 41 |
| video-ad-sdk 4.0.1 | VAST request URI, escaped text | other | 9 | 0 | 0 | 9 | 0 | 0 | 9 |
| iab-vast-loader 2.5.1 | Tracking pixel | 4.3 | 40 | 0 | 0 | 0 | 0 | 40 | 0 |
| iab-vast-loader 2.5.1 | Tracking pixel | other | 5 | 0 | 0 | 0 | 0 | 5 | 0 |
| iab-vast-loader 2.5.1 | VAST request URI, CDATA | 4.3 | 41 | 0 | 0 | 41 | 0 | 0 | 41 |
| iab-vast-loader 2.5.1 | VAST request URI, CDATA | other | 9 | 0 | 0 | 9 | 0 | 0 | 9 |
| iab-vast-loader 2.5.1 | VAST request URI, escaped text | 4.3 | 41 | 0 | 0 | 41 | 0 | 0 | 41 |
| iab-vast-loader 2.5.1 | VAST request URI, escaped text | other | 9 | 0 | 0 | 9 | 0 | 0 | 9 |
| vastlint-client 0.15.0 | Tracking pixel | 4.3 | 40 | 2 | 0 | 38 | 0 | 0 | 38 |
| vastlint-client 0.15.0 | Tracking pixel | other | 5 | 0 | 0 | 5 | 0 | 0 | 5 |
| vastlint-client 0.15.0 | VAST request URI, CDATA | 4.3 | 41 | 0 | 0 | 41 | 0 | 0 | 41 |
| vastlint-client 0.15.0 | VAST request URI, CDATA | other | 9 | 0 | 0 | 9 | 0 | 0 | 9 |
| vastlint-client 0.15.0 | VAST request URI, escaped text | 4.3 | 41 | 0 | 0 | 1 | 40 | 0 | 41 |
| vastlint-client 0.15.0 | VAST request URI, escaped text | other | 9 | 0 | 0 | 0 | 9 | 0 | 9 |
Pixel macros left literal, by set:
- vast-client-js 6.5.0: 4.3 set 0; other set 5 (GPPSECTIONID, GPPSTRING, PLAYBACKMETHODS, STOREID, STOREURL).
- video-ad-sdk 4.0.1: 4.3 set 38; other set 5 (GPPSECTIONID, GPPSTRING, PLAYBACKMETHODS, STOREID, STOREURL).
- vastlint-client 0.15.0: 4.3 set 38; other set 5 (GPPSECTIONID, GPPSTRING, PLAYBACKMETHODS, STOREID, STOREURL).
Of vast-client-js's five literal pixel macros, three were on the list when 4.3 was published (PLAYBACKMETHODS, STOREID, STOREURL) and two were added after it (GPPSECTIONID, GPPSTRING).
3. Every verdict, by client and by duty group
Every verdict is on two pages of these Online Resources, built from the reference results (Node.js layer and Chromium 141 on Linux; Firefox 142 and WebKit 26 added in the grid):
- Full results grid: Table R5.4 (every verdict, by requirement and configuration, with duty-group filters: the by-duty view), Table R5.5 (every deviating cell with its detail) and the tables of the paper built from the same cells.
- Every verdict by client: Table R5.7, one row per requirement and configuration (1,404 rows) with the oracle detail of every deviating or n/a cell.
4. Sensitivity of the must-level counts to strength labels, per configuration
Computed from the Node.js and Chromium reference matrices with the strengths of code/harness/suite/requirements.mjs; Section 5.1.6 of the paper summarizes it. Each configuration is counted once: the seven open-source configurations in Chromium 141 and vastlint-client under Node.js. Cells are must-level deviating cells. A scenario relabels requirements; the deviating cells themselves do not change, only their strength.
Table R5.3. Sensitivity of the must-level counts to strength labels, per configuration
| vast-client-js 6.5.0 (Chromium) | 3 | 2 | 1 | 2 | 3 |
|---|---|---|---|---|---|
| video-ad-sdk 4.0.1 (Chromium) | 16 | 15 | 13 | 13 | 17 |
| iab-vast-loader 2.5.1, defaults (Chromium) | 5 | 4 | 3 | 4 | 5 |
| iab-vast-loader 2.5.1, noSingleAdPods (Chromium) | 4 | 3 | 2 | 3 | 4 |
| vastlint-client 0.15.0 (Node.js) | 11 | 10 | 10 | 9 | 11 |
| Shaka Player 5.2.12 (Chromium) | 21 | 21 | 20 | 17 | 21 |
| rmp-vast 17.2.0, defaults (Chromium) | 12 | 11 | 10 | 8 | 12 |
| rmp-vast 17.2.0, omidSupport (Chromium) | 11 | 10 | 9 | 7 | 11 |
| Google IMA HTML5 3.794.0 (Chromium), closed comparison | 4 | 4 | 4 | 4 | 4 |
| Total, eight configurations | 83 | 76 | 68 | 63 | 84 |
Order of the configurations by must-level deviations:
- (a) M12 should: no pair changes order
- (b) M12, P01, P07 should: 2 pairs change order or tie (rmp-vast 17.2.0, defaults (Chromium) and vastlint-client 0.15.0 (Node.js); rmp-vast 17.2.0, omidSupport (Chromium) and vastlint-client 0.15.0 (Node.js)), within 1 deviation
- (c) macro-list rule: M01, M02, M03, M11, M12 should: 2 pairs change order or tie (rmp-vast 17.2.0, defaults (Chromium) and vastlint-client 0.15.0 (Node.js); rmp-vast 17.2.0, omidSupport (Chromium) and vastlint-client 0.15.0 (Node.js)), within 2 deviations
Clients involved in any change of order: rmp-vast, vastlint-client.
IMA (Chromium) has 4 must-level deviations in every scenario.