GamePix SDK Integration Guide v3

Developer guide for HTML5 games integrating the GamePix JavaScript SDK. The SDK exposes a global GamePix object and connects your game to the GamePix Player.

Integration checklist

  • Load the GamePix SDK before your game bundle or framework starts.
  • Register the required pause and resume callbacks with GamePix.events.on(...); pause must also mute game audio.
  • (Recommended) Enable manual lifecycle with window.GamePixConfig = { lifecycle: 'manual' }, then report loading with GamePix.lifecycle.loading(percentage), readiness with await GamePix.lifecycle.loaded(), and gameplay start with GamePix.lifecycle.gameStart(). Without it, the SDK sends loaded and game start automatically but the game analytics may not be accurate.
  • Use GamePix.ads.interstitial() and GamePix.ads.reward() at appropriate gameplay moments.
  • Save light progress with browser localStorage (GamePix synchronizes it automatically); use your own backend for complex or structured data.
  • If your game needs a user identity, read it with GamePix.user.getUser() (no UI, safe at startup) and let the player log in with GamePix.user.requestLogin() from a button. Your backend verifies the token with GamePix's public keys.

1. Setup

Include the SDK before your game bundle, engine bootstrap, framework persistence plugin, or any script that may read or write saves. There are two setups.

Legacy lifecycle

The SDK tells the Gamepix Game Player that the game is loaded and that gameplay started as soon as the SDK itself loads, but the Games Analytics not accurate:

Code
<script src="https://integration.gamepix.com/sdk/v3/gamepix.sdk.js"></script>
<script src="game.js"></script>

New lifecycle — recommended

Set window.GamePixConfig before the SDK script. Your game then reports loading progress, when it can be shown, and when gameplay actually starts:

Code
<script>
    window.GamePixConfig = { lifecycle: 'manual' };
</script>
<script src="https://integration.gamepix.com/sdk/v3/gamepix.sdk.js"></script>
<script src="game.js"></script>

Why manual? With real loading progress, readiness, and gameplay-start moments, GamePix collects more accurate analytics for your game (loading time, drop-off before play, time to first gameplay). Better data leads to a better evaluation and a better future ranking of your game on the platform.

After the script is loaded, the global object is available as:

Code
window.GamePix

Load order matters. GamePix synchronizes browser localStorage from inside the game page. Load the SDK first so frameworks such as Redux Persist, Zustand persist, Phaser/Construct plugins, or custom save systems work from the very first read.

2. Lifecycle

Lifecycle methods tell the GamePix Player how far your game is in its startup flow. They are used in manual lifecycle only (see Setup); in automatic lifecycle the SDK sends loaded and gameStart by itself and you do not need to call these methods.

GamePix.lifecycle.loading(percentage) — recommended in manual lifecycle

Reports loading progress while your game downloads assets.

InputTypeRequiredDescription
percentagenumberYesInteger progress value from 0 to 100.

Output: the accepted percentage (as an integer). If the value is outside 0..100, the SDK reports an error to the Player and returns the label "LOADING_VALUE_IS_NOT_A_NUMBER".

Rules: progress should only increase; values lower than the last accepted one are not sent. Calls made after loaded() has completed are ignored. Non-numeric values are ignored.

Code
async function loadAssets() {
    GamePix.lifecycle.loading(0);

    await YourLoadTextures();
    GamePix.lifecycle.loading(35);

    await YourLoadAudio();
    GamePix.lifecycle.loading(70);

    await YourLoadLevels();
    GamePix.lifecycle.loading(100);
}

GamePix.lifecycle.loaded() — required in manual lifecycle (automatic otherwise)

Notifies the GamePix Player that the game can be shown. The Player removes its loading bar and shows the game after receiving this signal.

InputOutput
No input.Promise<object>
ResolutionMeaning
Player acknowledgementThe Player received the loaded signal.
FallbackThe Promise also resolves when no GamePix Player is present, or when the Player does not answer in time, so your game is never blocked.

Calling loaded() more than once is safe: the signal is sent only once.

Code
async function bootGame() {
    await loadAssets();

    await GamePix.lifecycle.loaded();
    YourShowMainMenuOrIntro();
}

GamePix.lifecycle.gameStart() — required in manual lifecycle (automatic otherwise)

Call this when real gameplay starts, for example when the first level, timer, or active gameplay loop begins. It is separate from loaded(): loaded() controls the Player loading UI, gameStart() marks the start of the gameplay session.

