VASTlint

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-1

Before 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-1

The 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

Related macros

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.xml

Use 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.

Further reading