Yes2SDK for CrazyGames - Platform Guide

Prerequisite

Install Yes2SDK first. None of the API below compiles until the SDK is installed in your project:

  • Unity: UPM git URL https://github.com/yes2games/yes2sdk-unity.git#<version>, then Yes2SDK > Build Window > Install Template.
  • Defold: add the release archive to game.project [project] dependencies, then Project > Fetch Libraries.

If you use the Yes2SDK MCP, call get_install_instructions for exact pinned steps and detect_sdk to confirm the SDK is installed before generating any code.

Requirements

CrazyGames requires specific SDK initialization and lifecycle management. The platform replaces your HTML on upload, so the SDK uses a special bootstrap mechanism.

API Requirements

The Yes2SDK methods below cover every CrazyGames-platform call you need. The middle column is what Yes2SDK invokes on window.CrazyGames.SDK under the hood. You never call those directly. The same Yes2SDK API works in TypeScript, Unity (Yes2SDK.*), and Defold (yes2sdk.*). Only the method-naming convention changes (see Integration Example below).

Platform RequirementYes2SDK APIRequired
SDK.init({ wrapper: { engine, sdkVersion } })Yes2SDK.initializeAsync()Required
sdk.game.loadingStart()Yes2SDK.setLoadingProgress(n) (first call triggers it)Required
sdk.game.loadingStop()Yes2SDK.startGameAsync()Required
sdk.game.gameplayStart()game.gameplayStart()Required (CG QA checks this)
sdk.game.gameplayStop()game.gameplayStop()Required (before every ad)
sdk.ad.requestAd('midgame', cbs)ads.showInterstitial(placement, cbs)Recommended
sdk.ad.requestAd('rewarded', cbs)ads.showRewarded(placement, cbs)Recommended
Mute audio in adStarted, restore in adFinished / adErrorbeforeAd / afterAd callbacks (mute/unmute yourself)Required (CG QA checks audio)
sdk.game.happytime()game.happyTime()Recommended (boosts promotion)
sdk.banner.requestBanner(size)banners.showBanner(id, size)Optional
sdk.user.getUser() / getUserToken()auth.signInAsync() / auth.getTokenAsync()Optional
sdk.data.getItem/setItem (cloud storage)data.getInt/setInt, data.getString/setString, ...Optional

CrazyGames replaces your index.html on upload. Wrapping inline <script> calls is lost. The Yes2SDK Dashboard bundles the SDK into framework.js (Unity) or alongside your assets (Defold/HTML5) so initialization survives.

Mandatory Call Sequence

1. CrazyGames SDK loaded (CDN or injected by platform)
2. Yes2SDK.initializeAsync()
   -> SDK.init({ wrapper: { engine: 'unity', sdkVersion: '2.0.0' } })
3. Yes2SDK.setLoadingProgress(...)
   -> triggers sdk.game.loadingStart() on first call
4. Yes2SDK.startGameAsync()
   -> calls sdk.game.loadingStop()
5. game.gameplayStart()
6. [player plays]
7. game.gameplayStop()
8. ads.showInterstitial(...)     <-- midgame ad
9. game.gameplayStart()

Critical Rules

RuleDescription
Wrapper options in initMust pass { wrapper: { engine, sdkVersion } } to SDK.init(). QA rejection without it.
Loading progressMust call loadingStart() during loading and loadingStop() when ready
gameplayStart/StopMust bracket active gameplay. CG QA tool checks for this
Audio mute during adsMute when adStarted fires, restore on adFinished/adError
No ads during gameplayInterstitials only when gameplay is stopped
3-minute ad frequencyCG enforces 3-min minimum between interstitials server-side
happytime on positive momentsRecommended (not mandatory) for CG promotion algorithms
Settings change listenerHandle mute/unmute commands from the CG player

Integration Example

TypeScript / JavaScript

// Initialize
await Yes2SDK.initializeAsync();

// Report loading progress
Yes2SDK.setLoadingProgress(50);
Yes2SDK.setLoadingProgress(100);

// Game ready
await Yes2SDK.startGameAsync();
Yes2SDK.game.gameplayStart();

// Between levels: show interstitial
Yes2SDK.game.gameplayStop();
await Yes2SDK.ads.showInterstitial('level-complete', {
    beforeAd: () => {
        muteAudio();
        pauseGame();
    },
    afterAd: () => {
        unmuteAudio();
        resumeGame();
        Yes2SDK.game.gameplayStart();
    }
});

// Signal positive moment
Yes2SDK.game.happyTime();

// Rewarded ad
Yes2SDK.game.gameplayStop();
await Yes2SDK.ads.showRewarded('double-coins', {
    beforeAd: () => pauseGame(),
    afterAd: () => {
        resumeGame();
        Yes2SDK.game.gameplayStart();
    },
    adViewed: () => doubleCoins(),
    adDismissed: () => console.log('Ad dismissed')
});

Unity C#

Yes2SDK.Yes2SDK.InitializeAsync(onSuccess: () =>
{
    // Loading progress is reported automatically by Unity loader,
    // or call manually:
    Yes2SDK.Yes2SDK.SetLoadingProgress(100);

    Yes2SDK.Yes2SDK.StartGameAsync(onSuccess: () =>
    {
        Yes2SDK.Yes2SDK.Game.GameplayStart();
    });
});

