playgama-bridge-js-sdk

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Playgama Bridge JS SDK

Playgama Bridge JS SDK

Playgama Bridge is a unified JS SDK that lets a single HTML5 build run on 20+ platforms (Playgama, Yandex Games, Crazy Games, Facebook Gaming, YouTube Playables, Telegram, Poki, Y8, Lagged, MSN, Microsoft Store, Discord, GameSnacks, Xiaomi, Huawei, JioGames, BitQuest, Reddit, Game Distribution, Playhop, Aha Games, etc.).
When the game runs on a supported platform, Bridge auto-loads that platform's native scripts and routes API calls to it. In unsupported environments (local dev, unknown hosts) Bridge uses a
mock
platform that returns safe defaults (
false
,
reject
, etc.) instead of throwing — the same code works everywhere.
The JS SDK (JS Core) is the foundation; engine packages (Unity, Godot, Construct, GDevelop, GameMaker, Defold, Cocos Creator, Scratch) are thin wrappers. Use JS Core directly for web engines such as PlayCanvas, Phaser, LayaAir, Three.js, Babylon.js.
Playgama Bridge 是一个统一的 JS SDK,让单个 HTML5 构建版本能够在 20 多个平台上运行(Playgama、Yandex Games、Crazy Games、Facebook Gaming、YouTube Playables、Telegram、Poki、Y8、Lagged、MSN、Microsoft Store、Discord、GameSnacks、Xiaomi、Huawei、JioGames、BitQuest、Reddit、Game Distribution、Playhop、Aha Games 等)。
当游戏运行在受支持的平台上时,Bridge 会自动加载该平台的原生脚本,并将 API 调用转发给该平台。在不受支持的环境(本地开发、未知宿主)中,Bridge 会使用
mock
平台返回安全默认值(
false
、
reject
等),而不是抛出异常,因此同一套代码可在所有环境中运行。
JS SDK(JS Core)是整个 Bridge 的基础;引擎包(Unity、Godot、Construct、GDevelop、GameMaker、Defold、Cocos Creator、Scratch)都是轻量封装。对于 PlayCanvas、Phaser、LayaAir、Three.js、Babylon.js 等 Web 引擎,可直接使用 JS Core。

Installation

安装

Add the script tag to the
<head>
of your
index.html
before any game code:
html
<html>
    <head>
        <script src="https://bridge.playgama.com/v1/stable/playgama-bridge.js"></script>
    </head>
    <body>
        ...
    </body>
</html>
CDN options:
URLWhen to use
https://bridge.playgama.com/v1/stable/playgama-bridge.js
Recommended. Latest stable v1.x.x
https://bridge.playgama.com/latest/playgama-bridge.js
Bleeding edge — for testing only
https://bridge.playgama.com/v1.27.0/playgama-bridge.js
Pin a specific version
The SDK exposes a global
bridge
object after the script loads.
在任何游戏代码之前,将 script 标签添加到
index.html
的
<head>
中:
html
<html>
    <head>
        <script src="https://bridge.playgama.com/v1/stable/playgama-bridge.js"></script>
    </head>
    <body>
        ...
    </body>
</html>
CDN 选项:
URL使用场景
https://bridge.playgama.com/v1/stable/playgama-bridge.js
推荐。 最新的稳定版 v1.x.x
https://bridge.playgama.com/latest/playgama-bridge.js
最新开发版——仅用于测试
https://bridge.playgama.com/v1.27.0/playgama-bridge.js
锁定特定版本
脚本加载后,SDK 会暴露一个全局
bridge
对象。

Configuration file

配置文件

Bridge reads
playgama-bridge-config.json
from the build root. It declares platform IDs, IAP catalog, ad placements, leaderboards and other settings. Generate or edit it with the config editor.
Skeleton:
json
{
    "platforms": {
        "playgama": { "options": {} },
        "yandex": { "options": {} }
    },
    "advertisement": {
        "interstitial": { "minimumDelay": 60 },
        "advancedBanners": {/* see Advanced Banners */}
    },
    "payments": [
        {
            "id": "coins_100",
            "playgama": { "amount": 1 },
            "playdeck": { "amount": 1, "description": "100 Coins" }
        }
    ],
    "leaderboards": [{ "id": "high_score" }]
}
Bridge 会从构建根目录读取
playgama-bridge-config.json
。该文件用于声明平台 ID、IAP 商品目录、广告版位、排行榜及其他设置。可以使用配置编辑器生成或编辑此文件。
模板:
json
{
    "platforms": {
        "playgama": { "options": {} },
        "yandex": { "options": {} }
    },
    "advertisement": {
        "interstitial": { "minimumDelay": 60 },
        "advancedBanners": {/* see Advanced Banners */}
    },
    "payments": [
        {
            "id": "coins_100",
            "playgama": { "amount": 1 },
            "playdeck": { "amount": 1, "description": "100 Coins" }
        }
    ],
    "leaderboards": [{ "id": "high_score" }]
}

Initialization

初始化

Call
bridge.initialize()
and wait for the promise before touching any other API.
javascript
bridge
    .initialize()
    .then(() => {
        // SDK is ready, all bridge.* APIs are usable now
    })
    .catch((error) => {
        // Initialization failed — handle gracefully (the SDK still falls back to mock)
    });
After init, send
game_ready
once the game is fully loaded and the player can interact:
javascript
bridge.platform.sendMessage('game_ready');
This dismisses the platform loader. It is required — without it most platforms keep showing their splash on top of the game.
调用
bridge.initialize()
,并且必须等待 Promise 完成后再使用其他任何 API。
javascript
bridge
    .initialize()
    .then(() => {
        // SDK is ready, all bridge.* APIs are usable now
    })
    .catch((error) => {
        // Initialization failed — handle gracefully (the SDK still falls back to mock)
    });
初始化完成后,在游戏完全加载且玩家可以进行交互时发送一次
game_ready
:
javascript
bridge.platform.sendMessage('game_ready');
这会关闭平台加载界面。该消息是必需的,否则大多数平台会继续在游戏上方显示启动画面。

Required integration checklist

必需集成检查清单

