A simple guide for integrating the Play Fun SDK into HTML/JavaScript games. Get your game connected to Play Fun in minutes!
After login, ogp.playerId is the player's Play Fun Privy ID (managed by Play Fun's Privy instance — not your own). This is distinct from the internal Play Fun user ID (OGP ID). Use it as the canonical user key in your game/backend.
Quick Start - It's This Easy
// 1. Initializeconstogp=newOpenGameSDK({ui:{usePointsWidget:true}});ogp.init({gameId:'YOUR_GAME_ID'});// 2. Add points during gameplayogp.addPoints(10);// 3. End the game - opens a modal, auto-logs in if needed!awaitogp.endGame();
That's it! The SDK handles authentication automatically when you call endGame().
Key Concepts
Feature
What It Does
Auto-Login
endGame() automatically prompts login if user isn't authenticated
Points Widget
Built-in UI shows player's points - no extra work needed
Privy Auth
Secure authentication handled by SDK
Flush + Commit
addPoints() flushes incrementally, endGame() commits the session
Blocking Modal
endGame() opens a full-screen modal (loading → success/error). Only call at end of round!
1) Install
Add two lines to your HTML <head>:
2) Initialize
Simple Rules:
Create one SDK instance per page
Register event handlers before calling init
Wait for OnReady before enabling gameplay
3) Identity & Login
Auto-Login: The Easy Way
You don't need to handle login manually! When you call endGame(), the SDK automatically prompts the user to log in if they aren't already authenticated.
This means you can:
Let players start playing immediately
Only prompt for login when they want to save progress
Keep your code simple
Manual Login (Optional)
If you prefer to prompt login earlier (e.g., for multiplayer features):
After login, ogp.playerId contains the user's Play Fun Privy ID (managed by Play Fun's Privy instance, not your own). This is distinct from the internal OGP user ID. Use it as their unique identifier in the client SDK context.
4) Scoring & Saving
The Simple Pattern
Important:endGame() takes no parameters. It commits all points accumulated via addPoints(). If no points have been added, it throws an error.
Warning:endGame() opens a gameplay-blocking modal (loading screen → success/boost screen or error screen). Do NOT call it during active gameplay — only call it when the game round/session has ended. savePoints() is an alias for endGame().
Best Practice: Save Only Improvements
To prevent duplicate rewards, only add the difference when players beat their best:
Game Type Examples
Key Rules:
addPoints() to accumulate during gameplay
endGame() once when session ends (takes no args, opens a blocking modal)
Save improvements, not absolute scores
5) Rewards & Claims
6) UI Helpers
7) Events
Register these before calling init:
8) Complete Example
9) Integration Checklist
API Reference
Methods
Method
Description
init({ gameId })
Initialize SDK with your game ID
addPoints(amount)
Accumulate points during gameplay
endGame()
End game round, commit points (opens blocking modal, auto-login)
savePoints()
Alias for endGame()
getPoints()
Get player's current points and multiplier
listUserRewards()
Fetch player's available rewards
claimRewards(addresses)
Claim rewards for specified token addresses
login()
Manually trigger login modal
UI Methods
Method
Description
showPoints()
Show the points widget
hidePoints()
Hide the points widget
setTheme(theme)
Set 'light', 'dark', or 'system'
Events
Event
When Fired
OnReady
SDK initialized and ready
SessionStarted
Player session established
SessionEnded
Player session ended
LoginRequest
Login flow started
LoginSuccess
User successfully logged in
LoginFailed
Login failed
LoginCancelled
User closed login modal
Logout
User logged out
SavePointsSuccess
Points saved to server
SavePointsFailed
Failed to save points
SavePointsCancelled
User cancelled save
ClaimRequest
Claim transaction requested
ClaimSuccess
Claim transaction sent
ClaimFailed
Claim failed
ClaimCancelled
User cancelled claim
Constructor Options
That's everything you need! The SDK handles the complexity — you just call addPoints() during gameplay and endGame() when the session ends.
const ogp = new OpenGameSDK({
ui: {
usePointsWidget: true, // Show built-in points display (default: true)
theme: 'dark', // 'light', 'dark', or 'system' (default: 'system')
useCustomUI: false, // Set true to disable all automatic modals/widgets
},
logLevel: 'warn', // 'debug', 'info', 'warn', 'error'
});
ogp.on('OnReady', () => {
console.log('SDK ready - start your game!');
startGame();
});
ogp.on('LoginSuccess', () => {
console.log('Logged in as:', ogp.playerId);
});
ogp.init({ gameId: 'YOUR_GAME_ID' });
// Just call endGame when the round ends
// SDK handles login automatically if needed!
await ogp.endGame();
ogp.login(); // Opens login modal
// During gameplay - accumulate points (flushed incrementally to server)
ogp.addPoints(10);
// When game ends - commit all accumulated points
// IMPORTANT: This opens a gameplay-blocking modal!
await ogp.endGame();
let bestScore = 0;
let currentScore = 0;
// On game start, get player's best score
async function initBestScore() {
const result = await ogp.getPoints();
bestScore = result?.points ? Number(result.points) : 0;
}
// During gameplay
function updateScore(newScore) {
currentScore = Math.max(currentScore, newScore);
if (currentScore > bestScore) {
ogp.addPoints(currentScore - bestScore);
}
}
// When game ends
async function handleGameEnd() {
if (currentScore > bestScore) {
await ogp.endGame();
bestScore = currentScore;
}
currentScore = 0; // Reset for next run
}
// PLATFORMER - Height/distance based (higher is better)
currentScore = Math.max(currentScore, distance);
// RACING - Time based (lower is better)
if (time < bestScore || bestScore === 0) currentScore = time;
// SHOOTER - Points accumulated
currentScore = Math.max(currentScore, points);
// Get player's rewards
const rewards = await ogp.listUserRewards();
// Claim rewards for specific token addresses
await ogp.claimRewards(['token-mint-address-1', 'token-mint-address-2']);
ogp.showPoints(); // Show the points widget
ogp.hidePoints(); // Hide the points widget
ogp.setTheme('dark'); // 'light', 'dark', or 'system'