Without Prebid.js (passing VAST directly)
The player is ad-source-agnostic. All it needs to play is a VAST tag URL (vastUrl) or inline VAST XML (vastXml). Prebid.js is just one way to fetch VAST — it is not required.
If you already have the VAST, you can pass it straight to the player regardless of where it came from (a direct ad server tag, your own backend, another header bidding wrapper, or a direct-deal creative).
All the player needs is VAST
The player has no RTB and no bidding logic. Obtaining the VAST is left to your setup; the player handles only "playback, viewability, and reward granting."
The minimal bid
The bid you pass to the player has the following shape. Specify either vastUrl or vastXml, but not both.
const bid = {
mediaType: "video",
adUnitCode: "reward-slot", // any identifier (used for measurement logs, etc.)
vastUrl: "https://adserver.example.com/vast?...", // VAST tag URL
// or: vastXml: "<VAST>…</VAST>" // inline VAST XML
width: 640,
height: 360,
};width/heightare the expected ad dimensions. During playback the player follows the actual ad's aspect ratio.adUnitCodecan be any string. It is not used as an identifier to call RTB.
Reward: pass a VAST tag URL
Just pass the VAST tag URL returned by your ad server (any) into vastUrl.
<div id="reward-slot"></div>
<script src="https://cdn.michao-ssp.com/player/v1/reward.js"></script>
<script>
window.michao.createRewardPlayer({
target: "reward-slot",
bid: {
mediaType: "video",
adUnitCode: "reward-slot",
vastUrl: "https://adserver.example.com/vast?...",
width: 640,
height: 360,
},
reward: "50 coins",
callbacks: { onReward: () => grantReward() },
});
</script>import { createRewardPlayer } from "https://cdn.michao-ssp.com/player/v1/reward.mjs";
const handle = createRewardPlayer({
target: "reward-slot",
bid: {
mediaType: "video",
adUnitCode: "reward-slot",
vastUrl: "https://adserver.example.com/vast?...",
width: 640,
height: 360,
},
reward: "50 coins",
callbacks: { onReward: () => grantReward() },
});
const result = await handle.result; // "rewarded" | "dismissed" | "failed"Reward: pass inline VAST XML
If you already hold the VAST XML directly — for example from your own backend or server-side bidding — pass it straight into vastXml.
const vastXml = await fetch("/api/ad").then((r) => r.text()); // <VAST>…</VAST>
createRewardPlayer({
target: "reward-slot",
bid: {
mediaType: "video",
adUnitCode: "reward-slot",
vastXml,
width: 640,
height: 360,
},
reward: "50 coins",
callbacks: { onReward: () => grantReward() },
});Outstream
Outstream works the same way — just pass a VAST tag URL or inline XML.
import { createOutstreamPlayer } from "https://cdn.michao-ssp.com/player/v1/outstream.mjs";
const handle = createOutstreamPlayer({
target: "feed-slot",
bid: {
mediaType: "video",
adUnitCode: "feed-slot",
vastUrl: "https://adserver.example.com/vast?...",
width: 640,
height: 360,
},
onEnd: "collapse",
});
await handle.done; // "completed" | "failed" | "dismissed"Macros and cache busting
If the VAST tag URL contains a cache buster (such as [CACHEBUSTING]) or page-info macros, macro expansion is the caller's responsibility. The player loads vastUrl as-is, so pass an already-expanded URL.
const vastUrl = template
.replace("[CACHEBUSTING]", String(Math.floor(Math.random() * 1e10)))
.replace("[PAGE_URL]", encodeURIComponent(location.href));Macros inside the VAST's impression / tracking URLs (such as [TIMESTAMP]) are filled in automatically by the player when the trackers fire.
Caveats
- Google IMA mode (
mode: "ima") does not work with directly passed VAST. IMA requires a Google Ad Manager (GAM) video ad tag URL. See Google IMA mode for details. With standard VAST playback (normal), you can pass raw VAST directly as shown here. - Banners (display) have no VAST. A display creative is markup, and rendering is done by the caller. See Banner reward.
- For the wiring when you fetch VAST with Prebid.js, see Prebid.js integration.
See the API reference for details on each option.