For every game:
  1. Install SDK + create
    playgama-bridge-config.json
    .
  2. Wait for
    bridge.initialize()
    .
  3. Read
    bridge.platform.language
    and apply localization.
  4. Load saved progress with
    bridge.storage.get(...)
    .
  5. Send
    bridge.platform.sendMessage('game_ready')
    once the first playable frame is rendered.
  6. React to
    AUDIO_STATE_CHANGED
    and
    PAUSE_STATE_CHANGED
    events.
  7. Show interstitial ads at natural breakpoints (level transitions, game over, menu↔gameplay).
Interstitials are mandatory for revenue share. Without them games can be rejected during moderation.
对于每款游戏:
  1. 安装 SDK 并创建
    playgama-bridge-config.json
    。
  2. 等待
    bridge.initialize()
    完成。
  3. 读取
    bridge.platform.language
    并应用本地化。
  4. 使用
    bridge.storage.get(...)
    加载已保存的进度。
  5. 首个可玩帧渲染完成后,发送
    bridge.platform.sendMessage('game_ready')
    。
  6. 响应
    AUDIO_STATE_CHANGED
    和
    PAUSE_STATE_CHANGED
    事件。
  7. 在自然断点展示插屏广告(关卡切换、游戏结束、菜单与游戏场景之间切换)。
插屏广告是参与收入分成所必需的。缺少插屏广告时,游戏可能会在审核期间被拒绝。

Platform module —
bridge.platform

平台模块——
bridge.platform

Properties

属性

PropertyTypeDescription
bridge.platform.id
stringCurrent platform ID. One of:
playgama
,
vk
,
ok
,
yandex
,
facebook
,
crazy_games
,
game_distribution
,
playdeck
,
telegram
,
y8
,
lagged
,
msn
,
microsoft_store
,
poki
,
qa_tool
,
discord
,
gamepush
,
bitquest
,
huawei
,
jio_games
,
reddit
,
youtube
,
mock
,
xiaomi
bridge.platform.sdk
object | nullNative platform SDK (when Bridge exposes it). Use only for things Bridge doesn't wrap
bridge.platform.language
stringISO 639-1 user language (
en
,
ru
, ...). Falls back to browser language
bridge.platform.payload
string | nullURL launch payload (referral code, deep link). Format is platform-specific
bridge.platform.tld
string | nullTop-level domain (
com
,
ru
, ...) when host provides it
bridge.platform.isAudioEnabled
booleanWhether the host platform currently allows game audio
bridge.platform.isGetAllGamesSupported
booleanCapability flag for
getAllGames()
bridge.platform.isGetGameByIdSupported
booleanCapability flag for
getGameById()
属性类型说明
bridge.platform.id
string当前平台 ID,取值包括:
playgama
、
vk
、
ok
、
yandex
、
facebook
、
crazy_games
、
game_distribution
、
playdeck
、
telegram
、
y8
、
lagged
、
msn
、
microsoft_store
、
poki
、
qa_tool
、
discord
、
gamepush
、
bitquest
、
huawei
、
jio_games
、
reddit
、
youtube
、
mock
、
xiaomi
bridge.platform.sdk
object | nullBridge 暴露时为原生平台 SDK。仅用于 Bridge 未封装的功能
bridge.platform.language
stringISO 639-1 用户语言(
en
、
ru
等)。回退到浏览器语言
bridge.platform.payload
string | nullURL 启动载荷(推荐码、深层链接)。格式因平台而异
bridge.platform.tld
string | null宿主提供时为顶级域名(
com
、
ru
等)
bridge.platform.isAudioEnabled
boolean宿主平台当前是否允许游戏音频
bridge.platform.isGetAllGamesSupported
boolean是否支持
getAllGames()
的能力标志
bridge.platform.isGetGameByIdSupported
boolean是否支持
getGameById()
的能力标志

Methods

方法

javascript
// Server time — UTC ms — use for daily rewards / cooldowns instead of local clock
bridge.platform
    .getServerTime()
    .then((utcMs) => console.log(utcMs))
    .catch((error) => {});

// All games by the same developer (for "More games" screens)
bridge.platform.getAllGames().then((games) => {
    // platform-specific shape, on yandex: { appID, title, url, coverURL, iconURL }
});

// One game by ID (cross-promotion)
bridge.platform.getGameById({ gameId: '111111' }).then((game) => {
    // { appID, title, url, coverURL, iconURL, isAvailable }
});

// Lifecycle messages — see table below
bridge.platform.sendMessage('game_ready');

// Custom messages — used by Advanced Banners config
bridge.platform.sendCustomMessage('shop_opened');
javascript
// Server time — UTC ms — use for daily rewards / cooldowns instead of local clock
bridge.platform
    .getServerTime()
    .then((utcMs) => console.log(utcMs))
    .catch((error) => {});

// All games by the same developer (for "More games" screens)
bridge.platform.getAllGames().then((games) => {
    // platform-specific shape, on yandex: { appID, title, url, coverURL, iconURL }
});

// One game by ID (cross-promotion)
bridge.platform.getGameById({ gameId: '111111' }).then((game) => {
    // { appID, title, url, coverURL, iconURL, isAvailable }
});

// Lifecycle messages — see table below
bridge.platform.sendMessage('game_ready');

// Custom messages — used by Advanced Banners config
bridge.platform.sendCustomMessage('shop_opened');

Built-in lifecycle messages

内置生命周期消息

MessagePayloadWhen to send
game_ready
—Game loaded, loading screen done, player can interact (required)
in_game_loading_started
—Sub-loading begins (e.g. level load)
in_game_loading_stopped
—Sub-loading finished
gameplay_started
—Active gameplay begins
gameplay_stopped
—Active gameplay ends (menu, pause, game over)
player_got_achievement
—Significant moment (boss defeated, record set)
level_started
{ world, level }
(optional)
Level begins
level_completed
{ world, level }
Level won
level_failed
{ world, level }
Level lost
level_paused
{ world, level }
Pause menu opened
level_resumed
{ world, level }
Resumed from pause
These also trigger Advanced Banners placements automatically.
消息载荷发送时机
game_ready
—游戏已加载、加载界面结束且玩家可以交互(必需)
in_game_loading_started
—子加载开始(例如加载关卡)
in_game_loading_stopped
—子加载结束
gameplay_started
—活跃游戏开始
gameplay_stopped
—活跃游戏结束(菜单、暂停、游戏结束)
player_got_achievement
—重要时刻(击败 Boss、刷新纪录)
level_started
{ world, level }
(可选)
关卡开始
level_completed
{ world, level }
关卡胜利
level_failed
{ world, level }
关卡失败
level_paused
{ world, level }
打开暂停菜单
level_resumed
{ world, level }
从暂停中恢复
这些消息还会自动触发 Advanced Banners 版位。

