VAST Tag Integration Spec
If your inventory terminates at SpringServe, Publica, or any other CTV SSAI / ad-stitching platform that only speaks VAST tag URLs, use this endpoint instead of our oRTB one. The auction, demand partners, IVT scoring, and caps are identical — only the request format changes.
Tag generator
Pick your ad server and floor tier, and we’ll build the exact tag URL — with the right macro syntax for the platform — that you can paste straight into your demand-tag config.
Test this URL Fire a live request with sample device values
The endpoint
GET https://rtb.vuukle.com/vast?pub=<YOUR_PUBLISHER_ID>&plc=<TAG>&<macros...>| Setting | Value |
|---|---|
| Method | GET |
| Content-Type returned | application/xml; charset=utf-8 |
| Protocol | VAST 4.2 (backwards compatible to 4.0 / 3.0 players) |
| Recommended client timeout | 1200 ms (we cap server-side at 1500 ms) |
| Auction model | First-price (at: 1) |
| No-fill response | Empty <VAST version="4.2"></VAST> with HTTP 200 |
Required parameters
The minimum viable tag — just three values:
https://rtb.vuukle.com/vast?pub=<YOUR_PUBLISHER_ID>&plc=<TAG>&ifa={IFA}| Parameter | Required | What it is |
|---|---|---|
pub | Yes | Your Vuukle Publisher ID. Issued during onboarding. |
plc | Recommended | Placement tag — typically a floor tier (tier_6, tier_10, tier_15) or your own slot name. Defaults to default if omitted. |
ifa | Yes for fill | Device advertising ID. Without an IFA, ~95% of CTV demand will no-bid. Use whichever macro your SSAI substitutes. See aliases. |
Recommended parameters
Everything else is optional, but each one materially improves bid rate and CPM. Pass what your SSAI can provide.
| Parameter | What it is | Why it matters |
|---|---|---|
bundle | App bundle / store ID (e.g. com.fawesome.tv) | Required for app-level allowlists at every major DSP. |
app_name | Human-readable app name | Used by DSPs for app-level brand-safety pre-checks. |
storeurl | App’s store URL | DSPs cross-reference against their own app catalogs. |
ua | Device User-Agent | We classify this for IVT scoring; DSPs use it for device targeting. |
ip | Device public IP | We fall back to Cloudflare’s CF-Connecting-IP if you don’t supply it. |
w, h | Player width × height | Defaults to 1920×1080. CTV-specific sizing affects creative selection. |
cc | ISO-2 country code | We fall back to Cloudflare’s IP-derived country. Explicit value is preferred. |
content_id, content_title, content_genre | Content metadata | DSPs use these for contextual targeting and brand-safety. |
gdpr_consent | TCF v2 consent string | Required to receive bids from EU traffic. |
us_privacy | CCPA string (e.g. 1YNN) | Required for California traffic to receive bids from privacy-strict DSPs. |
coppa | 1 for child-directed content | Switches the request to COPPA-compliant demand only. |
Supported parameter aliases
SpringServe, Publica, and the long tail of platforms each use slightly different param names for the same signal. Our endpoint accepts every common variant — use whichever your SSAI substitutes natively, no remapping required.
| Logical field | Aliases we accept |
|---|---|
| Publisher ID | pub, pub_id, publisher_id |
| Placement / tag | plc, tag, tag_id, tagid, placement, placement_id |
| IFA | ifa, device_ifa, did, device_id, deviceid, idfa, rida, advertising_id |
| IFA type | ifa_type, ifatype, idtype |
| Bundle | bundle, app_bundle, appbundle, app_id, appid |
| App name | app_name, appname |
| Store URL | storeurl, store_url, app_store_url |
| IP | ip, device_ip, deviceip, ipaddress |
| User-Agent | ua, user_agent, useragent, browser |
| Width / Height | w/h, width/height, player_width/player_height |
| Country | cc, country, geo_country, ip_country |
| Content ID | content_id, contentid, cid |
| Content title | content_title, content_name, contenttitle |
| Content genre | content_genre, contentgenre, genre |
| GDPR consent | gdpr_consent, consent, tcstring |
| CCPA / US privacy | us_privacy, usprivacy, uspriv, ccpa |
| COPPA / Kids | coppa, kids |
| Cachebuster | cb, cachebuster, cache_buster, random |
Device & IFA conventions
CTV device classes each use a different ID standard. If you don’t pass ifa_type explicitly, we infer it from the User-Agent — but passing both is more reliable.
| Device family | IFA standard | ifa_type value | UA contains |
|---|---|---|---|
| Roku | RIDA | rida | Roku |
| Fire TV | AFAI | afai | AFTSS, AFTOLC, AFTHA, AFTS, Fire OS |
| Samsung Smart TV | TIFA | tifa | Tizen |
| LG WebOS | LGUDID | lgudid | webOS |
| Apple TV | IDFA | idfa | AppleTV |
| Android (mobile / Google TV) | AAID | aaid | Android |
| iOS (iPhone / iPad) | IDFA | idfa | iPhone, iPad |
Platform-specific config
In SpringServe, create a new Demand Tag (RTB) with:
- Tag URL:
https://rtb.vuukle.com/vast?pub=<YOUR_PUBLISHER_ID>&plc=<TAG>&ifa={IFA}&bundle={APP_BUNDLE}&app_name={APP_NAME}&storeurl={APP_STORE_URL}&ua={USER_AGENT}&ip={IP}&w={WIDTH}&h={HEIGHT}&cc={IP_COUNTRY}&content_id={CONTENT_ID}&content_genre={CONTENT_GENRE}&gdpr_consent={GDPR_CONSENT}&us_privacy={US_PRIVACY}&cb={CACHEBUSTER}
- Request type: GET
- Timeout: 1200 ms
- Floor CPM: match the
plctier (e.g.tier_6⇒ $6.00 floor) - VAST version: 4.0 or higher
SpringServe substitutes the {MACRO} tokens before firing. You do not need to URL-encode the macros yourself.
In Publica, create a new Demand Source of type VAST URL with:
- VAST URL:
https://rtb.vuukle.com/vast?pub=<YOUR_PUBLISHER_ID>&plc=<TAG>&ifa=[IFA]&bundle=[BUNDLE]&app_name=[APP_NAME]&storeurl=[APP_STORE_URL]&ua=[USER_AGENT]&ip=[IP]&w=[WIDTH]&h=[HEIGHT]&cc=[COUNTRY]&content_id=[CONTENT_ID]&content_genre=[CONTENT_GENRE]&gdpr_consent=[GDPR_CONSENT]&us_privacy=[US_PRIVACY]&cb=[CACHEBUSTER]
- Method: GET
- Timeout: 1200 ms
- Floor CPM: match the
plctier - Currency: USD
Publica uses [MACRO] syntax (bracketed) rather than {MACRO} — both work the same way once substituted.
For any other SSAI platform, the spec is just:
- HTTP
GETto the URL above with the publisher’s chosen macro syntax. - Substitute
{IFA}/[IFA]/%%IFA%%etc. with the real device ID at request time. - We accept the same payload regardless of the macro delimiters the SSAI used.
If your platform is exotic and a macro name we don’t list above is being used, contact us at adops@vuukle.com — we’ll add the alias.
Response shapes
On a winning bid
HTTP 200 with Content-Type: application/xml; charset=utf-8.
We return the winning DSP’s inline VAST verbatim, with our own <Impression> element injected for caps + IVT confirmation. The bidder’s MediaFiles, tracking events, and clickthrough are untouched.
<?xml version="1.0" encoding="UTF-8"?><VAST version="4.2"> <Ad id="..."> <InLine> <AdSystem>pubmatic</AdSystem> <AdTitle>...</AdTitle> <Impression id="vuukle"><![CDATA[https://rtb.vuukle.com/event/imp?rid=...]]></Impression> <Impression><![CDATA[https://dsp-tracking-url/...]]></Impression> <Creatives> <Creative> <Linear> <Duration>00:00:30</Duration> <MediaFiles> <MediaFile type="video/mp4" width="1920" height="1080">...</MediaFile> </MediaFiles> </Linear> </Creative> </Creatives> </InLine> </Ad></VAST>We also set these response headers:
X-Request-ID— auction request UUID, useful for our support teamCache-Control: no-store, max-age=0— prevents SSAI cross-user cache hits
On no-bid / cap-blocked / placement-disabled
HTTP 200 with an empty VAST document — the CTV-standard “no fill” response:
<?xml version="1.0" encoding="UTF-8"?><VAST version="4.2"></VAST>If the request was blocked by our internal caps (per-tag / per-IFA / per-revenue), we also include:
X-Vuukle-Block-Reason: <reason>— one oftag_imps_capped,ifa_freq_capped,revenue_capped
This is informational; SSAI platforms don’t read it.
Internal controls
These run on every VAST request, identical to the oRTB path:
- Default impression caps — 50,000 imps/tag/day, 5 imps/IFA/day, $500 revenue/day. Auto-loosened after a 7-day warm-up. Tunable per publisher.
- IVT signal capture — one compact row per request to ClickHouse: Cloudflare bot score, threat score, country, ASN, UA classification, IFA presence, outcome. Used for the IVT panel on your dashboard.
- Schain construction — server-side. Your
asi=vuukle.comentry is preserved through the demand chain. - IPD enrichment — per-bundle
inventorypartnerdomainis injected based on your seller declaration. You don’t need to send this.
FAQ
Do you support VPAID? No — CTV devices don’t run JavaScript, so VPAID is irrelevant for this endpoint. VAST 4.2 inline / wrapper only.
Do you support VMAP playlists? Not yet on this endpoint — most CTV inventory is single-slot pods. If your SSAI needs a VMAP playlist (pre-roll + mid-rolls + post-roll), contact us and we’ll prioritize it.
Can we use this endpoint for web preroll inventory?
Yes, but pass bundle as your site domain (e.g. bundle=example.com) and ua as the desktop/mobile browser UA. We auto-classify the request as CTV by default; for web-video traffic we’ll switch the inferred devicetype based on UA.
What happens if the macro doesn’t get substituted?
If {IFA} reaches us unsubstituted, we treat it as missing and fall back to header-derived signals where possible. The request will still complete but will mostly no-bid. Check your SSAI’s macro config first.
Can we point both oRTB and VAST at the same Publisher ID? Yes — recommended. The reporting dashboard aggregates both.
What’s the latency budget? End-to-end p95 is ~750 ms (Cloudflare → edge → Prebid Server → 2-3 DSPs → response). Set your SSAI client timeout to 1200 ms minimum to leave headroom.
Do we need to handle wrapper redirects?
Only if the winning DSP returned a wrapper-style VAST tag URL (adm is a URL rather than inline XML). We construct a proper <Wrapper> doc pointing at it; the SSAI handles the follow.
Need help?
- Operational questions: adops@vuukle.com
- Technical / integration: tech@vuukle.com
- Reference your Publisher ID in any support thread for fastest resolution.