Developer docs

Glaze Games SDK v3

One script gives your HTML5 game ads, cloud saves, leaderboards, player auth and more. Everything runs in a local simulator until you deploy — build the full integration without leaving your machine.

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 init

Game 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' | null

Call 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(); // boolean

For 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.json

Cloud 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 keys

Leaderboards

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 simulator

QA 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.

Build it, test it, apply

Integrate the SDK in your local sandbox, verify the callbacks, and send us a playable build for review.