Events

事件

javascript
// Audio mute/unmute requests from the host
bridge.platform.on(bridge.EVENT_NAME.AUDIO_STATE_CHANGED, (isEnabled) => {
    if (!isEnabled) muteGameAudio();
    else restoreGameAudio();
});

// Pause/resume requests (tab switch, platform overlay, etc.)
bridge.platform.on(bridge.EVENT_NAME.PAUSE_STATE_CHANGED, (isPaused) => {
    if (isPaused) pauseGame();
    else resumeGame();
});
Both events are required to handle — many platforms enforce this during moderation.
javascript
// Audio mute/unmute requests from the host
bridge.platform.on(bridge.EVENT_NAME.AUDIO_STATE_CHANGED, (isEnabled) => {
    if (!isEnabled) muteGameAudio();
    else restoreGameAudio();
});

// Pause/resume requests (tab switch, platform overlay, etc.)
bridge.platform.on(bridge.EVENT_NAME.PAUSE_STATE_CHANGED, (isPaused) => {
    if (isPaused) pauseGame();
    else resumeGame();
});
这两个事件都是必须处理的——许多平台会在审核期间强制检查这些事件。

Player module —
bridge.player

玩家模块——
bridge.player

Player identity and platform authorization.
PropertyTypeDescription
bridge.player.id
string | nullPlatform player ID, only when authorized
bridge.player.name
string | nullDisplay name from platform
bridge.player.photos
string[]Avatar URLs sorted by increasing resolution;
[]
if none
bridge.player.extra
objectPlatform-specific auth/verification data
bridge.player.isAuthorizationSupported
booleanWhether host supports a login flow
bridge.player.isAuthorized
booleanWhether the player is currently authorized
javascript
// Trigger only from a direct user action (button tap)
bridge.player
    .authorize({})
    .then(() => {
        // bridge.player.id, .name, .photos now populated
    })
    .catch((error) => {
        // Cancelled or failed
    });
Some platforms expose guest data even before authorization (
name
, partial
id
). Don't treat those as verified — only post-authorization data is trustworthy.
用于管理玩家身份和平台授权。
属性类型说明
bridge.player.id
string | null平台玩家 ID,仅在授权后可用
bridge.player.name
string | null平台显示名称
bridge.player.photos
string[]头像 URL,按分辨率从低到高排列;没有时为
[]
bridge.player.extra
object平台特定的授权/验证数据
bridge.player.isAuthorizationSupported
boolean宿主是否支持登录流程
bridge.player.isAuthorized
boolean玩家当前是否已授权
javascript
// Trigger only from a direct user action (button tap)
bridge.player
    .authorize({})
    .then(() => {
        // bridge.player.id, .name, .photos now populated
    })
    .catch((error) => {
        // Cancelled or failed
    });
某些平台会在授权前提供访客数据(
name
、部分
id
)。不要将这些数据视为已验证数据——只有授权后的数据才可信。

Backend verification

后端验证

Use
bridge.player.extra
to verify player identity from your server. Currently only
playgama
,
msn
, and
microsoft_store
are supported by Playgama's verification API:
bash
curl -X POST 'https://playgama.com/api/bridge/v1/verify' \
  -H 'Content-Type: application/json' \
  -d '{"platform":"<PLATFORM_ID>","type":"authorization","data":{ <...bridge.player.extra> }}'
使用
bridge.player.extra
在你的服务器上验证玩家身份。目前,Playgama 的验证 API 仅支持
playgama
、
msn
和
microsoft_store
:
bash
curl -X POST 'https://playgama.com/api/bridge/v1/verify' \
  -H 'Content-Type: application/json' \
  -d '{"platform":"<PLATFORM_ID>","type":"authorization","data":{ <...bridge.player.extra> }}'

Response: { success, errorMessage?, playerId?, publisherPlayerId? }

Response: { success, errorMessage?, playerId?, publisherPlayerId? }

undefined
undefined

Device module —
bridge.device

设备模块——
bridge.device

javascript
bridge.device.type; // 'mobile' | 'tablet' | 'desktop' | 'tv'
Use for broad UI adaptation — touch vs. keyboard input, asset quality, layout. Don't make business logic decisions on device type.
javascript
bridge.device.type; // 'mobile' | 'tablet' | 'desktop' | 'tv'
用于进行粗粒度 UI 适配——触控与键盘输入、素材质量、布局等。不要根据设备类型做出业务逻辑决策。

Storage module —
bridge.storage

存储模块——
bridge.storage

Persistent player data (progress, settings, currency). Almost every game needs this.
用于持久化玩家数据(进度、设置、货币)。几乎每款游戏都需要此功能。

Two storage types

两种存储类型

TypePersistenceCross-deviceWhen
local_storage
Browser localStorageNoDefault for offline single-device save
platform_internal
Platform cloud serversYesPlayer is authorized + you want cloud sync
javascript
bridge.storage.defaultType;
// 'local_storage' or 'platform_internal' — host's preferred type

bridge.storage.isAvailable('local_storage');
bridge.storage.isAvailable('platform_internal');
// Check before forcing a specific type
类型持久化方式跨设备使用场景
local_storage
浏览器 localStorage否离线单设备存档的默认选择
platform_internal
平台云服务器是玩家已授权且希望使用云同步
javascript
bridge.storage.defaultType;
// 'local_storage' or 'platform_internal' — host's preferred type

bridge.storage.isAvailable('local_storage');
bridge.storage.isAvailable('platform_internal');
// Check before forcing a specific type

Load

读取

javascript
// Single key
bridge.storage.get('level').then((value) => {
    // value === null when key is missing — always have a default in your game state
});

// Multiple keys — returns array, same order
bridge.storage.get(['level', 'coins', 'settings']).then(([level, coins, settings]) => {});

// Force specific storage type (third arg)
bridge.storage.get('level', 'local_storage');
javascript
// Single key
bridge.storage.get('level').then((value) => {
    // value === null when key is missing — always have a default in your game state
});

// Multiple keys — returns array, same order
bridge.storage.get(['level', 'coins', 'settings']).then(([level, coins, settings]) => {});