Input: no input. Output: true the first time, false on later calls (the signal is sent only once).

Code
function startLevel() {
    GamePix.lifecycle.gameStart();
    YourStartGame();
}

Automatic lifecycle. Without window.GamePixConfig = { lifecycle: 'manual' }, the SDK sends loaded and gameStart by itself as soon as it loads. Loading progress is not reported, and calling loaded() or gameStart() yourself has no further effect because the signals were already sent.

3. Pause and resume

The GamePix Player can pause and resume your game when needed, for example during ads or Player UI interactions.

Every game must register pause and resume handlers. The pause handler must also mute game audio; resume restores audio according to the game's own mute setting.

EventRequiredWhen it is calledWhat your game should do
pauseYesBefore ads, overlays, or other pause moments.Pause gameplay, timers, physics, input, and all audio.
resumeYesAfter the pause reason ends.Resume gameplay, timers, physics, and input; restore audio only when allowed by the game's mute setting.

GamePix.events.on(eventName, callback) — required for pause / resume

Registers a callback.

InputTypeRequiredDescription
eventNamestringYes'pause', 'resume', or 'authChanged' (see section 8).
callbackfunctionYesFunction called when the event happens.

Output: an unsubscribe function. If eventName is not supported or callback is not a function, nothing is registered.

GamePix.events.off(eventName, callback) — optional

Removes a callback previously registered with events.on. Pass the same function reference.

Code
// YourPauseGame pauses gameplay, timers, physics and mutes audio.
const unsubscribePause = GamePix.events.on('pause', () => YourPauseGame());

// YourResumeGame resumes gameplay and restores audio if the player did not mute it.
const onResume = () => YourResumeGame();
GamePix.events.on('resume', onResume);

// Later, when destroying a scene or module:
unsubscribePause();
GamePix.events.off('resume', onResume);

Handlers may be called more than once in a row (for example pause from the SDK and again from the Player). Make them idempotent: pausing an already paused game or resuming an already running one must do nothing.

The SDK detects the player's first interaction by itself; you do not need to call anything for it. Browser audio-unlock policies remain the responsibility of your game or engine.

4. Ads

The ads API is Promise-based. Ad calls require loaded() to have completed.

Pause handling is automatic. When you request an ad, the SDK calls your pause handlers; when the ad ends it calls your resume handlers, just before the Promise resolves. You do not need to pause the game yourself before calling an ad, as long as the handlers from section 3 are registered. If another ad is still in progress, resume waits until the last one ends.

GamePix.ads.interstitial() — optional

Requests an interstitial ad. Use it at natural breaks such as level complete, game over, return to menu, or between sessions.

Input: no input.

Output: Promise<{ success: boolean; message?: string }>

ResponseMeaning
{ success: true }The interstitial flow completed.
{ success: false }No ad was shown (no fill, error, or skipped by the Player).
{ success: false, message: "GamePix Player not found" }The game is not running inside a GamePix Player.
{ success: false, message: "Interstitial ad superseded by a new request" }A newer interstitial request replaced this one.
{ success: false, message: "GamePix Player is not ready to receive request: ..." }Called before loaded() completed.
Code
async function onLevelCompleted() {
    await GamePix.ads.interstitial();
    YourGoToNextLevel();
}

Wait for the Promise before requesting another interstitial: calling it again while one is in progress cancels the earlier call, which resolves with success: false.

GamePix.ads.reward() — optional

Requests a rewarded ad. Use it only when the player explicitly chooses to watch an ad for a reward.

Input: no input.

Output: Promise<{ success: boolean; message?: string }>

ResponseMeaning
{ success: true }Grant the reward.
{ success: false }Do not grant the reward (ad closed early, no fill, or error).
{ success: false, message: "GamePix Player not found" }The game is not running inside a GamePix Player.
{ success: false, message: "Reward ad superseded by a new request" }A newer rewarded request replaced this one.
{ success: false, message: "GamePix Player is not ready to receive request: ..." }Called before loaded() completed.
Code
async function onRewardButtonClicked() {
    const result = await GamePix.ads.reward();

    if (result.success) {
        YourGiveReward();
    } else {
        YourShowRewardUnavailableMessage();
    }
}

Grant the reward only when success is true. Wait for the Promise before requesting another rewarded ad: a second call cancels the earlier one, which resolves with success: false.

