The developer docs are written in English and Spanish. You are reading the English version.
Migrate from CrazyGames
The CrazyGames shim exposes the CrazyGames HTML5 SDK v3 (window.CrazyGames.SDK) on top of Gamealia. Most games only swap one script tag.
1. Swap the script
<!-- before -->
<script src="https://sdk.crazygames.com/crazygames-sdk-v3.js"></script>
<!-- after -->
<script src="https://gamealia.app/sdk/crazygames.js"></script>
gamealia init --write (or gamealia_integrate_sdk) does it for you, and the MCP prompt migrate-from-crazygames walks your assistant through the whole migration. The shim includes the Gamealia SDK, so window.Gamealia is there too: you can move calls over one by one.
Older SDK versions (v1, v2) are not covered: port those calls to v3 or to the Gamealia SDK (the integration prints a TODO). If you import @crazygames/crazygames-sdk from npm, load the shim with a script tag instead.
2. Check the policy
CrazyGames allows some things Gamealia does not: remove in-game purchases (Xsolla), "remove ads" offers, other ad networks and your own login. See Game requirements.
Method mapping
| CrazyGames SDK v3 | On Gamealia |
|---|---|
SDK.init() | Gamealia.init(), then loads the saved data for SDK.data |
SDK.environment, getEnvironment() | always "crazygames", so your existing branches keep working |
SDK.game.loadingStart() / loadingStop() | Gamealia.game.loadingStart() / loadingStop() |
SDK.game.sdkGameLoadingStart() / sdkGameLoadingStop() | same as above |
SDK.game.gameplayStart() / gameplayStop() | Gamealia.game.gameplayStart() / gameplayStop() |
SDK.game.happytime() | Gamealia.game.happyTime() |
SDK.ad.requestAd("midgame", callbacks) | Gamealia.ad.requestMidgame(); adStarted, then adFinished, or adError with code unfilled |
SDK.ad.requestAd("rewarded", callbacks) | Gamealia.ad.requestRewarded(); adFinished only when rewarded |
SDK.ad.hasAdblock | always false |
SDK.banner.* | no-ops that report success (the portal shows its own banner) |
SDK.game.inviteLink(params) | the same portal link as Gamealia.room.inviteLink(code) (/game/<slug>?room=<code>). The code is roomId, roomName, room, id or code (else the first param) and must be 1-32 of A-Z a-z 0-9 _ -; other params do not travel. "" before init() resolves or for an invalid code |
SDK.game.showInviteButton(params) | Gamealia.room.showInvite(code); returns the link |
SDK.game.getInviteParam(key) / inviteParams | for a player who joined from a link: the room code under roomId, roomName and room |
SDK.game.settings.muteAudio, addSettingsChangeListener(cb) | follows the portal's mute / unmute (ads, hidden tab, the mute button); listeners get the new settings |
SDK.game.addJoinRoomListener(cb) | the roomJoin event, as { roomId } |
SDK.user.getUser() | Gamealia.user.get() as { __dangerousUserId, username, profilePictureUrl } |
SDK.user.getUserToken() | Gamealia.user.getToken() ("" for guests); verify it with the Gamealia JWKS, see Player accounts |
SDK.user.showAuthPrompt() | Gamealia.user.requestLogin() |
SDK.user.addAuthListener(cb) | Gamealia.user.onChange() |
SDK.user.isUserAccountAvailable | true |
SDK.user.getSystemInfo(), systemInfo | locale and device from Gamealia; countryCode is always "US" |
SDK.data.getItem/setItem/removeItem/clear | Cloud save; values are kept as strings, like localStorage |
SDK.user.listFriends() | an empty list |
SDK.user.showAccountLinkPrompt() | { response: "no" } |
SDK.store.isAvailable | false (no purchases in v1) |
SDK.user.getXsollaUserToken() | null, with a warning |
SDK.user.submitScore, game.reportGameCompletedPercentage, game.setGameContext, game.clearGameContext, game.updateRoom, game.leftRoom, analytics.trackOrder, game.hideInviteButton | accepted and ignored (one console warning each) |
SDK.data.getItem reads from a copy loaded during SDK.init(): await init() before reading.
Your backend
If your server verified CrazyGames tokens, switch it to Gamealia's: ES256 with the Gamealia JWKS, sub as the player id. See Player accounts.