Advertising cards
A WebApp can temporarily replace the playlist on an approved Advertising screen on the same kiosk. The operator chooses the media and allowed keys; the WebApp requests a key.
Start here · Bridge reference · Complete Markdown
Configure the receiving screen first
For example, a lower touchscreen runs your game while the upper display runs Advertising.
- Assign your external WebApp to its screen and an Advertising playlist to the receiving screen.
- In Monitors, select the Advertising screen, then its Advertising tab.
- Open Playback → Edit playback → WebApp cards.
- Under Allow a WebApp to show cards, select the assigned source WebApp. Default is Off.
- Select the Allowed cards keys and save.
- In the receiving screen's Cards view, configure the fleet default or screen override media for a custom key such as
jackpot. Wait for the kiosk to download/apply that content before testing.
The source WebApp must run on another monitor. Its audience/origin approval and the target's card permission are separate requirements.
Standard keys are loading, webapp_error, offline, needs_service, and paused; they have built-in fallback visuals. Custom keys need configured media. Keys must match [a-z][a-z0-9_]{1,31}: 2–32 characters, starting with a lowercase letter, then lowercase letters, digits, or underscores.
Show and clear a card: showCard / clearCard
const bridge = await getKioskBridge(); // Helper from Start here.
const result = await bridge.showCard({
key: "jackpot",
seconds: 60
});
// result: { screens: ["<TARGET_SCREEN_ID>"], seconds: 60, key: "jackpot" }
// When this WebApp's card is no longer needed:
await bridge.clearCard();
seconds defaults to 300 and must be an integer from 1 to 300. Zero, fractions, larger durations, and extra option fields are rejected. key is required.
The page cannot pass a target monitor, URL, file, HTML, or image. Native code derives the source and targets from the live browser session and operator configuration. These are local bridge calls, not cloud requests.
clearCard() releases only this runtime's own card lease. It does not clear an operator's portal override or another runtime's lease. Success returns { screens: [...], seconds: 0, key: null }; an empty screen list can mean there was no owned lease left to clear.
Pause and resume the playlist: pauseAds / resumeAds
await bridge.pauseAds(); // "paused" card for 300 seconds
await bridge.pauseAds({ seconds: 120 }); // Explicit bounded duration
await bridge.resumeAds(); // Clear this runtime's lease
pauseAds() is the paused card; the receiving screen must allow that key. resumeAds() and clearCard() clear the same owned lease. There is one active WebApp card lease per target, not a stack of independent pause and card requests.
Keep a card up during a longer activity
Renew before expiry while the activity is still running. This example uses one serialized renewal loop and a single cleanup path:
async function holdCardWhile(key, runActivity, onCardError) {
const bridge = await getKioskBridge();
let active = true;
let timer;
let pending = Promise.resolve();
const renew = () => {
pending = bridge.showCard({ key, seconds: 300 })
.then(() => {
if (active) timer = setTimeout(renew, 60_000);
})
.catch(error => {
active = false; // Stop renewing; the bounded lease will expire.
onCardError(error);
});
};
// Fail before starting the activity if the initial request is denied.
await bridge.showCard({ key, seconds: 300 });
timer = setTimeout(renew, 60_000);
try {
return await runActivity();
} finally {
active = false;
clearTimeout(timer);
await pending; // Finish any renewal before clearing.
try {
await bridge.clearCard();
} catch (error) {
onCardError(error); // Do not silently claim that playback resumed.
}
}
}
Use one owner/controller in your app so two activities do not clear each other's lease. Handle cancellation by ending runActivity and running cleanup. Do not use a rapid retry loop when native access is denied.
Expiry, priority, and confirmation
- The lease uses the kiosk's monotonic clock and expires without renewal.
- It does not survive an agent restart or reboot. Configuration, assignment, or runtime revocation can remove it sooner.
- Same-origin navigation can retain the browser runtime; stopping renewal leaves the old card until clear or bounded expiry. Do not depend on an unload handler completing an async clear.
- An operator's portal card has priority over a WebApp card. Clearing your lease may therefore leave the operator's card visible.
- Offline bridge access remains subject to the source WebApp's valid business lease. It does not grant indefinite offline authority.
- A resolved Promise confirms that native control accepted the request. It is not proof of physical pixels. Use the target's reported card state or an explicit screenshot when checking actual display.
- Card transitions appear as
kiosk:card_shownandkiosk:card_clearedin Observations → Events, with the screen, key, and source.
General show/clear controls belong to Advertising. The system's own WebApp error/recovery pages are separate and do not grant arbitrary card control over external WebApp screens.