// Force specific storage type (third arg)
bridge.storage.get('level', 'local_storage');

Save

保存

javascript
bridge.storage.set('level', 'dungeon_3');

bridge.storage
    .set(['level', 'coins', 'tutorial_done'], ['dungeon_3', 42, true])
    .then(() => {
        /* persisted */
    })
    .catch((error) => {});

bridge.storage.set('level', 'dungeon_3', 'platform_internal');
Save on meaningful state change (level done, purchase, settings change). Do not save every frame.
javascript
bridge.storage.set('level', 'dungeon_3');

bridge.storage
    .set(['level', 'coins', 'tutorial_done'], ['dungeon_3', 42, true])
    .then(() => {
        /* persisted */
    })
    .catch((error) => {});

bridge.storage.set('level', 'dungeon_3', 'platform_internal');
在有意义的状态变化时保存(关卡完成、购买、设置变更)。不要每帧都保存。

Delete

删除

javascript
bridge.storage.delete('level');
bridge.storage.delete(['level', 'coins']);
javascript
bridge.storage.delete('level');
bridge.storage.delete(['level', 'coins']);

Advertisement module —
bridge.advertisement

广告模块——
bridge.advertisement

playgama-bridge-config.json
controls placements. Never show ads during active gameplay — only at natural pauses.
广告版位由
playgama-bridge-config.json
控制。游戏进行中绝不要展示广告——只在自然停顿期间展示。

Format overview

格式概览

FormatStatusWhen
InterstitialRequiredLevel transitions, game over, menu↔gameplay
RewardedRecommendedPlayer opts in for in-game reward
BannerRecommendedIdle screens (menu, lobby, pause)
Advanced BannersRecommendedCustom multi-position responsive banner layouts
AdBlock checkOptionalAdapt UI when ads are blocked
格式状态使用场景
插屏广告必需关卡切换、游戏结束、菜单与游戏场景之间切换
激励广告推荐玩家主动选择观看广告以获得游戏内奖励
Banner推荐空闲界面(菜单、大厅、暂停)
Advanced Banners推荐自定义多位置响应式 Banner 布局
AdBlock 检查可选广告被屏蔽时调整 UI

Interstitial — required

插屏广告——必需

javascript
bridge.advertisement.isInterstitialSupported; // boolean

bridge.advertisement.minimumDelayBetweenInterstitial; // default 60 seconds
bridge.advertisement.setMinimumDelayBetweenInterstitial(30); // override

bridge.advertisement.interstitialState;
// 'loading' | 'opened' | 'closed' | 'failed'

bridge.advertisement.on(bridge.EVENT_NAME.INTERSTITIAL_STATE_CHANGED, (state) => {
    if (state === 'opened') {
        muteGameAudio();
        pauseGame();
    } else if (state === 'closed' || state === 'failed') {
        restoreGameAudio();
        resumeGame();
    }
});

// Optional placement string
bridge.advertisement.showInterstitial('level_complete');
Do not call
showInterstitial()
at game start — platforms that support a startup interstitial show it automatically. Calling it explicitly causes duplicate ads.
Also check
interstitialState
right after init: if it is already
opened
, mute and pause immediately.
javascript
bridge.advertisement.isInterstitialSupported; // boolean

bridge.advertisement.minimumDelayBetweenInterstitial; // default 60 seconds
bridge.advertisement.setMinimumDelayBetweenInterstitial(30); // override

bridge.advertisement.interstitialState;
// 'loading' | 'opened' | 'closed' | 'failed'

bridge.advertisement.on(bridge.EVENT_NAME.INTERSTITIAL_STATE_CHANGED, (state) => {
    if (state === 'opened') {
        muteGameAudio();
        pauseGame();
    } else if (state === 'closed' || state === 'failed') {
        restoreGameAudio();
        resumeGame();
    }
});

// Optional placement string
bridge.advertisement.showInterstitial('level_complete');
在游戏开始时不要调用
showInterstitial()
——支持启动插屏广告的平台会自动展示它。显式调用会导致广告重复。
初始化后还应立即检查
interstitialState
:如果它已经是
opened
,应立即静音并暂停游戏。

Rewarded

激励广告

javascript
bridge.advertisement.isRewardedSupported;

bridge.advertisement.rewardedState;
// 'loading' | 'opened' | 'closed' | 'rewarded' | 'failed'

bridge.advertisement.rewardedPlacement; // current placement string

bridge.advertisement.on(bridge.EVENT_NAME.REWARDED_STATE_CHANGED, (state) => {
    switch (state) {
        case 'opened':
            muteGameAudio();
            pauseGame();
            break;
        case 'rewarded':
            // ONLY here grant the reward
            grantReward(bridge.advertisement.rewardedPlacement);
            break;
        case 'closed':
        case 'failed':
            restoreGameAudio();
            resumeGame();
            break;
    }
});

bridge.advertisement.showRewarded('double_coins');
Critical: grant the reward only on the
rewarded
state. Granting on
closed
lets players claim rewards without watching the ad.
javascript
bridge.advertisement.isRewardedSupported;

bridge.advertisement.rewardedState;
// 'loading' | 'opened' | 'closed' | 'rewarded' | 'failed'

bridge.advertisement.rewardedPlacement; // current placement string

bridge.advertisement.on(bridge.EVENT_NAME.REWARDED_STATE_CHANGED, (state) => {
    switch (state) {
        case 'opened':
            muteGameAudio();
            pauseGame();
            break;
        case 'rewarded':
            // ONLY here grant the reward
            grantReward(bridge.advertisement.rewardedPlacement);
            break;
        case 'closed':
        case 'failed':
            restoreGameAudio();
            resumeGame();
            break;
    }
});

bridge.advertisement.showRewarded('double_coins');
**关键:**仅在
rewarded
状态下发放奖励。如果在
closed
时发放奖励,玩家不观看广告也能领取奖励。

Banner

Banner

javascript
bridge.advertisement.isBannerSupported;

let position = 'bottom'; // 'top' | 'bottom', default 'bottom'
let placement = 'menu'; // optional
bridge.advertisement.showBanner(position, placement);

bridge.advertisement.hideBanner();

bridge.advertisement.bannerState;
// 'loading' | 'shown' | 'hidden' | 'failed'

bridge.advertisement.on(bridge.EVENT_NAME.BANNER_STATE_CHANGED, (state) => {});
javascript
bridge.advertisement.isBannerSupported;