// Interstitial between levels
void OnLevelComplete()
{
    Yes2SDK.Yes2SDK.Game.GameplayStop();
    Yes2SDK.Yes2SDK.Game.HappyTime();

    Yes2SDK.Yes2SDK.Ads.ShowInterstitial("level-complete", "Between levels",
        beforeAd: () => { AudioListener.pause = true; Time.timeScale = 0f; },
        afterAd: () => {
            AudioListener.pause = false;
            Time.timeScale = 1f;
            Yes2SDK.Yes2SDK.Game.GameplayStart();
        }
    );
}

Defold Lua

yes2sdk.initialize(function(self, success, error)
    yes2sdk.set_loading_progress(100)
    yes2sdk.start_game(function(self, success, error)
        yes2sdk.session_gameplay_start()
    end)
end)

-- Between levels
yes2sdk.session_gameplay_stop()
yes2sdk.game_happy_time()
yes2sdk.ads_show_interstitial("level-complete",
    function(self) end,
    function(self) yes2sdk.session_gameplay_start() end,
    function(self) yes2sdk.session_gameplay_start() end
)

How CrazyGames Works Under the Hood

SDK Loading

CrazyGames SDK is loaded from https://sdk.crazygames.com/crazygames-sdk-v3.js. The SDK sets window.CrazyGames.SDK asynchronously, so the adapter polls for it (100ms intervals, 15 second timeout, then CDN fallback).

HTML Replacement

CrazyGames replaces your HTML when you upload a game. This means inline <script> wrappers in index.html are lost. The Unity SDK handles this with Yes2SDKPlatformInit.jslib, which uses Emscripten's $__postset to inject the wrapper into framework.js (which IS preserved).

For non-Unity engines, the Yes2SDK Dashboard bundles the SDK into your game files so it loads independently of the HTML.

Ad Callback Flow

requestAd('midgame', callbacks):
  adStarted -> [ad plays] -> adFinished
  adStarted -> [error]     -> adError

requestAd('rewarded', callbacks):
  adStarted -> [watched fully]  -> adFinished (= grant reward)
  adStarted -> [error 'unfilled' or 'adblock'] -> adError (= noFill)
  adStarted -> [other error]    -> adError (= adDismissed)

The adError callback receives an error object with a .code property. The SDK maps:

  • 'unfilled' or 'adblock' -> noFill callback
  • Other error codes -> adDismissed callback

Banner Sizes

CrazyGames supports 5 banner sizes:

NameSize
Leaderboard728x90
Medium300x250
Mobile320x50
Main468x60
Large Mobile320x100

How to Submit

You don't upload to CrazyGames yourself. The Yes2Games team handles platform submission.

  1. Upload a build on your game page (Onboarding → Stage 1)
  2. Test it in the Inspector (Onboarding → Stage 3)
  3. Click Request Publish in Onboarding → Stage 4 and select CrazyGames
  4. The Yes2Games team validates the build against CG's QA tool, registers the game in the CrazyGames developer portal, and uploads it on your behalf
  5. You'll see status updates (pending_reviewreviewingapproved / needs_changes) and feedback messages on the game page

If reviewers send back changes, upload a new build and request publish again on that build.

What Yes2Games reviewers check before submitting to CrazyGames

  • SDK init with wrapper options
  • gameplayStart / gameplayStop called around active gameplay
  • Audio muted during ads
  • loadingStart / loadingStop sequence completes
  • No ads during active gameplay
  • Ad error codes mapped correctly (unfilled / adblock → noFill)

Common Rejection Reasons

IssueFix
Missing wrapper options in initPass { wrapper: { engine: 'unity', sdkVersion: '2.0.0' } } to SDK.init()
Audio plays during adsMute in beforeAd/adStarted, restore in afterAd/adFinished
No gameplay lifecycleAdd gameplayStart()/gameplayStop() around active gameplay
Ads during active gameplayCall gameplayStop() before requesting any ad
Missing loading progressCall loadingStart() during loading, loadingStop() when ready
Wrong reward on ad errorCheck adError.code -- 'unfilled'/'adblock' = no fill, not dismissal

Platform-Specific Features

Auth

CrazyGames supports user authentication:

if (Yes2SDK.auth.isSupported()) {
    const user = await Yes2SDK.auth.signInAsync();
    console.log(`Welcome, ${user.name}`);
}

Friends

const result = await Yes2SDK.friends.listFriendsAsync(0, 20);
result.friends.forEach(f => console.log(f.name));

Cloud Data

CrazyGames provides sdk.data.getItem/setItem for cloud storage. The SDK Data module (data.getInt, data.setString, etc.) uses this automatically.

Banners

await Yes2SDK.banners.showBanner('main-menu', '300x250');
Yes2SDK.banners.hideBanner('main-menu');

Settings Change Listener

CrazyGames can send settings changes (e.g., mute audio from the CG player). The SDK handles this automatically, but you can also listen for platform events:

// The SDK dispatches OnPause/OnResume events when CG requests it
Yes2SDK.OnPause += () => MuteAudio();
Yes2SDK.OnResume += () => UnmuteAudio();

Build & Upload Limits

  • Total size: 250 MB
  • Initial download: 50 MB (≤20 MB to qualify for the mobile homepage)
  • File count: 1500 files
  • Max per-file: ⚠️ Not published; verify in portal
  • Entry point: index.html
  • Paths: relative paths only, never absolute
  • External requests: allowed, but must reach gameplay within ~20 seconds
  • Compression: Brotli recommended over gzip
  • Persistence: localStorage available
  • Canvas: landscape on desktop; consistent resolution; runs on 4 GB Chromebook
  • Review: QA team review; PEGI 12; English localization mandatory

Sources:

Pitch your game