5. Gameplay signals

happyMoment() and sadMoment() are one-way signals: they return immediately and wait for nothing. They require loaded() to have completed; if called earlier, the SDK reports an error to the Player and sends nothing.

Both take an optional type: a short string that says which moment it is. Use short snake_case names and keep them stable across versions of your game, so the moments can be compared over time. A type that is not a non-empty string is ignored, and the signal is sent without it.

InputTypeRequiredDescription
typestringNoWhat happened, for example 'level_complete', 'high_score', 'boss_defeated', 'game_over', 'level_failed', 'time_up'.

GamePix.happyMoment(type?) — optional

Signals a positive moment, such as a high score, achievement, boss defeat, or big win.

Output: none.

Code
function onBossDefeated() {
    GamePix.happyMoment('boss_defeated');
    YourShowVictoryScreen();
}

GamePix.sadMoment(type?) — optional

Signals a negative moment, such as a game over, a failed level, or a timeout.

Output: null.

Code
function onGameOver() {
    GamePix.sadMoment('game_over');
    YourShowGameOverScreen();
}

6. Language

GamePix.lang() — optional

Returns the language chosen by the GamePix Player for this session.

Input: no input.

Output: an ISO 639-1 language code: two lowercase letters, such as 'en', 'it', 'de', 'fr'. Defaults to 'en' when the Player does not provide one.

GamePix currently offers en, bg, de, el, fi, fr, it, nl, pl, and pt; the list may grow. If your game does not support the returned language, fall back to English.

Code
const strings = YourTranslations[GamePix.lang()] || YourTranslations.en;
YourApplyStrings(strings);

7. Storage

Save progress with browser localStorage, directly or through an engine/framework persistence layer backed by localStorage. No GamePix-specific save/load method is required: the SDK synchronizes the game's storage with the GamePix Player automatically, and restores it on the next session.

Code
localStorage.setItem('progress', JSON.stringify(progress));
const saved = JSON.parse(localStorage.getItem('progress') || 'null');

Values are stored as strings, as in the browser.

Which storage to use:

  • Light saves → localStorage. Settings, unlocked levels, best score, a compact save slot: data that is small and fits naturally in a few string values.
  • Complex or structured data → your own backend. Large saves, inventories, economies, multiplayer or cross-device state, anything that needs queries, validation, or server-side authority. Store it on your developer backend, keyed by the user id from GamePix.user.getUser().
Storage technologyGamePix behavior
Browser localStorage (setItem / getItem / removeItem / clear)Synchronized automatically.
Framework or plugin backed by localStorageSupported, because it uses the same storage methods.
IndexedDB / localForage in IndexedDB modeNot synchronized. Use localStorage for critical progress.

Rule 1: load the SDK first. Anything your game writes to localStorage before the SDK has loaded is lost.

Rule 2: read keys you know. Do not discover saves by enumerating storage: localStorage.length, localStorage.key(i), Object.keys(localStorage), and property reads such as localStorage.progress do not see synchronized data. Always use localStorage.getItem('yourKey') with known key names (for example keep a fixed list of save-slot keys).

Outside GamePix, when the game is opened directly as a top-level page (your own site, a direct link, localhost), there is no Player to synchronize with: the SDK leaves localStorage untouched and the game uses the browser's storage as usual.

8. User and authentication

GamePix authenticates users with Xsolla ID. If your game uses a different account system, you do not need Xsolla ID on your side: user.id is unique and stable for each user, so you can use it as the user's identifier in your own system (for example as the key of their save on your backend).

There are three optional methods. getUser() and requestLogin() return the same result object; showBackpack() has its own (see below):

MethodShows UI?Use it
GamePix.user.getUser()NeverAny time, also at startup, to know whether the player is logged in. A guest gets 401 right away.
GamePix.user.requestLogin()Yes: the GamePix loginOnly from a player action (a "Log in" or "Save to cloud" button), to let a guest log in.
GamePix.user.showBackpack()Yes: the Backpack card (no pause, no login)From a player action (an "Inventory" button), to open the player's Xsolla Backpack. A guest gets 401.

GamePix.user.getUser() — optional

Returns the current GamePix user together with a GamePix Game Token (a token for your game only, see Verifying the token on your backend), without showing anything to the player. If the player is not logged in, it resolves { success: false, code: 401 } within a few seconds; the player stays a guest and nothing is shown.

GamePix.user.requestLogin() — optional

