VAST macros / Ad and pod
[ADCATEGORIES] VAST macro
Short answer: Category codes declared on the ad, comma-separated and percent-encoded. Introduced in VAST 4.1.
What it means
Resolves to the category codes from the ad's Category elements. Commas are encoded as %2C because the list sits inside a query parameter.
Example value
After the player substitutes the macro, [ADCATEGORIES] becomes something like:
IAB7%2CIAB7-1Before and after the player substitutes it
The first line is the URL in the tag. The second line is the request the player sends once it has a value.
https://t.example.com/i?cats=[ADCATEGORIES]
https://t.example.com/i?cats=IAB7%2CIAB7-1The ad's categories, not the video's
[ADCATEGORIES] resolves to the codes on the ad's Category elements, comma-separated and percent-encoded. VAST 4.1 added the macro. A comma has to travel as %2C. A log line that shows IAB7,IAB7-1 with a raw comma has been split by the query parser, and the second code is now its own parameter or part of the next one.
These codes describe the advertised product, which is what competitive separation uses. They do not describe the content the ad ran against. Content categories are a different signal, on the content object in the bid, and they do not appear in this macro. [BLOCKEDADCATEGORIES] is the publisher's block list, also different. A brand-safety decision made from [ADCATEGORIES] alone is using the ad's declaration about itself.
The authority is not in the value
Each Category element can carry an authority attribute, the URI of the taxonomy that issued the code. The macro substitutes the codes. It does not substitute the authority. Two ads can both produce IAB7 under different taxonomies, and the pixel cannot tell them apart. If the downstream system needs the taxonomy, it has to be agreed out of band or read from the tag, not from this parameter.
An ad with no Category elements leaves the macro empty. An empty cats= parameter is not the same as a declaration of uncategorized. It is the absence of the element. Competitive separation that treats empty as safe will pass ads that never declared a category.
What the player sends
One category or many, the encoding is the same. The authority attributes stay in the XML.
The request carries cats=IAB7%2CIAB7-1. The authority URI is not in that string.
<Category authority="https://www.iab.com/guidelines/content-taxonomy">IAB7</Category>
<Category authority="https://www.iab.com/guidelines/content-taxonomy">IAB7-1</Category>
<Impression><![CDATA[https://t.example.com/i?cats=[ADCATEGORIES]]]></Impression>VAST XML fragment only. This excerpt belongs inside a complete VAST document, so standalone validation will fail until it is wrapped in a full <VAST>response.
Where it is valid
Impression and tracking URLs. The authority for those codes is an attribute on Category, and it is not part of this macro.
Macros are case-sensitive and substituted only inside URL fields. A macro written in the wrong case, or placed where it has no defined value, is sent to the server as literal text instead of a value.
Using it in a tag
<Category authority="https://www.iab.com/taxonomy">IAB7</Category>
<Impression><![CDATA[https://t.example.com/i?cats=[ADCATEGORIES]]]></Impression>VAST XML fragment only. This excerpt belongs inside a complete VAST document, so standalone validation will fail until it is wrapped in a full <VAST>response.
Related vastlint rules
- VAST-2.0-macro-unknown: URL contains a [MACRO] that is not a recognised IAB VAST macro
- VAST-2.0-macro-lowercase: Recognised macro is not uppercase — players match macro names case-sensitively
- VAST-2.0-macro-uri-unencoded: Macro-bearing URL contains characters that must be percent-encoded per RFC 3986
Related macros
- [BLOCKEDADCATEGORIES]: Categories the publisher has blocked for this request.
- [ADTYPE]: The type of ad: video, audio, or hybrid.
Validate your macros
vastlint flags unknown, mis-cased, deprecated, out-of-context, and unencoded macros in any tracking, click, error, impression, or media URL:
# CLI: exits non-zero on errors, ideal for pipelines
vastlint check creative.xmlUse the right tool for this failure
If you already have the resolved XML, run a pure spec check. If you only have a live tag URL, test that endpoint first. If the failure happens in the wrapper chain, inspect each hop.