let position = 'bottom'; // 'top' | 'bottom', default 'bottom'
let placement = 'menu'; // optional
bridge.advertisement.showBanner(position, placement);

bridge.advertisement.hideBanner();

bridge.advertisement.bannerState;
// 'loading' | 'shown' | 'hidden' | 'failed'

bridge.advertisement.on(bridge.EVENT_NAME.BANNER_STATE_CHANGED, (state) => {});

Advanced Banners

Advanced Banners

Multi-position, responsive banner layouts driven by config. Auto-hidden during interstitials/rewarded, auto-restored after. Re-evaluate on orientation/resize (200ms debounce).
javascript
bridge.advertisement.isAdvancedBannersSupported;

// Method 1 — explicit
bridge.advertisement.showAdvancedBanners('main_menu');
bridge.advertisement.hideAdvancedBanners();

// Method 2 — automatic via platform messages (recommended)
bridge.platform.sendMessage('gameplay_stopped'); // shows if configured
bridge.platform.sendMessage('gameplay_started'); // hides if action: 'hide'
bridge.platform.sendCustomMessage('shop_opened');

// State
bridge.advertisement.advancedBannersState;
bridge.advertisement.on('advanced_banners_state_changed', (state) => {});
Config example:
json
{
    "advertisement": {
        "advancedBanners": {
            "disable": false,
            "placementFallback": "main_menu",
            "main_menu": {
                "default": [{ "width": "20%", "height": "25%", "top": "10%", "right": "10%" }]
            },
            "gameplay_stopped": {
                "action": "show",
                "default": [{ "width": "20%", "height": "25%", "bottom": "10%", "right": "5%" }],
                "mobile:portrait": [
                    { "width": "100%", "height": "8%", "bottom": "0", "left": "0" }
                ],
                "desktop:landscape:w>1200": [
                    { "width": "10%", "height": "60%", "top": "10%", "left": "1%" },
                    { "width": "10%", "height": "60%", "top": "10%", "right": "1%" }
                ]
            },
            "gameplay_started": { "action": "hide" }
        }
    }
}
由配置驱动的多位置响应式 Banner 布局。插屏广告或激励广告期间会自动隐藏,并在之后自动恢复。屏幕方向或尺寸变化时需要重新评估(200ms 防抖)。
javascript
bridge.advertisement.isAdvancedBannersSupported;

// Method 1 — explicit
bridge.advertisement.showAdvancedBanners('main_menu');
bridge.advertisement.hideAdvancedBanners();

// Method 2 — automatic via platform messages (recommended)
bridge.platform.sendMessage('gameplay_stopped'); // shows if configured
bridge.platform.sendMessage('gameplay_started'); // hides if action: 'hide'
bridge.platform.sendCustomMessage('shop_opened');

// State
bridge.advertisement.advancedBannersState;
bridge.advertisement.on('advanced_banners_state_changed', (state) => {});
配置示例:
json
{
    "advertisement": {
        "advancedBanners": {
            "disable": false,
            "placementFallback": "main_menu",
            "main_menu": {
                "default": [{ "width": "20%", "height": "25%", "top": "10%", "right": "10%" }]
            },
            "gameplay_stopped": {
                "action": "show",
                "default": [{ "width": "20%", "height": "25%", "bottom": "10%", "right": "5%" }],
                "mobile:portrait": [
                    { "width": "100%", "height": "8%", "bottom": "0", "left": "0" }
                ],
                "desktop:landscape:w>1200": [
                    { "width": "10%", "height": "60%", "top": "10%", "left": "1%" },
                    { "width": "10%", "height": "60%", "top": "10%", "right": "1%" }
                ]
            },
            "gameplay_started": { "action": "hide" }
        }
    }
}

Condition keys

条件键

Colon-separated segments, all must match:
SegmentExamples
Device type
mobile
,
desktop
,
tablet
,
tv
Orientation
portrait
,
landscape
Width
w>600
,
w<=1024
,
w>=768
Height
h>400
,
h<=900
Aspect ratio
ar>1.5
,
ar>=1.78
,
ar<=1.0
Canvas mode
canvas
(use canvas size instead of window)
Priority: device type +4, orientation +2, canvas +1, each w/h/ar condition +1. Ties broken by more segments → closer threshold to actual value.
default
is fallback (-1).
以冒号分隔的片段,必须全部匹配:
片段示例
设备类型
mobile
、
desktop
、
tablet
、
tv
屏幕方向
portrait
、
landscape
宽度
w>600
、
w<=1024
、
w>=768
高度
h>400
、
h<=900
宽高比
ar>1.5
、
ar>=1.78
、
ar<=1.0
Canvas 模式
canvas
(使用 Canvas 尺寸而不是窗口尺寸)
优先级:设备类型 +4、屏幕方向 +2、canvas +1,每个 w/h/ar 条件 +1。并列时,片段更多者优先,然后选择阈值更接近实际值的条件。
default
是回退项(-1)。

Banner object

Banner 对象

CSS positioning:
width
,
height
,
top
,
bottom
,
left
,
right
— all strings (
"300px"
,
"100%"
,
"0"
).
CSS 定位属性:
width
、
height
、
top
、
bottom
、
left
、
right
——全部为字符串(
"300px"
、
"100%"
、
"0"
)。

AdBlock detection

AdBlock 检测

javascript
bridge.advertisement.checkAdBlock().then((isBlocked) => {
    // true | false — informational only, doesn't suppress ads
});
javascript
bridge.advertisement.checkAdBlock().then((isBlocked) => {
    // true | false — informational only, doesn't suppress ads
});

Payments module —
bridge.payments

支付模块——
bridge.payments

In-game purchases. Optional but often the highest-revenue feature.
用于应用内购买。可选,但通常是最具收益的功能。

Product types

商品类型

TypeExampleLifecycle
Permanent"Remove ads", DLCBought once. Check ownership with
getPurchases()
on every launch
ConsumableCoins, gems, energyBought → granted → must be consumed with
consumePurchase(id)
. Until consumed, repeat purchases of the same product fail
类型示例生命周期
永久型"Remove ads"、DLC一次性购买。每次启动时使用
getPurchases()
检查所有权
可消耗型金币、宝石、能量购买 → 发放 → 必须消耗,调用
consumePurchase(id)
。消耗前,重复购买同一商品会失败