Asks the player to log in. If they are already logged in, it resolves immediately like getUser(). Otherwise the GamePix Player opens its login window (without reloading your game) and the Promise resolves when the player logs in (200) or cancels (401). Your game keeps running while the player logs in; do not pause it.

Call it only from a click or tap. The login opens in a separate window, and browsers block windows that are not opened in response to a user action. Never call requestLogin() at startup or from a timer.

Input: no input (both methods).

Output (both methods):

Code
Promise<{
    success: boolean;
    code: number;              // see the table below
    user: {
        id: string;
        username?: string;     // Xsolla username, e.g. "id5441"
        displayName?: string;  // GamePix nickname, else the username: show this one
        name?: string;         // deprecated: equals username
        avatar?: string;
        guest?: boolean;
        [key: string]: any;
    } | null;
    token: string | null;      // GamePix Game Token (JWT), for your backend
    expiresAt: number | null;  // token expiry, milliseconds since epoch (Date.now() scale)
    message?: string;
}>
ResponseMeaning
{ success: true, code: 200, user, token, expiresAt }The user is authenticated.
{ success: false, code: 401 }getUser(): the player is not logged in. requestLogin(): the player did not log in (closed or cancelled the login).
{ success: false, code: 404 }Not available: the game is not running inside the GamePix Player.
{ success: false, code: 408 }The Player did not answer in time.
Code
// At startup: show the player's name if they are already logged in. Never shows UI.
const auth = await GamePix.user.getUser();
if (auth.success) {
    YourShowPlayerName(auth.user.displayName);
} else {
    YourShowLoginButton();
}

// "Log in" / "Save to cloud" button: called from the click handler.
async function onSaveToCloudClicked() {
    const auth = await GamePix.user.requestLogin();

    if (!auth.success) {
        YourShowMessage('Log in to save your progress');
        return;
    }

    YourShowPlayerName(auth.user.displayName);
    await YourSaveOnYourBackend(auth.token); // the backend verifies the token
}

A guest must always be able to play: use getUser() to adapt the UI and requestLogin() only when the player chooses to log in.

Token lifetime and renewal

The token is valid for 15 minutes; expiresAt tells you when it expires. There is no refresh token: the SDK asks the Player for a new one.

  • The SDK caches the token: calling getUser() or requestLogin() while the token is valid returns immediately, with no request to the Player. Call getUser() every time you need the token instead of storing it yourself.
  • The SDK renews the token automatically about one minute before expiresAt, silently and without showing any UI.
  • If your backend rejects the token as expired, call getUser() again and retry once. If it returns 401, the session has ended: treat the player as a guest.

Event authChanged

Register it with GamePix.events.on('authChanged', callback). It fires when the authentication state changes outside your getUser() / requestLogin() calls:

  • the token was renewed automatically (token and expiresAt change);
  • the user logged in or out on the GamePix site while your game was running;
  • automatic renewal failed because the session ended (success: false, user: null).

The callback receives the same object as getUser().

Code
GamePix.events.on('authChanged', (auth) => {
    if (auth.success) {
        YourShowPlayerName(auth.user.displayName);
    } else {
        YourSwitchToGuestMode();
    }
});

Fields

FieldDescription
user.idUnique, stable user identifier. It does not change between sessions, so you can use it as the user's key in your own system.
user.displayNameThe name to show: the player's GamePix nickname, or their username when they have not set one.
user.usernameThe player's Xsolla username (e.g. id5441). It can change: never use it as a key.
user.avatarThe player's avatar URL, when they have one.
user.nameDeprecated, equals user.username. Use user.displayName.
user.guesttrue when the account is a guest account.
tokenGamePix Game Token: a JWT signed by GamePix for this game only.
expiresAtToken expiry in milliseconds since epoch.

The token proves who the player is to your backend. It is valid only for your game, for 15 minutes, and no Xsolla service accepts it.

  • Send it only to your own backend, over HTTPS.
  • Never log it, never store it in localStorage or cookies, never send it to analytics or third parties.
  • Always get it from GamePix.user.getUser() when you need it; the SDK keeps it fresh.

user (including user.id), displayName, username, name, avatar, and guest are for display only. On GamePix, the token is how your backend knows who the player is: take the identity from the verified token, never from a value the game sends.

Verifying the token on your backend

The token is a JWT signed by GamePix (RS256). Verify it with any standard JWT library against GamePix's public keys:

