Quickstart
Add a single script tag to your game’s HTML, then await Glaze.init() before calling anything else. The SDK is exposed globally as Glaze (on window.Glaze). TypeScript types ship alongside the script.
<script src="https://glazegames.com/sdk/v3/glaze.js"></script>
<script>
async function boot() {
// 1. Connect to the platform (or fall back to the local simulator).
const env = await Glaze.init();
console.log('Glaze ready:', env.stage); // 'live' | 'qa' | 'local'
// 2. Tell the platform your splash is done and play has started.
Glaze.game.loadingStop();
Glaze.game.gameplayStart();
}
boot();
</script>Every module call returns a Promise. Calling any method before init() resolves throws — always await Glaze.init() first.
Glaze.init()
Performs the handshake with the Glaze embed page. If no Glaze parent answers within ~1.5s (i.e. you’re running locally), the SDK transparently enters simulator mode and resolves anyway. It’s safe to call init() more than once — the same promise is reused.
const env = await Glaze.init();
// env: SdkEnvironment
// sdkVersion: string
// locale: string // e.g. 'en-US'
// stage: 'qa' | 'live' | 'local' // 'local' === simulator
// host: string
// userAccountAvailable: boolean
Glaze.version; // 'glaze-v3'
Glaze.isSimulator; // true when running outside the platform
Glaze.environment; // the SdkEnvironment, or null before initGame lifecycle events
These events let the platform time ads, measure engagement, and decide when prompts are least disruptive. Fire them honestly — they directly affect your revenue and your QA pass.
Glaze.game.loadingStart(); // assets started loading (optional)
Glaze.game.loadingStop(); // loading done — REQUIRED once ready to play
Glaze.game.gameplayStart(); // a round/level started
Glaze.game.gameplayStop(); // a round/level ended (pause, death, menu)
// Signal a moment of delight (boss killed, level beaten). The platform
// uses these to time non-intrusive prompts.
Glaze.game.happytime();
// Invite / deep links. Build a shareable link with custom params, then
// read them back when a friend opens the game.
const link = await Glaze.game.inviteLink({ room: 'abc123' });
const room = Glaze.game.getInviteParam('room'); // 'abc123' | nullCall loadingStop() exactly once when the game is interactive, and bracket each round with gameplayStart() / gameplayStop().
Ads
Two ad types: 'midgame' (interstitial, e.g. on death or level end) and 'rewarded' (the player opted in for a reward). Mute and pause your game in adStarted, and resume in adFinished / adError.
// Rewarded ad — only grant the reward when it actually finished.
await Glaze.ads.requestAd('rewarded', {
adStarted: () => pauseAndMute(),
adFinished: () => { resume(); grantCoins(100); },
adError: (err) => { resume(); console.warn(err.code); },
});
// Interstitial between rounds.
const { shown } = await Glaze.ads.requestAd('midgame');
// Detect ad blockers so you can adjust your economy / messaging.
const blocked = await Glaze.ads.hasAdblock(); // booleanFor rewarded ads, the promise rejects (and adError fires with code user-cancelled) if the player skips — so never grant the reward in a .catch(). Don’t request ads back-to-back; gate them behind real game moments.
User & authentication
Read the signed-in Glaze player, prompt them to sign in, and listen for auth changes. For server-authoritative features, mint a short-lived JWT with getUserToken() and verify it on your backend.
// Is a player-account system available in this context?
const available = await Glaze.user.isUserAccountAvailable();
// Current player (or null if not signed in).
const user = await Glaze.user.getUser();
// user: { id: string, username: string, avatarUrl: string | null }
// Prompt sign-in; resolves with the user (or null if dismissed).
const signedIn = await Glaze.user.showAuthPrompt();
// React to sign-in / sign-out anywhere in your game.
function onAuth(u) { updateProfileUi(u); }
Glaze.user.addAuthListener(onAuth);
Glaze.user.removeAuthListener(onAuth);Verifying the player on your backend
getUserToken() returns a short-lived JWT. Send it to your server and verify the signature against the public keys at https://glazegames.com/sdk/v3/jwks.json before trusting the player’s identity.
const token = await Glaze.user.getUserToken();
await fetch('/my-api/sync', {
method: 'POST',
headers: { Authorization: 'Bearer ' + token },
});
// Server: verify against https://glazegames.com/sdk/v3/jwks.jsonCloud saves (data)
A simple key/value store that follows the player across devices. Values are JSON-serializable. In the simulator, saves are written to localStorage under a glaze.sim. namespace.
await Glaze.data.setItem('progress', { level: 7, coins: 320 });
const progress = await Glaze.data.getItem('progress');
// -> { level: 7, coins: 320 } (or null if unset)
await Glaze.data.removeItem('progress');
await Glaze.data.clear(); // wipe all of this game's saved keysLeaderboards
Submit a score to a named board and read it back. Boards support global or friends scope and alltime / daily / weekly periods.
// Submit a score (optionally with metadata). Returns the new rank.
const { rank } = await Glaze.leaderboards.submitScore('highscores', 9001, {
combo: 12,
});
// Read a board.
const { entries } = await Glaze.leaderboards.getLeaderboard('highscores', {
scope: 'global', // or 'friends'
period: 'weekly', // 'alltime' | 'daily' | 'weekly'
limit: 25,
});
// entries: { rank, username, score, meta? }[]
// Where does the current player sit?
const me = await Glaze.leaderboards.getPlayerEntry('highscores');Achievements
Unlock achievements by id and read the full unlocked set back at any time.
await Glaze.achievements.unlock('first-win');
const unlocked = await Glaze.achievements.getAll();
// -> ['first-win', ...]Purchases
List available products, run a purchase, and restore prior purchases. Prices are reported in micros (one-millionth of a currency unit) alongside a display label.
const products = await Glaze.purchases.getAvailableProducts();
// products: { id, name, priceLabel, priceMicros, currency }[]
const purchase = await Glaze.purchases.purchase('remove-ads');
// purchase: { productId, purchasedAt, token }
const owned = await Glaze.purchases.getPurchases();Purchases are unavailable in the simulator — purchase() rejects with code unsupported so you can test the error path.
Screen
Request fullscreen and lock orientation for the player’s session.
await Glaze.screen.requestFullscreen();
await Glaze.screen.exitFullscreen();
// 'portrait' | 'landscape' | 'any'
await Glaze.screen.lockOrientation('landscape');Analytics
Fire a custom event with optional properties. This is fire-and-forget (no promise) and is a no-op until init() has resolved.
Glaze.analytics.track('level_complete', { level: 7, time: 42.3 });Config
Read a remote / A-B flag with a required local default. The default is returned when no remote value exists (and always in the simulator), so your game never blocks on config.
const dropRate = await Glaze.config.get('rare_drop_rate', 0.05);
const theme = await Glaze.config.get('event_theme', 'default');Simulator & devtools
When the SDK can’t reach a Glaze parent (i.e. you’re developing locally), it enters simulator mode automatically — no config needed. Ads play a placeholder overlay, cloud saves go to localStorage, a test player (TestPlayer) can sign in, and stage is 'local'. This means you can build and test the entire integration before uploading anything.
A small Glaze SDK · SIM badge appears in the corner. Click it, or call the API below, to open the on-screen devtools panel — trigger ads, sign in a test player, and dump cloud saves.
Glaze.debug.show(); // open the devtools panel
Glaze.isSimulator; // true when simulating
Glaze.environment.stage; // 'local' in the simulatorQA requirements
Before a build passes review, confirm each of the following:
- You await
Glaze.init()before any other SDK call. game.loadingStop()fires exactly once when the game becomes playable.- Each round is bracketed with
gameplayStart()/gameplayStop(). - Audio mutes and gameplay pauses during ads (
adStarted) and resumes after (adFinished/adError). - Rewarded rewards are granted only in
adFinished, never on skip / error. - The game loads and is playable on both mobile (touch) and desktop, and scales to its container.
- No console errors on load, no broken assets, and no mature content.
Revenue & payouts
The planned developer share for accepted titles is 70% of eligible net revenue. Final revenue definitions, reporting, payment timing, tax requirements, and minimum thresholds are confirmed in writing during partner onboarding.
Do not enable live monetization until onboarding is complete. Simulator mode is available for testing ad callbacks without serving a real advertisement.
Ready to publish? Apply for publishing access with a playable build, or revisit the platform overview.