API

API

javascript
bridge.payments.isSupported;

// Catalog — localized prices, currencies, metadata
bridge.payments.getCatalog().then((items) => {
    items.forEach((item) => {
        console.log(item.id);
        console.log(item.price); // formatted string
        console.log(item.priceCurrencyCode); // ISO 4217
        console.log(item.priceValue); // numeric value
    });
});

// Purchase — only from a direct user action
bridge.payments
    .purchase('coins_100')
    .then((purchase) => {
        // Platform-specific shape, always has .id
        grantItems(purchase.id);
        // For consumables, immediately consume:
        return bridge.payments.consumePurchase(purchase.id);
    })
    .catch((error) => {
        // Cancelled or failed
    });

// Consume a consumable after granting items
bridge.payments.consumePurchase('coins_100').then((purchase) => {});

// Active purchases — call on every launch and after reconnect
// to recover items from purchases interrupted by disconnects
bridge.payments.getPurchases().then((purchases) => {
    purchases.forEach((p) => {
        // Permanent: check ownership here
        // Consumable: grant items + consume
    });
});
javascript
bridge.payments.isSupported;

// Catalog — localized prices, currencies, metadata
bridge.payments.getCatalog().then((items) => {
    items.forEach((item) => {
        console.log(item.id);
        console.log(item.price); // formatted string
        console.log(item.priceCurrencyCode); // ISO 4217
        console.log(item.priceValue); // numeric value
    });
});

// Purchase — only from a direct user action
bridge.payments
    .purchase('coins_100')
    .then((purchase) => {
        // Platform-specific shape, always has .id
        grantItems(purchase.id);
        // For consumables, immediately consume:
        return bridge.payments.consumePurchase(purchase.id);
    })
    .catch((error) => {
        // Cancelled or failed
    });

// Consume a consumable after granting items
bridge.payments.consumePurchase('coins_100').then((purchase) => {});

// Active purchases — call on every launch and after reconnect
// to recover items from purchases interrupted by disconnects
bridge.payments.getPurchases().then((purchases) => {
    purchases.forEach((p) => {
        // Permanent: check ownership here
        // Consumable: grant items + consume
    });
});

Catalog config

商品目录配置

json
{
    "payments": [
        {
            "id": "coins_100",
            "playgama": { "amount": 1 },
            "playdeck": { "amount": 1, "description": "100 Coins" }
        }
    ]
}
id
is your in-game identifier; per-platform keys carry platform-specific price/metadata.
json
{
    "payments": [
        {
            "id": "coins_100",
            "playgama": { "amount": 1 },
            "playdeck": { "amount": 1, "description": "100 Coins" }
        }
    ]
}
id
是游戏内标识符;各平台专属键用于保存平台特定的价格和元数据。

Backend verification

后端验证

bash
curl -X POST 'https://playgama.com/api/bridge/v1/verify' \
  -H 'Content-Type: application/json' \
  -d '{"platform":"<PLATFORM_ID>","type":"purchase","data":{ <...purchase> }}'
bash
curl -X POST 'https://playgama.com/api/bridge/v1/verify' \
  -H 'Content-Type: application/json' \
  -d '{"platform":"<PLATFORM_ID>","type":"purchase","data":{ <...purchase> }}'

Response: { success, errorMessage?, orderId?, productId?, externalId? }

Response: { success, errorMessage?, orderId?, productId?, externalId? }


Currently supports `playgama`, `msn`, `microsoft_store`.

目前支持 `playgama`、`msn` 和 `microsoft_store`。

Leaderboards module —
bridge.leaderboards

排行榜模块——
bridge.leaderboards

Optional. First check
bridge.leaderboards.type
:
TypeAction
not_available
Hide all leaderboard UI
in_game
Call
setScore(...)
, render your own UI from
getEntries(...)
native
Call
setScore(...)
only — platform renders the board
native_popup
Call
setScore(...)
and
showNativePopup(...)
to open overlay
可选。首先检查
bridge.leaderboards.type
:
类型操作
not_available
隐藏所有排行榜 UI
in_game
调用
setScore(...)
,并使用
getEntries(...)
自行渲染 UI
native
仅调用
setScore(...)
,由平台渲染排行榜
native_popup
调用
setScore(...)
和
showNativePopup(...)
以打开弹窗

API

API

javascript
bridge.leaderboards.type;

bridge.leaderboards.setScore('high_score', 1000).then(() => {});

// Only when type === 'in_game'
bridge.leaderboards.getEntries('high_score').then((entries) => {
    entries.forEach((e) => {
        console.log(e.id);
        console.log(e.name);
        console.log(e.photo);
        console.log(e.score);
        console.log(e.rank);
    });
});

// Only when type === 'native_popup'
bridge.leaderboards.showNativePopup('high_score');
javascript
bridge.leaderboards.type;

bridge.leaderboards.setScore('high_score', 1000).then(() => {});

// Only when type === 'in_game'
bridge.leaderboards.getEntries('high_score').then((entries) => {
    entries.forEach((e) => {
        console.log(e.id);
        console.log(e.name);
        console.log(e.photo);
        console.log(e.score);
        console.log(e.rank);
    });
});

// Only when type === 'native_popup'
bridge.leaderboards.showNativePopup('high_score');

Config

配置

json
{
    "leaderboards": [
        {
            "id": "high_score",
            "<PLATFORM_ID>": "<NATIVE_ID_FOR_PLATFORM>"
        }
    ]
}
Use the in-game
id
in code; per-platform overrides map to native leaderboard IDs when they differ.
json
{
    "leaderboards": [
        {
            "id": "high_score",
            "<PLATFORM_ID>": "<NATIVE_ID_FOR_PLATFORM>"
        }
    ]
}
代码中使用游戏内
id
;当各平台的原生排行榜 ID 不同时,可通过平台专属覆盖项进行映射。

Achievements module —
bridge.achievements

成就模块——
bridge.achievements

Optional. Achievement IDs are configured in each platform's developer dashboard, not in
playgama-bridge-config.json
.
javascript
bridge.achievements.isSupported;
bridge.achievements.isGetListSupported;
bridge.achievements.isNativePopupSupported;

