@verse8/ads-parent
v0.2.0
Published
Verse8 web shell parent module — relays ad requests between game iframe and SSV verifier
Downloads
336
Maintainers
Readme
@verse8/ads-parent
Verse8 web shell parent module. Runs inside https://verse8.io and brokers
the postMessage relationship between the Verse8 game iframe and the SSV
verifier worker.
Architecture overview: see
../ads/ARCHITECTURE.mdfor how this package fits with the unified SDK (which absorbed the old@verse8/ads-h5-rendererpackage in v0.3.0), mobile parent, and verifier worker.
What it does
- Receives
VERSE8_ADS_PING/VERSE8_ADS_SHOW_*/VERSE8_ADS_RENDER_RESULTfrom the game iframe. - Replies with
VERSE8_ADS_PONGwithin 500 ms. WhenadSenseClientIdis configured, includes it in the PONG payload so the SDK's built-in H5 listener (since@verse8/[email protected]) installs itself. - Dispatches
VERSE8_ADS_RENDER_H5_REWARDED/VERSE8_ADS_RENDER_H5_INTERSTITIALto the SDK's in-iframe H5 listener. - For rewarded ads: when the renderer reports
viewed, pollsGET {verifierBaseUrl}/ads/status?requestId=…until SSV is verified, then forwardsVERSE8_ADS_RESULT { status:'rewarded', reward }to the SDK. - For interstitial ads: forwards
VERSE8_ADS_RESULTimmediately based on the renderer outcome (no SSV polling). - On mobile bridges (e.g.
window.FlutterVerse8Adsinjected by the Flutter app), the parent is a no-op — the native bridge owns the lifecycle.
Quick start
import { startVerse8AdsParent } from "@verse8/ads-parent";
const handle = startVerse8AdsParent({
iframeSelector: "#game-frame",
gameOrigin: "https://a.verse8.games",
verifierBaseUrl: "https://ads-verifier.verse8.io",
ssvWaitMs: 5000,
onTelemetry: (event) => {
console.log("[ads-parent]", event.type, event);
},
});
// On unmount / page nav:
handle.stop();Or via the IIFE bundle (loads window.Verse8AdsParent):
<script src="https://unpkg.com/@verse8/[email protected]/dist/index.global.js"></script>
<script>
Verse8AdsParent.startVerse8AdsParent({
iframeSelector: "#game-frame",
gameOrigin: "https://a.verse8.games",
verifierBaseUrl: "https://ads-verifier.verse8.io",
});
</script>API
startVerse8AdsParent(config: ParentConfig): { stop(): void }
| Field | Type | Default | Notes |
|---|---|---|---|
| iframeSelector | string | — | CSS selector for the game iframe element. |
| iframeWindow | HTMLIFrameElement \| Window | — | Alternative to iframeSelector. |
| gameOrigin | string | required | Expected child origin (used as targetOrigin and trusted inbound origin). |
| verifierBaseUrl | string | required | Base URL of the ads-verifier worker. |
| ssvWaitMs | number | 5000 | Total budget for /ads/status polling. |
| onTelemetry | (event) => void | — | Analytics hook. Errors thrown here are swallowed. |
| trustedIframeOrigins | string[] | [] | Additional origins to accept (in addition to gameOrigin). |
Either iframeSelector OR iframeWindow must be supplied — both are
acceptable; if both are present, iframeWindow wins.
Telemetry events
type TelemetryEvent =
| { type: 'ping'; requestId }
| { type: 'show'; adType: 'rewarded'|'interstitial'; placementId; requestId }
| { type: 'render_dispatched'; requestId }
| { type: 'renderer_result'; requestId; outcome: 'viewed'|'dismissed'|'not-ready'|'failed' }
| { type: 'ssv_polling'; requestId }
| { type: 'ssv_arrived'; requestId }
| { type: 'ssv_timeout'; requestId }
| { type: 'result_dispatched'; requestId; status: 'rewarded'|'dismissed'|'failed' };Wire protocol
This package implements the parent half of the protocol documented in
@verse8/ads/PROTOCOL.md, plus the new render-plane
envelopes:
| Direction | Type | Payload |
|---|---|---|
| Iframe → Parent | VERSE8_ADS_PING | { sdkVersion? } |
| Iframe → Parent | VERSE8_ADS_SHOW_REWARDED | { placementId } |
| Iframe → Parent | VERSE8_ADS_SHOW_INTERSTITIAL | { placementId } |
| Iframe → Parent | VERSE8_ADS_RENDER_RESULT | { outcome, reason? } |
| Parent → Iframe | VERSE8_ADS_PONG | { platform: 'web' } |
| Parent → Iframe | VERSE8_ADS_RENDER_H5_REWARDED | { placementId } |
| Parent → Iframe | VERSE8_ADS_RENDER_H5_INTERSTITIAL | { placementId } |
| Parent → Iframe | VERSE8_ADS_RESULT | { status, reward?, error? } |
Origin validation runs BEFORE any payload inspection. Unknown / malformed envelopes are silently dropped.
Environment detection
The parent module short-circuits to a no-op handle when:
typeof window === 'undefined'(SSR / Node)window.FlutterVerse8Adsis defined (the Flutter app's JS channel marker — the native bridge handles ad lifecycle directly)
In both cases, startVerse8AdsParent returns { stop: () => {} } immediately
without installing listeners.
Test helpers (dev only)
Convenience wrappers for E2E shells, demos, and fixture pages live on a separate sub-path so production bundles can tree-shake them out:
import { startTestParent, GOOGLE_TEST_PUBLISHER_ID } from "@verse8/ads-parent/test-helpers";
const handle = startTestParent({
iframeSelector: "#game-frame",
gameOrigin: "https://a.verse8.games",
verifierBaseUrl: "https://ads-verifier.verse8.io",
});These wrappers default to Google's public test publisher ID, enable
adBreakTestMode, and short-circuit the SSV verifier via skipResultUpload.
Not for production — skipResultUpload bypasses the server-side
verification boundary.
Bundle size
IIFE bundle target: < 12 KB gzipped.
License
MIT