CheckValue
Keys (JWKS)https://auth.gamepix.com/.well-known/jwks.json
isshttps://auth.gamepix.com
audgpx:game:<your gameId>
algRS256 only
expnot expired
Code
// Node.js, with `jose`
import { createRemoteJWKSet, jwtVerify } from 'jose';

const JWKS = createRemoteJWKSet(new URL('https://auth.gamepix.com/.well-known/jwks.json'));

async function playerFromRequest(req) {
    const token = (req.headers.authorization || '').replace(/^Bearer /, '');
    const { payload } = await jwtVerify(token, JWKS, {
        issuer: 'https://auth.gamepix.com',
        audience: 'gpx:game:YOUR_GAME_ID',
        algorithms: ['RS256']
    });
    return payload.sub; // the player's Xsolla ID
}
  • sub is the player's Xsolla ID (the same as user.id), identical on every GamePix site and app. Use it as the player's key, and as the user ID for Xsolla server-to-server APIs (Store, Backpack).
  • The library caches the keys: there is no call to GamePix per request.
  • Other claims: gid (your gameId), username, name (deprecated), avatar, iat, nbf, jti. There is no displayName claim: the nickname is not verified by GamePix, so it is never signed.

Games that also run outside GamePix. Xsolla server APIs such as Backpack and Store only need the player's Xsolla user ID: the GamePix Game Token is one safe way to get it, not a requirement of those APIs. If your game also runs on your own site with its own Xsolla login, your backend can accept that login's token too, verified with that login's keys, next to the GamePix Game Token. In both cases the identity comes from a verified token, never from a value the game sends in clear.

GamePix.user.showBackpack() — optional

Opens the player's Xsolla Backpack in the GamePix Player, the same card the player opens from the GamePix user menu. Call it from a player action, for example an "Inventory" button.

  • The card is not modal: the Player does not pause your game, and the game stays usable while the card is open. Pause the game yourself if you need to.
  • It does not show the login. If the player is a guest, it resolves 401; to let them log in first, call requestLogin() and then showBackpack().
  • There is no event when the player closes the card.

It resolves { success, code, message? }:

ResultMeaning
{ success: true, code: 200 }The Backpack is open (or was already open).
{ success: false, code: 401 }The player is not logged in.
{ success: false, code: 404 }The Backpack is not available here (outside GamePix, on a partner site, or not enabled).
{ success: false, code: 408 }The Player did not answer within 10 seconds.
Code
async function onInventoryClicked() {
    let result = await GamePix.user.showBackpack();

    if (result.code === 401) {
        const auth = await GamePix.user.requestLogin();
        if (!auth.success) return;
        result = await GamePix.user.showBackpack();
    }

    if (!result.success) YourShowMessage('Inventory not available');
}

9. Local testing

When your game runs outside the GamePix Player (on localhost, 127.0.0.1, from file:, or as a standalone page), the SDK simulates the Player so you can test the full flow:

  • loaded() resolves immediately.
  • GamePix.ads.interstitial() triggers your pause handler, shows a fake ad overlay, then triggers resume and resolves { success: true }.
  • GamePix.ads.reward() triggers pause, asks for confirmation with a browser dialog, then triggers resume and resolves with your answer.
  • GamePix.user.getUser() and GamePix.user.requestLogin() resolve { success: false, code: 404, user: null }, unless you choose a simulated user with gpx_user.
  • GamePix.user.showBackpack() resolves { success: false, code: 404 }.

Add these query parameters to your game URL to choose the simulated results:

ParameterValuesEffect
gpx_adsuccess (default), nofill, errorInterstitial result. nofill and error resolve success: false without the overlay.
gpx_rewardconfirm (default, shows a dialog), success, cancel, errorRewarded result. success grants the reward, cancel / error do not, without a dialog.
gpx_useruser, guestSimulated player. user: logged in. guest: getUser() resolves 401, requestLogin() asks with a dialog (OK logs in and fires authChanged). Without it, both resolve 404.
gpx_inspectortrue or 1Shows a small overlay with the detected environment and SDK state.
Code
http://localhost:8080/index.html?gpx_ad=nofill&gpx_reward=success&gpx_inspector=1
http://localhost:8080/index.html?gpx_user=guest

The simulated player's token is gpx-local-mock-token: it is not a JWT and no backend can verify it. Locally you test your game's branches (guest, login, cancelled login); verifying a real token needs the game running on GamePix.