// Unlock — send each achievement only once
let options = {};
switch (bridge.platform.id) {
    case 'y8':
        options = { achievement: 'ACHIEVEMENT_NAME', achievementkey: 'ACHIEVEMENT_KEY' };
        break;
    case 'lagged':
        options = { achievement: 'ACHIEVEMENT_ID' };
        break;
}
bridge.achievements.unlock(options).then(() => {});

// List (platform-specific shape)
bridge.achievements.getList({}).then((list) => {});

// Native overlay
bridge.achievements.showNativePopup({});
Keep a constants file in your game that maps internal milestones to per-platform achievement IDs.
可选。成就 ID 在每个平台的开发者控制台中配置,而不是在
playgama-bridge-config.json
中配置。
javascript
bridge.achievements.isSupported;
bridge.achievements.isGetListSupported;
bridge.achievements.isNativePopupSupported;

// Unlock — send each achievement only once
let options = {};
switch (bridge.platform.id) {
    case 'y8':
        options = { achievement: 'ACHIEVEMENT_NAME', achievementkey: 'ACHIEVEMENT_KEY' };
        break;
    case 'lagged':
        options = { achievement: 'ACHIEVEMENT_ID' };
        break;
}
bridge.achievements.unlock(options).then(() => {});

// List (platform-specific shape)
bridge.achievements.getList({}).then((list) => {});

// Native overlay
bridge.achievements.showNativePopup({});
在游戏项目中维护一个常量文件,将内部里程碑映射到各平台的成就 ID。

Social module —
bridge.social

社交模块——
bridge.social

All optional. Each method has an
is*Supported
flag — always check it and hide the button when unsupported. Trigger only from direct user action.
所有功能均为可选。每个方法都有
is*Supported
标志——务必检查,并在不支持时隐藏按钮。仅可通过用户的直接操作触发。

Capability matrix

能力矩阵

FeatureFlagTypical platforms
Share
isShareSupported
VK, Facebook, MSN
Join community
isJoinCommunitySupported
VK, OK, Facebook
Invite friends
isInviteFriendsSupported
VK, OK, Facebook
Create post
isCreatePostSupported
VK, OK
Add to favorites
isAddToFavoritesSupported
VK, Yandex
Add to home screen
isAddToHomeScreenSupported
Yandex, GameSnacks
Rate game
isRateSupported
VK, GameSnacks, Yandex
External links
isExternalLinksAllowed
Most non-portal platforms
功能标志常见平台
分享
isShareSupported
VK、Facebook、MSN
加入社区
isJoinCommunitySupported
VK、OK、Facebook
邀请好友
isInviteFriendsSupported
VK、OK、Facebook
创建帖子
isCreatePostSupported
VK、OK
添加到收藏
isAddToFavoritesSupported
VK、Yandex
添加到主屏幕
isAddToHomeScreenSupported
Yandex、GameSnacks
评价游戏
isRateSupported
VK、GameSnacks、Yandex
外部链接
isExternalLinksAllowed
大多数非门户平台

Share

分享

javascript
let options = {};
switch (bridge.platform.id) {
    case 'vk':
        options = { link: 'https://...' };
        break;
    case 'facebook':
        options = { image: 'base64...', text: 'Check this game!' };
        break;
    case 'msn':
        options = { title: '...', image: 'base64 or URL', text: '...' };
        break;
}
bridge.social.share(options).then(() => {});
javascript
let options = {};
switch (bridge.platform.id) {
    case 'vk':
        options = { link: 'https://...' };
        break;
    case 'facebook':
        options = { image: 'base64...', text: 'Check this game!' };
        break;
    case 'msn':
        options = { title: '...', image: 'base64 or URL', text: '...' };
        break;
}
bridge.social.share(options).then(() => {});

Join community

加入社区

javascript
let options = {};
switch (bridge.platform.id) {
    case 'vk':
    case 'ok':
        options = { groupId: 123456 };
        break;
    case 'facebook':
        options = { isPage: true };
        break; // false → group
}
bridge.social.joinCommunity(options);
javascript
let options = {};
switch (bridge.platform.id) {
    case 'vk':
    case 'ok':
        options = { groupId: 123456 };
        break;
    case 'facebook':
        options = { isPage: true };
        break; // false → group
}
bridge.social.joinCommunity(options);

Invite friends

邀请好友

javascript
let options = {};
switch (bridge.platform.id) {
    case 'ok':
        options = { text: 'Hello!' };
        break;
    case 'facebook':
        options = { image: 'base64...', text: 'Join me!' };
        break;
}
bridge.social.inviteFriends(options);
javascript
let options = {};
switch (bridge.platform.id) {
    case 'ok':
        options = { text: 'Hello!' };
        break;
    case 'facebook':
        options = { image: 'base64...', text: 'Join me!' };
        break;
}
bridge.social.inviteFriends(options);

Create post

创建帖子

javascript
// OK example with mixed media
bridge.social.createPost({
    media: [
        { type: 'text', text: 'Hello!' },
        { type: 'link', url: 'https://...' },
        {
            type: 'poll',
            question: 'Like the game?',
            answers: [{ text: 'Yes' }, { text: 'No' }],
            options: 'SingleChoice,AnonymousVoting'
        }
    ]
});
javascript
// OK example with mixed media
bridge.social.createPost({
    media: [
        { type: 'text', text: 'Hello!' },
        { type: 'link', url: 'https://...' },
        {
            type: 'poll',
            question: 'Like the game?',
            answers: [{ text: 'Yes' }, { text: 'No' }],
            options: 'SingleChoice,AnonymousVoting'
        }
    ]
});

Other social

其他社交功能

javascript
bridge.social.addToFavorites().then(() => {});
bridge.social.addToHomeScreen().then(() => {});
bridge.social.rate().then(() => {});
javascript
bridge.social.addToFavorites().then(() => {});
bridge.social.addToHomeScreen().then(() => {});
bridge.social.rate().then(() => {});

Remote Config module —
bridge.remoteConfig

远程配置模块——
bridge.remoteConfig

Optional. Read game settings (difficulty, drop rates, feature flags, A/B values) at runtime without rebuilding.
javascript
bridge.remoteConfig.isSupported;

let options = {};
switch (bridge.platform.id) {
    case 'yandex':
        options = {
            clientFeatures: [{ name: 'levels', value: '5' }]
        };
        break;
}

bridge.remoteConfig
    .get(options)
    .then((data) => {
        // e.g. { showFullscreenAdOnStart: 'no', difficulty: 'hard' }
    })
    .catch((error) => {});
