Skip to main content
Integration for HTML5 Sites/Apps Updated Jun 8

Advanced: Faster Ad Loading (Preload)

By default, initializeAndOpenPlayer() does all of its work after the click: it runs the ad auction, requests the video, and buffers the creative, then reveals the player. On slower networks that can take a few seconds, and the user is staring at a spinner the whole time.

The preloadAd() API splits that work in two. You do the slow part — the auction and video request — ahead of the click, on a high-intent signal. The click itself only reveals an ad that is already loaded, which brings click-to-reveal down from ~1.5–3.5s to roughly 100–300ms. This is the same pattern used by Poki, CrazyGames, and Google H5 Games Ads.

How it works

<script type="text/javascript">
const options = {
apiKey: "xxxx-xxxx-xxxx-xxxx", // Replace with your actual API key
injectionElementId: "some-id", // The ID of the div from Step 2
adStatusCallbackFn: (status) => {
if (status.type === "complete") {
// Grant the reward here (see Step 4)
}
},
adErrorCallbackFn: (error) => {
console.log("Error: ", error.getError().data);
},
};

let adHandle = null;

// 1. Preload early — on a high-intent signal, NOT on page load.
async function loadAd() {
try {
adHandle = await preloadAd(options); // runs the auction + video request now
} catch (e) {
adHandle = null; // no-fill or network error — fall back on click
}
}

// 2. On click, just reveal the already-loaded ad.
document.getElementById("watch-ad").addEventListener("click", async () => {
if (adHandle) {
await adHandle.show(); // ~100–300ms
adHandle = null; // each handle is single-use
loadAd(); // preload the next one for the next click
} else {
initializeAndOpenPlayer(options); // fallback: the standard (slower) path
}
});
</script>

preloadAd(options) takes the same options object as initializeAndOpenPlayer() and returns a handle { show }. Call show() from inside your click handler to reveal the ad.

Three rules for using it well

  1. Preload on a high-intent signal, not on page load. Good triggers: a reward modal mounting, a level-complete screen, an "out of coins" overlay, a "watch ad to double your reward" prompt appearing. Preloading on page load wastes ad requests on visitors who never click.

  2. Always keep an on-click fallback. Roughly 10–30% of preloads will no-fill or fail. If the handle is missing or the promise rejected, fall through to initializeAndOpenPlayer() for one best-effort try — never call show() on a failed preload.

  3. Re-preload after each show. Each handle is single-use. Right after show() resolves (or in your reward callback), call preloadAd() again to have the next ad ready for the next click.

Pattern: an always-visible "Watch Ad" button

If your "Watch Ad" button is on screen for most of the session, there's no single intent moment — the button itself is the intent. Keep an ad loaded while the button is visible:

let adHandle = null;
let lastRefresh = 0;

async function refreshAd() {
try {
adHandle = await preloadAd(options);
lastRefresh = Date.now();
} catch (e) {
adHandle = null; // fall back to the on-click path
}
}

refreshAd(); // when the button first renders
setInterval(refreshAd, 4 * 60 * 1000); // keep it fresh (bids expire ~5 min)

document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "visible" && Date.now() - lastRefresh > 60000) {
refreshAd(); // refresh on return, but not while backgrounded
}
});

watchBtn.addEventListener("click", () => {
if (adHandle) { adHandle.show(); adHandle = null; refreshAd(); }
else initializeAndOpenPlayer(options); // fallback
});

Things to keep in mind

  • Bids expire (~5 minutes). If the gap between preloadAd() and show() is longer than the bid's lifetime, the video URL can fail. Refresh on a timer (as above) or re-call preloadAd() on the next intent signal.
  • Preload uses an ad request. Each preloadAd() call runs a real auction. Triggering it on genuine intent (rather than on every page load) keeps that efficient. For low-traffic games, a lighter option is to preload on hover / touchstart of the button — it fires ~50–200ms before the click for a partial speed-up without the polling.
  • It can fail silently. In Incognito or with third-party cookies blocked, the auction may fail without throwing. The on-click fallback (rule 2) is what keeps the experience working in those cases.
  • Don't break the click gesture. show() must be called from inside your click/tap handler (as in the examples). The preload does the network work in the background; the reveal stays bound to the user's tap, which keeps it working on iOS/Safari.

When you don't need this

If your ad is triggered by a deliberate, one-off action where a short wait is acceptable (e.g. an end-of-run "continue?" screen), the standard initializeAndOpenPlayer() from Step 3 is simpler and perfectly fine. Reach for preloadAd() when the speed of the reveal matters — frequent rewarded prompts, fast-paced loops, or an always-visible watch button.