In-game ads integration
Last updated: 2026-08-11
Integrate Banner, interstitial, and rewarded ads through the PlayNova host bridge. Your game runs in an iframe and talks to the host with postMessage — do not embed third-party ad SDKs inside the package.
How monetization works
PlayNova fills ads on the host side and shares revenue with certified creators (default 70% creator share). Games only request show/load; the host handles inventory, frequency caps, and impression/click reporting.
Envelope for every message:
{ "source": "...", "type": "...", "payload": { } }- Games must set
sourcetoplaynova-game - The host replies with
sourceplaynova-host
Ad formats:
- Rewarded — player opt-in (revive, double reward, free item). Grant rewards only after
ads.rewarded_completed. - Interstitial — natural breaks (level complete / game over). Never mid-input.
- Banner — host-owned strip; game only requests show/hide.
Recommended placements
Always pass a stable placement string for analytics and caps. Prefer the platform names below:
| Placement | Use case |
|---|---|
revive | Continue after fail |
double_reward | End-of-level bonus |
free_item / unlock | Consumable or content unlock |
level_complete / level_start / game_over / pause | Interstitial moments |
banner_bottom / banner_top | Banner slots |
Integration flow
- On a natural break, call
ads.load_*withplacement(and optionalrequestId). - Wait for
ads.*_loaded(or handle*_failedand continue without ads). - Call
ads.show_*with the samerequestId/placement. - For rewarded, mutate game state only on
ads.rewarded_completed. On dismissed/failed, do not grant the reward.
Bridge message types
Canonical type strings are defined in playnova-web (ads-bridge). Keep your game package aligned with these exact values.
Game → host
| type | Purpose |
|---|---|
ads.load_rewarded | Preload rewarded inventory |
ads.show_rewarded | Show rewarded (grant only after completed) |
ads.load_interstitial | Preload interstitial |
ads.show_interstitial | Show interstitial at a break |
ads.show_banner | Request host banner visible |
ads.hide_banner | Hide host banner |
ads.preload | Preload multiple formats |
ads.get_banner_height | Query banner height for layout |
Host → game
| type | Purpose |
|---|---|
ads.rewarded_loaded | Rewarded ready to show |
ads.rewarded_failed | Rewarded load/show failed |
ads.rewarded_completed | User finished rewarded — safe to grant |
ads.rewarded_dismissed | User closed rewarded early — do not grant |
ads.interstitial_loaded | Interstitial ready |
ads.interstitial_failed | Interstitial failed |
ads.interstitial_closed | Interstitial closed |
ads.banner_shown | Banner is visible |
ads.banner_hidden | Banner hidden |
ads.banner_failed | Banner failed |
Copy-paste helper
Drop this into your index.html (or module). Replace reward grant with your own game logic.
function pnAds(type, payload) {
parent.postMessage({ source: 'playnova-game', type, payload }, '*');
}
function onPnHost(handler) {
window.addEventListener('message', (e) => {
const d = e.data;
if (!d || d.source !== 'playnova-host') return;
handler(d);
});
}
// Example: revive flow
pnAds('ads.load_rewarded', { placement: 'revive' });
onPnHost((msg) => {
if (msg.type === 'ads.rewarded_loaded') {
pnAds('ads.show_rewarded', {
requestId: msg.payload && msg.payload.requestId,
placement: 'revive',
reward: { type: 'life', amount: 1 },
});
}
if (msg.type === 'ads.rewarded_completed') {
// grant reward ONLY here
}
});Production rules
- Do not auto-click, force-loop, or obscure Close / Skip controls.
- Do not grant rewards unless you received
ads.rewarded_completedfor thatrequestId. - Respect host failures: if inventory is empty, continue the game gracefully.
- Prefer load ahead of show so players wait less at the trigger moment.
- Keep packages free of third-party ad SDKs, trackers, or pop-under scripts.
- Interstitial frequency is enforced by the host; spam show calls may be ignored.
FAQ
Can I use AdMob / Unity Ads inside the zip?
No. PlayNova aggregates demand on the host. Embedding other SDKs will fail review and breaks iframe sandbox assumptions.
What if the host does not answer?
Treat silence or *_failed as no-fill. Continue gameplay without blocking the player on an endless spinner.
Where do I see revenue?
After ads are live in production, impressions and revenue roll into creator analytics. Settlement follows the creator program terms.
Host bridge is live on the play page. Message types above are the production contract — implement against them now.