Always have hardcoded defaults for every key. The request can fail or return partial data.
可选。在运行时读取游戏设置(难度、掉率、功能开关、A/B 测试值),无需重新构建。
javascript
bridge.remoteConfig.isSupported;

let options = {};
switch (bridge.platform.id) {
    case 'yandex':
        options = {
            clientFeatures: [{ name: 'levels', value: '5' }]
        };
        break;
}

bridge.remoteConfig
    .get(options)
    .then((data) => {
        // e.g. { showFullscreenAdOnStart: 'no', difficulty: 'hard' }
    })
    .catch((error) => {});
必须为每个键提供硬编码默认值。请求可能失败,也可能只返回部分数据。

Event names

事件名称

javascript
bridge.EVENT_NAME.AUDIO_STATE_CHANGED;
bridge.EVENT_NAME.PAUSE_STATE_CHANGED;
bridge.EVENT_NAME.INTERSTITIAL_STATE_CHANGED;
bridge.EVENT_NAME.REWARDED_STATE_CHANGED;
bridge.EVENT_NAME.BANNER_STATE_CHANGED;
bridge.EVENT_NAME.ADVANCED_BANNERS_STATE_CHANGED;
bridge.platform.on(...)
and
bridge.advertisement.on(...)
accept event-name strings as well.
javascript
bridge.EVENT_NAME.AUDIO_STATE_CHANGED;
bridge.EVENT_NAME.PAUSE_STATE_CHANGED;
bridge.EVENT_NAME.INTERSTITIAL_STATE_CHANGED;
bridge.EVENT_NAME.REWARDED_STATE_CHANGED;
bridge.EVENT_NAME.BANNER_STATE_CHANGED;
bridge.EVENT_NAME.ADVANCED_BANNERS_STATE_CHANGED;
bridge.platform.on(...)
和
bridge.advertisement.on(...)
也接受事件名称字符串。

State value reference

状态值参考

ModuleStates
Interstitial
loading
,
opened
,
closed
,
failed
Rewarded
loading
,
opened
,
closed
,
rewarded
,
failed
Banner
loading
,
shown
,
hidden
,
failed
Advanced Banners
loading
,
shown
,
hidden
,
failed
Leaderboards type
not_available
,
in_game
,
native
,
native_popup
Storage type
local_storage
,
platform_internal
模块状态
插屏广告
loading
、
opened
、
closed
、
failed
激励广告
loading
、
opened
、
closed
、
rewarded
、
failed
Banner
loading
、
shown
、
hidden
、
failed
Advanced Banners
loading
、
shown
、
hidden
、
failed
排行榜类型
not_available
、
in_game
、
native
、
native_popup
存储类型
local_storage
、
platform_internal

Best-practice checklist

最佳实践检查清单

  1. Wait for
    bridge.initialize()
    before using any API.
  2. Apply
    bridge.platform.language
    to localization.
  3. Load saved state from
    bridge.storage.get(...)
    before showing gameplay.
  4. Send
    bridge.platform.sendMessage('game_ready')
    when first playable frame is rendered.
  5. Subscribe to
    AUDIO_STATE_CHANGED
    and
    PAUSE_STATE_CHANGED
    and react immediately.
  6. Show interstitials at natural breakpoints — never during gameplay.
  7. Never call
    showInterstitial()
    at game start.
  8. Mute + pause on
    opened
    ; restore on
    closed
    /
    failed
    /
    rewarded
    .
  9. Grant rewarded rewards only on the
    rewarded
    state.
  10. Save storage on meaningful events, not every frame.
  11. After granting items for a consumable purchase, call
    consumePurchase(id)
    .
  12. On launch and reconnect, call
    getPurchases()
    to recover interrupted purchases.
  13. Check every
    is*Supported
    flag and hide UI for unsupported features.
  14. Trigger social actions and
    payments.purchase()
    only from direct user input.
  15. Provide hardcoded defaults for every Remote Config key.
  16. Send platform messages (
    level_started
    ,
    gameplay_stopped
    , etc.) — they drive analytics and Advanced Banners.
  1. 使用任何 API 前,等待
    bridge.initialize()
    完成。
  2. 将
    bridge.platform.language
    应用于本地化。
  3. 显示游戏内容前,通过
    bridge.storage.get(...)
    加载已保存的状态。
  4. 首个可玩帧渲染完成后,发送
    bridge.platform.sendMessage('game_ready')
    。
  5. 订阅
    AUDIO_STATE_CHANGED
    和
    PAUSE_STATE_CHANGED
    ,并立即作出响应。
  6. 在自然断点展示插屏广告——游戏进行中绝不能展示。
  7. 在游戏开始时绝不调用
    showInterstitial()
    。
  8. 状态变为
    opened
    时静音并暂停;变为
    closed
    、
    failed
    或
    rewarded
    时恢复。
  9. 仅在
    rewarded
    状态下发放激励广告奖励。
  10. 在有意义的事件发生时保存存储数据,而不是每帧都保存。
  11. 发放可消耗型商品后,调用
    consumePurchase(id)
    。
  12. 启动和重新连接时,调用
    getPurchases()
    以恢复因断线而中断的购买。
  13. 检查每个
    is*Supported
    标志,并隐藏不受支持功能的 UI。
  14. 仅通过用户的直接输入触发社交操作和
    payments.purchase()
    。
  15. 为每个 Remote Config 键提供硬编码默认值。
  16. 发送平台消息(
    level_started
    、
    gameplay_stopped
    等)——它们会驱动分析统计和 Advanced Banners。

Local development

本地开发

In environments Bridge doesn't recognize it falls back to
mock
. APIs return safe defaults instead of throwing, so you can develop and debug locally before publishing.
bridge.platform.id === 'mock'
indicates this state.
在 Bridge 无法识别的环境中,会回退到
mock
。API 会返回安全默认值而不是抛出异常,因此你可以在发布前进行本地开发和调试。
bridge.platform.id === 'mock'
表示当前处于此状态。

Resources

资源

  • Config editor:
    https://playgama.github.io/bridge-config-editor/
  • Wiki:
    https://wiki.playgama.com/
  • 配置编辑器:
    https://playgama.github.io/bridge-config-editor/
  • Wiki:
    https://wiki.playgama.com/