The developer docs are written in English and Spanish. You are reading the English version.
SDK reference
The Gamealia SDK is window.Gamealia. Load it in index.html before your game scripts:
<script src="https://gamealia.app/sdk/v1.js"></script>
The SDK is not published to npm. The CrazyGames and Poki shims (/sdk/crazygames.js, /sdk/poki.js) include it too, so a page loads exactly one of the three files.
How calls behave
- Promises that never reject. Every async call resolves, with a safe fallback on failure (for example
{ shown: false, rewarded: false }for an ad,nullfor a user). You never needtry/catcharound the SDK. - Init first. Call
Gamealia.init()once at startup. Every other call waits for it (and starts it if you did not), so the order is always right, but call it yourself first: the autotest'ssdk_initcheck requiresinitto be the first SDK message. - Timeouts. Inside the portal, a call that gets no answer resolves its fallback after 15 s; ads and
requestLoginwait up to 120 s.init()waits up to 5 s for the portal, then falls back to the mock. - Mock mode. When the page is not inside the portal (your dev server, a file you opened, the standalone site of your game), the SDK runs a local mock, described for each method below. Add
?gamealia_debug=1to the URL for a small panel that logs every SDK call.
Types
interface InitResult {
environment: "gamealia" | "preview" | "autotest" | "mock";
locale: string; // the player's portal language, e.g. "es", "en", "pt-BR", "ja"
gameId: string; // your game's id ("local" in the mock)
user: PublicUser | null; // null for guests
joinRoom: string | null; // the room code the player was invited to
device: "mobile" | "desktop";
}
interface PublicUser { id: string; username: string; avatarUrl: string | null }
interface AdResult { shown: boolean; rewarded: boolean }
interface RoomInfo { code: string; name: string; players: number; max: number; inProgress: boolean }
type EventType = "adStart" | "adEnd" | "userChange" | "roomJoin" | "pause" | "resume" | "mute" | "unmute";
PublicUser.id is per game: the same player has a different id in every game, so games cannot match players with each other. environment is "preview" in the developer's and the reviewer's preview, "autotest" during the autotest and "gamealia" on the live portal.
Lifecycle
Gamealia.init(): Promise<InitResult>
The first call, once, at startup. Calling it again returns the same promise.
const { locale, user, device, joinRoom } = await Gamealia.init();
setLanguage(locale.startsWith("es") ? "es" : "en");
Mock: environment: "mock", gameId: "local", locale from the browser languages, user: null (until requestLogin), joinRoom from ?gamealia_join=CODE, device "mobile" when the window is narrower than 768 px or has touch.
Gamealia.peekInit(): InitResult | null
The init result once init() has finished, else null. Synchronous, for code that cannot wait.
Gamealia.game.loadingStart(): Promise<void>
Loading started. Optional.
Gamealia.game.loadingStop(): Promise<void>
Required. The game is loaded and ready to play. The autotest fails if it does not arrive within 15 s of the page load.
Gamealia.game.gameplayStart(): Promise<void> / Gamealia.game.gameplayStop(): Promise<void>
Real play starts (first input, level start, unpause) and stops (game over, pause menu, level end, an ad). They feed the stats and the friends' presence; the autotest warns when gameplayStart does not follow the first input.
Gamealia.game.happyTime(): Promise<void>
A big moment: a win, a record, a level cleared.
All game.* calls do nothing visible in the mock (they show up in the debug panel).
Ads
See Ads for the rules and frequency.
Gamealia.ad.requestMidgame(): Promise<AdResult>
An interstitial ad break at a natural pause. Resolves when the break is over (or was skipped), with shown: true only when an ad played. The portal may skip it (frequency cap, ads off, no fill): then it resolves { shown: false, rewarded: false } right away.
Gamealia.ad.requestRewarded(): Promise<AdResult>
A rewarded ad the player chose to watch. Give the reward only when rewarded is true.
const { rewarded } = await Gamealia.ad.requestRewarded();
if (rewarded) lives++;
Mock (both): a full-screen "Mock ad" overlay for 2 s, adStart and adEnd events, then { shown: true, rewarded: true } for a rewarded ad and { shown: true, rewarded: false } for a midgame.
Gamealia.onAdStart(cb): () => void / Gamealia.onAdEnd(cb): () => void
Shortcuts for Gamealia.on("adStart", cb) and Gamealia.on("adEnd", cb). Pause the game and mute its audio between them. Each returns an unsubscribe function.
Players
See Player accounts for backends and tokens.
Gamealia.user.get(): Promise<PublicUser | null>
The signed-in player, or null for a guest. Mock: null until requestLogin().
Gamealia.user.getToken(): Promise<string | null>
A signed token (ES256 JWT, valid 5 minutes) that your own backend verifies to identify the player. null for guests. Mock: always null.
Gamealia.user.requestLogin(): Promise<PublicUser | null>
Asks the portal to show its sign-in. Resolves the player after they sign in, or null if they did not. Call it from a button the player pressed. Never build your own login. Mock: signs in the fake player { id: "mock-user", username: "Mock Player", avatarUrl: null } and fires userChange.
Gamealia.user.onChange(cb: (user: PublicUser | null) => void): () => void
The player signed in or out. Returns an unsubscribe function. The SDK has already dropped its cached save: call data.load() here (see Cloud save).
Saves
See Cloud save.
Gamealia.data.load(): Promise<{ ok: true; data } | { ok: false; error }>
All of the player's saved data for this game. Unlike getAll(), it tells "no save yet" ({ ok: true, data: {} }) apart from "could not load" ({ ok: false, error: "timeout" }). On ok: false, do not start a new save over the old one.
Gamealia.data.get(key: string): Promise<unknown>
A saved value, or null when there is none (or it could not be read).
Gamealia.data.set(key: string, value: unknown): Promise<boolean>
Saves a JSON-serializable value. Resolves false when it was not saved: the value is not JSON, the whole save would pass 1 MB (UTF-8 bytes of the whole save as one JSON object), or the portal refused it.
Gamealia.data.getAll(): Promise<Record<string, unknown>>
All the saved data ({} when there is none or it could not be read).
Gamealia.data.remove(key: string): Promise<void> / Gamealia.data.clear(): Promise<void>
Deletes one key, or the whole save of this game.
Mock: the data lives in this browser's localStorage under keys prefixed gml:local:.
Multiplayer
See Multiplayer.
Gamealia.room.getJoinCode(): string | null
The room code the player was invited to (from the invite link), or null. Synchronous; valid after init().
Gamealia.room.inviteLink(code: string): Promise<string>
A link that opens your game on the portal and joins room code (https://gamealia.app/game/<slug>?room=<code>). Mock: the current URL with ?gamealia_join=<code>. Codes are 1-32 characters of A-Z a-z 0-9 _ -.
Gamealia.room.showInvite(code: string): Promise<void>
Opens the portal's invite sheet (copy link, share) for room code.
Gamealia.room.publish(room: RoomInfo): Promise<void>
Lists the room in the portal's open rooms so others can join. The SDK repeats it every 15 s while the page is open; the portal drops a room it has not heard from in 30 s. Publishing another code replaces the previous room.
Gamealia.room.unpublish(): Promise<void>
Takes the room down (it is full, started, or closed) and stops the heartbeat.
Gamealia.presence.setStatus(text: string): Promise<void>
A short status of what the player is doing ("Level 3", "In the lobby"), shown to the player's friends next to the game they are playing. The portal strips control characters, cuts it to 64 characters and forwards at most one change every 2 s (a burst keeps the latest). An empty text clears it; it also clears when the player leaves the game. Mock: logged only.
Events
Gamealia.on(event: EventType, cb): () => void
Subscribes to an event and returns an unsubscribe function.
| Event | Payload | When |
|---|---|---|
adStart / adEnd | none | Around every ad break: pause and mute in between |
userChange | PublicUser | null | The player signed in or out |
roomJoin | the room code | The player joined a room from the portal while playing |
pause / resume | none | The portal tab was hidden or shown again |
mute / unmute | none | Turn the game audio off / back on. The portal sends mute during ads, while the tab is hidden and when the player presses its mute button, and unmute when none of these applies any more. A game that starts while muted gets mute right after init() |
Module exports
For code inside a bundle (the shims use them): createGamealia(window) makes a new SDK instance bound to a window and getGamealia(window) returns the page's singleton (window.Gamealia).