yandex-js-sdk
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseYandex Games JavaScript SDK
Yandex Games JavaScript SDK
Overview
概述
Yandex Games loads games inside a frame on . The host injects the global once the SDK script is loaded. Key capability areas:
yandex.<tld>/gamesYaGames- Lifecycle & environment: init, ,
LoadingAPI.ready(), pause/resume events, device info, language/TLDGameplayAPI.start/stop - Player & storage: authorization, profile data, per-player key/value cloud storage
- Monetization: fullscreen interstitial, rewarded video, sticky banner ads, in-app purchases
- Engagement: leaderboards, remote config flags, review prompt, add-to-home-screen shortcut, server time, clipboard write, cross-promotion via
GamesAPI
The SDK does NOT expose social share, invite-friends, community-join, add-to-favorites, achievements, or stat counters.
Yandex Games 会在 的 iframe 中加载游戏。SDK 脚本加载完成后,宿主页面会注入 全局变量。主要能力领域包括:
yandex.<tld>/gamesYaGames- 生命周期与运行环境:init、、
LoadingAPI.ready()、暂停/恢复事件、设备信息、语言/TLDGameplayAPI.start/stop - 玩家与存储:授权、个人资料、按玩家存储的键值云存储
- 商业变现:全屏插页广告、激励视频、常驻横幅广告、应用内购买
- 用户互动:排行榜、远程配置标志、评价提示、添加到主屏幕快捷方式、服务器时间、剪贴板写入、通过 进行交叉推广
GamesAPI
SDK 不提供社交分享、邀请好友、加入社区、收藏、成就或统计计数器功能。
Installation
安装
html
<script src="https://yandex.ru/games/sdk/v2"></script>If loaded dynamically, poll until is defined before calling .
window.YaGames && window.YaGames.initinit()html
<script src="https://yandex.ru/games/sdk/v2"></script>如果通过动态方式加载,应轮询检查 ,确认已定义后再调用 。
window.YaGames && window.YaGames.initinit()Quick Start / Integration Workflow
快速开始 / 集成工作流
Follow this sequence when wiring up the SDK for the first time. Verify each step before proceeding to the next.
javascript
async function bootstrap() {
// 1. Ensure SDK script has loaded
if (!window.YaGames?.init) {
throw new Error('YaGames SDK not available — check that the script tag loaded');
}
// 2. Initialize — all subsequent SDK calls require ysdk
const ysdk = await window.YaGames.init();
// 3. Bind host-driven pause / resume before anything else
ysdk.on('game_api_pause', () => {
/* mute audio, pause gameplay */
});
ysdk.on('game_api_resume', () => {
/* unmute, resume */
});
// 4. Signal that the loading screen is gone
ysdk.features.LoadingAPI?.ready();
// 5. Read environment (language, device type)
const env = readEnvironment(ysdk);
// 6. Fetch player — fall back to guest mode if not authorized
let player = null;
let storageCache = {};
try {
const info = await getPlayer(ysdk);
player = info.raw;
if (info.isAuthorized) {
storageCache = await loadStorage(player);
}
} catch (err) {
console.warn('Player init failed, continuing as guest:', err);
}
// 7. Start gameplay tracking
onGameplayStarted(ysdk);
return { ysdk, player, storageCache, env };
}javascript
function readEnvironment(ysdk) {
return {
language: ysdk.environment.i18n.lang.toLowerCase(),
tld: ysdk.environment.i18n.tld.toLowerCase(),
deviceType: ysdk.deviceInfo.type // 'desktop' | 'mobile' | 'tablet' | 'tv'
};
}首次接入 SDK 时,请按照以下顺序操作。完成每一步的验证后,再继续下一步。
javascript
async function bootstrap() {
// 1. Ensure SDK script has loaded
if (!window.YaGames?.init) {
throw new Error('YaGames SDK not available — check that the script tag loaded');
}
// 2. Initialize — all subsequent SDK calls require ysdk
const ysdk = await window.YaGames.init();
// 3. Bind host-driven pause / resume before anything else
ysdk.on('game_api_pause', () => {
/* mute audio, pause gameplay */
});
ysdk.on('game_api_resume', () => {
/* unmute, resume */
});
// 4. Signal that the loading screen is gone
ysdk.features.LoadingAPI?.ready();
// 5. Read environment (language, device type)
const env = readEnvironment(ysdk);
// 6. Fetch player — fall back to guest mode if not authorized
let player = null;
let storageCache = {};
try {
const info = await getPlayer(ysdk);
player = info.raw;
if (info.isAuthorized) {
storageCache = await loadStorage(player);
}
} catch (err) {
console.warn('Player init failed, continuing as guest:', err);
}
// 7. Start gameplay tracking
onGameplayStarted(ysdk);
return { ysdk, player, storageCache, env };
}javascript
function readEnvironment(ysdk) {
return {
language: ysdk.environment.i18n.lang.toLowerCase(),
tld: ysdk.environment.i18n.tld.toLowerCase(),
deviceType: ysdk.deviceInfo.type // 'desktop' | 'mobile' | 'tablet' | 'tv'
};
}Player / Authorization
玩家 / 授权
javascript
async function getPlayer(ysdk, { useSignedData = false } = {}) {
const player = await ysdk.getPlayer({ signed: useSignedData });
return {
raw: player,
id: player.getUniqueID(),
name: player.getName() || null,
photos: ['small', 'medium', 'large'].map((size) => player.getPhoto(size)).filter(Boolean),
isAuthorized: player.isAuthorized(),
payingStatus: player.getPayingStatus(),
signature: useSignedData ? player.signature : null
};
}
async function authorizePlayer(ysdk, options) {
const current = await getPlayer(ysdk, options);
if (current.isAuthorized) {
return current;
}
await ysdk.auth.openAuthDialog();
return getPlayer(ysdk, options);
}javascript
async function getPlayer(ysdk, { useSignedData = false } = {}) {
const player = await ysdk.getPlayer({ signed: useSignedData });
return {
raw: player,
id: player.getUniqueID(),
name: player.getName() || null,
photos: ['small', 'medium', 'large'].map((size) => player.getPhoto(size)).filter(Boolean),
isAuthorized: player.isAuthorized(),
payingStatus: player.getPayingStatus(),
signature: useSignedData ? player.signature : null
};
}
async function authorizePlayer(ysdk, options) {
const current = await getPlayer(ysdk, options);
if (current.isAuthorized) {
return current;
}
await ysdk.auth.openAuthDialog();
return getPlayer(ysdk, options);
}Storage
存储
Every call writes the full document — there is no per-key API. Cache the latest snapshot client-side and merge before each save. Fall back to for guests.
localStoragejavascript
async function loadStorage(player) {
return player.getData();
}
async function setStorage(player, cache, key, value) {
const data = { ...(cache || {}) };
if (Array.isArray(key)) {
for (let i = 0; i < key.length; i++) {
data[key[i]] = value[i];
}
} else {
data[key] = value;
}
await player.setData(data);
return data;
}
async function deleteStorage(player, cache, key) {
const data = { ...(cache || {}) };
if (Array.isArray(key)) {
for (let i = 0; i < key.length; i++) {
delete data[key[i]];
}
} else {
delete data[key];
}
await player.setData(data);
return data;
}
function getCached(cache, key) {
if (Array.isArray(key)) {
return key.map((k) => (typeof cache?.[k] === 'undefined' ? null : cache[k]));
}
return typeof cache?.[key] === 'undefined' ? null : cache[key];
}每次调用都会写入完整文档,没有按单个 key 操作的 API。应在客户端缓存最新快照,并在每次保存前进行合并。访客用户应回退到 。
localStoragejavascript
async function loadStorage(player) {
return player.getData();
}
async function setStorage(player, cache, key, value) {
const data = { ...(cache || {}) };
if (Array.isArray(key)) {
for (let i = 0; i < key.length; i++) {
data[key[i]] = value[i];
}
} else {
data[key] = value;
}
await player.setData(data);
return data;
}
async function deleteStorage(player, cache, key) {
const data = { ...(cache || {}) };
if (Array.isArray(key)) {
for (let i = 0; i < key.length; i++) {
delete data[key[i]];
}
} else {
delete data[key];
}
await player.setData(data);
return data;
}
function getCached(cache, key) {
if (Array.isArray(key)) {
return key.map((k) => (typeof cache?.[k] === 'undefined' ? null : cache[k]));
}
return typeof cache?.[key] === 'undefined' ? null : cache[key];
}Advertisement
广告
Fullscreen interstitial
全屏插页广告
onClose(wasShown)wasShown === falsejavascript
function showInterstitial(ysdk, handlers = {}) {
ysdk.adv.showFullscreenAdv({
callbacks: {
onOpen: () => handlers.onOpen?.(),
onClose: (wasShown) => handlers.onClose?.(wasShown),
onError: (err) => handlers.onError?.(err)
}
});
}onClose(wasShown)wasShown === falsejavascript
function showInterstitial(ysdk, handlers = {}) {
ysdk.adv.showFullscreenAdv({
callbacks: {
onOpen: () => handlers.onOpen?.(),
onClose: (wasShown) => handlers.onClose?.(wasShown),
onError: (err) => handlers.onError?.(err)
}
});
}Rewarded video
激励视频
Grant the reward inside . fires after the ad UI is dismissed.
onRewardedonClosejavascript
function showRewarded(ysdk, handlers = {}) {
ysdk.adv.showRewardedVideo({
callbacks: {
onOpen: () => handlers.onOpen?.(),
onRewarded: () => handlers.onRewarded?.(),
onClose: () => handlers.onClose?.(),
onError: (err) => handlers.onError?.(err)
}
});
}应在 中发放奖励。 会在广告界面关闭后触发。
onRewardedonClosejavascript
function showRewarded(ysdk, handlers = {}) {
ysdk.adv.showRewardedVideo({
callbacks: {
onOpen: () => handlers.onOpen?.(),
onRewarded: () => handlers.onRewarded?.(),
onClose: () => handlers.onClose?.(),
onError: (err) => handlers.onError?.(err)
}
});
}Sticky banner
常驻横幅广告
javascript
async function getBannerStatus(ysdk) {
return ysdk.adv.getBannerAdvStatus(); // { stickyAdvIsShowing: boolean, reason?: string }
}
async function showBanner(ysdk) {
const data = await ysdk.adv.showBannerAdv();
return data.stickyAdvIsShowing === true;
}
async function hideBanner(ysdk) {
const data = await ysdk.adv.hideBannerAdv();
return data.stickyAdvIsShowing === false;
}javascript
async function getBannerStatus(ysdk) {
return ysdk.adv.getBannerAdvStatus(); // { stickyAdvIsShowing: boolean, reason?: string }
}
async function showBanner(ysdk) {
const data = await ysdk.adv.showBannerAdv();
return data.stickyAdvIsShowing === true;
}
async function hideBanner(ysdk) {
const data = await ysdk.adv.hideBannerAdv();
return data.stickyAdvIsShowing === false;
}Payments / IAP
支付 / IAP
Obtain the payments object once after init. Pass for backend signature validation.
signed: truejavascript
async function initPayments(ysdk, { signed = true } = {}) {
return ysdk.getPayments({ signed });
}初始化后获取一次 payments 对象。传入 以进行后端签名验证。
signed: truejavascript
async function initPayments(ysdk, { signed = true } = {}) {
return ysdk.getPayments({ signed });
}Catalog
商品目录
javascript
async function getCatalog(payments) {
const products = await payments.getCatalog();
return products.map((p) => ({
id: p.id,
title: p.title,
description: p.description,
imageURI: p.imageURI,
price: p.price,
priceValue: p.priceValue,
priceCurrencyCode: p.priceCurrencyCode,
priceCurrencyImage: p.getPriceCurrencyImage?.('medium')
}));
}javascript
async function getCatalog(payments) {
const products = await payments.getCatalog();
return products.map((p) => ({
id: p.id,
title: p.title,
description: p.description,
imageURI: p.imageURI,
price: p.price,
priceValue: p.priceValue,
priceCurrencyCode: p.priceCurrencyCode,
priceCurrencyImage: p.getPriceCurrencyImage?.('medium')
}));
}Purchase
购买
javascript
async function purchase(payments, productId, payload) {
const result = await payments.purchase({ id: productId, developerPayload: payload });
if (!result?.purchaseData?.purchaseToken) {
throw new Error(
`Purchase succeeded but returned no purchaseToken for product ${productId}`
);
}
return { id: productId, ...result.purchaseData };
}javascript
async function purchase(payments, productId, payload) {
const result = await payments.purchase({ id: productId, developerPayload: payload });
if (!result?.purchaseData?.purchaseToken) {
throw new Error(
`Purchase succeeded but returned no purchaseToken for product ${productId}`
);
}
return { id: productId, ...result.purchaseData };
}Owned purchases
已购买的商品
javascript
async function getPurchases(payments) {
const list = await payments.getPurchases();
return list.map((purchase) => ({ id: purchase.productID, ...purchase.purchaseData }));
}javascript
async function getPurchases(payments) {
const list = await payments.getPurchases();
return list.map((purchase) => ({ id: purchase.productID, ...purchase.purchaseData }));
}Consume
消耗
Verify the item was granted before consuming. A failed consume leaves the token intact for retry.
javascript
async function consumePurchase(payments, purchaseToken) {
if (!purchaseToken) {
throw new Error('consumePurchase: purchaseToken is required');
}
await payments.consumePurchase(purchaseToken);
}消耗前请确认物品已发放。消耗失败时,token 会保持有效,以便重试。
javascript
async function consumePurchase(payments, purchaseToken) {
if (!purchaseToken) {
throw new Error('consumePurchase: purchaseToken is required');
}
await payments.consumePurchase(purchaseToken);
}Leaderboards
排行榜
Boards are configured in the developer console and referenced by string id. Setting a score requires an authorized player.
javascript
async function setLeaderboardScore(ysdk, leaderboardId, score) {
const lb = await ysdk.getLeaderboards();
await lb.setLeaderboardScore(leaderboardId, score);
}
async function getLeaderboardEntries(ysdk, leaderboardId, { isPlayerAuthorized = false } = {}) {
const lb = await ysdk.getLeaderboards();
const options = { quantityTop: 20 };
if (isPlayerAuthorized) {
options.includeUser = true;
options.quantityAround = 3;
}
const result = await lb.getLeaderboardEntries(leaderboardId, options);
if (!result || result.entries.length === 0) {
return [];
}
return result.entries.map((e) => ({
id: e.player.uniqueID,
name: e.player.publicName,
score: e.score,
rank: e.rank,
photo: e.player.getAvatarSrc('large')
}));
}排行榜在开发者控制台中配置,并通过字符串 id 引用。设置分数需要玩家已授权。
javascript
async function setLeaderboardScore(ysdk, leaderboardId, score) {
const lb = await ysdk.getLeaderboards();
await lb.setLeaderboardScore(leaderboardId, score);
}
async function getLeaderboardEntries(ysdk, leaderboardId, { isPlayerAuthorized = false } = {}) {
const lb = await ysdk.getLeaderboards();
const options = { quantityTop: 20 };
if (isPlayerAuthorized) {
options.includeUser = true;
options.quantityAround = 3;
}
const result = await lb.getLeaderboardEntries(leaderboardId, options);
if (!result || result.entries.length === 0) {
return [];
}
return result.entries.map((e) => ({
id: e.player.uniqueID,
name: e.player.publicName,
score: e.score,
rank: e.rank,
photo: e.player.getAvatarSrc('large')
}));
}Remote config
远程配置
ysdk.getFlags(options){ key: stringValue }javascript
async function getRemoteConfig(ysdk, options = {}) {
const params = { clientFeatures: [], ...options };
return ysdk.getFlags(params);
}ysdk.getFlags(options){ key: stringValue }javascript
async function getRemoteConfig(ysdk, options = {}) {
const params = { clientFeatures: [], ...options };
return ysdk.getFlags(params);
}Server time
服务器时间
javascript
function getServerTime(ysdk) {
// Returns Unix timestamp in milliseconds
return ysdk.serverTime();
}javascript
function getServerTime(ysdk) {
// Returns Unix timestamp in milliseconds
return ysdk.serverTime();
}Social
社交
Review prompt
评价提示
javascript
async function requestReview(ysdk) {
const can = await ysdk.feedback.canReview();
if (!can.value) {
throw new Error(can.reason || 'review not available');
}
const { feedbackSent } = await ysdk.feedback.requestReview();
return feedbackSent;
}javascript
async function requestReview(ysdk) {
const can = await ysdk.feedback.canReview();
if (!can.value) {
throw new Error(can.reason || 'review not available');
}
const { feedbackSent } = await ysdk.feedback.requestReview();
return feedbackSent;
}Add to home screen (shortcut)
添加到主屏幕(快捷方式)
javascript
async function canAddToHomeScreen(ysdk) {
const prompt = await ysdk.shortcut.canShowPrompt();
return prompt.canShow === true;
}
async function addToHomeScreen(ysdk) {
const result = await ysdk.shortcut.showPrompt();
return result.outcome === 'accepted';
}javascript
async function canAddToHomeScreen(ysdk) {
const prompt = await ysdk.shortcut.canShowPrompt();
return prompt.canShow === true;
}
async function addToHomeScreen(ysdk) {
const result = await ysdk.shortcut.showPrompt();
return result.outcome === 'accepted';
}Clipboard
剪贴板
javascript
async function clipboardWrite(ysdk, text) {
await ysdk.clipboard.writeText(text);
}javascript
async function clipboardWrite(ysdk, text) {
await ysdk.clipboard.writeText(text);
}Gameplay lifecycle, pause and audio
游戏生命周期、暂停与音频
Bracket every active gameplay session with / to drive ad pacing and analytics.
GameplayAPI.start()GameplayAPI.stop()javascript
function onGameplayStarted(ysdk) {
ysdk.features.GameplayAPI?.start();
}
function onGameplayStopped(ysdk) {
ysdk.features.GameplayAPI?.stop();
}javascript
function bindPauseHandlers(ysdk, { onPause, onResume }) {
ysdk.on('game_api_pause', () => onPause?.());
ysdk.on('game_api_resume', () => onResume?.());
}Visibility/focus changes not announced by Yandex should still be handled with , , and alongside these SDK callbacks.
document.visibilitychangewindow.blurwindow.focus使用 / 包裹每次活跃的游戏会话,以控制广告节奏并支持分析。
GameplayAPI.start()GameplayAPI.stop()javascript
function onGameplayStarted(ysdk) {
ysdk.features.GameplayAPI?.start();
}
function onGameplayStopped(ysdk) {
ysdk.features.GameplayAPI?.stop();
}javascript
function bindPauseHandlers(ysdk, { onPause, onResume }) {
ysdk.on('game_api_pause', () => onPause?.());
ysdk.on('game_api_resume', () => onResume?.());
}除了这些 SDK 回调,还应通过 、 和 处理 Yandex 未通知的可见性或焦点变化。
document.visibilitychangewindow.blurwindow.focusCatalog of other Yandex Games (optional)
其他 Yandex Games 的目录(可选)
features.GamesAPIjavascript
async function getAllGames(ysdk) {
const { games } = await ysdk.features.GamesAPI.getAllGames();
return games;
}
async function getGameById(ysdk, gameId) {
const { game, isAvailable } = await ysdk.features.GamesAPI.getGameByID(gameId);
return { ...game, isAvailable };
}features.GamesAPIjavascript
async function getAllGames(ysdk) {
const { games } = await ysdk.features.GamesAPI.getAllGames();
return games;
}
async function getGameById(ysdk, gameId) {
const { game, isAvailable } = await ysdk.features.GamesAPI.getGameByID(gameId);
return { ...game, isAvailable };
}