10. Recommended minimal integration

Manual lifecycle, as recommended in Setup:

Code
<script>
    window.GamePixConfig = { lifecycle: 'manual' };
</script>
<script src="https://integration.gamepix.com/sdk/v3/gamepix.sdk.js"></script>
<script src="game.js"></script>
Code
// game.js
async function main() {
    GamePix.events.on('pause', () => YourPauseGame());
    GamePix.events.on('resume', () => YourResumeGame());

    GamePix.lifecycle.loading(0);
    await YourLoadGameAssets();
    GamePix.lifecycle.loading(100);

    await GamePix.lifecycle.loaded();
    YourShowMainMenuOrIntro();
}

function startLevel() {
    GamePix.lifecycle.gameStart();
    YourStartGame();
}

async function onLevelCompleted() {
    await GamePix.ads.interstitial();
    YourGoToNextLevel();
}

main();

11. Method summary

MethodRequiredPurpose
GamePix.lifecycle.loading(percentage)Recommended (manual lifecycle)Report asset loading progress.
GamePix.lifecycle.loaded()Yes in manual lifecycle; automatic otherwiseNotify the Player that the game can be shown.
GamePix.lifecycle.gameStart()Yes in manual lifecycle; automatic otherwiseNotify that actual gameplay started.
GamePix.events.on(eventName, callback)Yes for pause / resumeRegister pause, resume, and auth callbacks.
GamePix.events.off(eventName, callback)OptionalRemove a registered callback.
GamePix.ads.interstitial()OptionalShow an interstitial ad at a natural break.
GamePix.ads.reward()OptionalShow a rewarded ad after an explicit player choice.
GamePix.happyMoment(type?)OptionalSignal a positive moment, optionally saying which one.
GamePix.sadMoment(type?)OptionalSignal a negative moment, optionally saying which one.
GamePix.lang()OptionalRead the language chosen by the Player.
Browser localStorageRecommended for light savesSynchronized automatically when the SDK is loaded first.
GamePix.user.getUser()OptionalGet the logged-in user (unique id) and the GamePix Game Token for your backend, without any UI; 401 for a guest.
GamePix.user.requestLogin()OptionalLet a guest log in (from a click); resolves with the same object as getUser().
GamePix.user.showBackpack()OptionalOpen the player's Xsolla Backpack in the Player; 401 for a guest, no pause.

12. Appendix: legacy API aliases

Existing games may keep using these flat aliases. New integrations should use the APIs above.

Legacy callModern equivalent
GamePix.loaded()GamePix.lifecycle.loaded()
GamePix.loading(percentage)GamePix.lifecycle.loading(percentage)
GamePix.interstitialAd()GamePix.ads.interstitial()
GamePix.rewardAd()GamePix.ads.reward()
GamePix.addEventListener(eventName, callback)GamePix.events.on(eventName, callback)
GamePix.removeEventListener(eventName, callback)GamePix.events.off(eventName, callback)
GamePix.pause = fn, GamePix.on.pause = fn (and resume)GamePix.events.on('pause', fn)
GamePix.game.gameLoading(percentage)GamePix.lifecycle.loading(percentage)
GamePix.game.gameLoaded(callback)await GamePix.lifecycle.loaded() then your code
Pausing manually before interstitialAd() and resuming in its callback (old guide)Not needed anymore; the SDK calls your pause/resume handlers. Keeping it is harmless.

Legacy methods without a modern equivalent

These calls still work for existing games, but they are no longer part of the recommended integration and new games should not use them.

Legacy callBehavior
GamePix.sendScore(score), GamePix.updateScore(score)Sends the current score (a number; strings are rejected and reported as an error).
GamePix.sendLevel(level), GamePix.updateLevel(level)Sends the current level or stage (a number; strings are rejected and reported as an error).
GamePix.gameStop()Signals that a gameplay session ended. The Player may use it as a break for an ad, so pause / resume may follow.
GamePix.gameAction()Signals that meaningful gameplay activity happened (a move, a shot, a completed action).
GamePix.events.on('soundOff', fn) / ('soundOn', fn), GamePix.soundOff = fn / GamePix.soundOn = fn (and GamePix.on.*)Optional audio controls: mute, and restore audio according to the game's mute setting. pause already includes muting.

Like the other gameplay signals, sendScore, sendLevel, gameStop, and gameAction require loaded() to have completed.