Skip to main content

Game Role API

The Game Role API tells the SDK which server, character, and level the player is currently on — used to enrich analytics and IAP tracking with player context.

Swift vs Objective-C entry point

OEGAuth.shared (Swift) is not visible to Objective-C — it's a plain Swift class, not an NSObject subclass. Objective-C games must call through OegSdkCore, which exposes @objc-bridged wrappers for every method below. Every example on this page shows both.

The One Rule​

There is exactly one call to make: setGameRole(), any time the player's server, character, or level changes. It's cheap and safe to call often — there's no separate API for "on level up" or "on character switch," it's always the same call, wired to whatever hook in your game already notices player state changing.

Call it from every one of these trigger points:

  • Right after login, once you know the player's starting server/character
  • After creating a new character
  • Whenever the player switches character or server — this fires af_sdk_switch_role automatically, no extra step needed
  • Whenever the player levels up — easy to forget since it's not a "switch," but skipping it means level silently drifts stale in analytics with no error to flag it
// Call this from wherever your game already tracks these values changing —
// login, character creation, server switch, level up all funnel through here.
func reportGameRole(_ player: Player) {
OegSdkCore.setGameRole(
serverId: player.serverId,
serverName: player.serverName,
roleId: player.characterId,
roleName: player.characterName,
level: player.level
)
}
- (void)reportGameRole:(Player *)player {
[OegSdkCore setGameRoleWithServerId:player.serverId
serverName:player.serverName
roleId:player.characterId
roleName:player.characterName
level:(int)player.level];
}

When the player instead leaves to a character/server-select screen with no role picked yet — a real gap, not a direct switch — call logoutGameRole() first so no stale role backs analytics/purchases in the meantime (see below).

Note for Objective-C games specifically: OEGAuth.shared.login(username:password:) (a headless credential call) is Swift-only and not bridged. Objective-C games use the SDK's own login UI via OEGManager's showLoginWithCallback: instead (see Authentication) — call reportGameRole from inside that success callback rather than after a direct login() call.

API Reference​

setGameRole()​

import OegSdkV2

OegSdkCore.setGameRole(
serverId: String,
serverName: String? = nil,
roleId: String,
roleName: String? = nil,
level: Int = 0
)

Parameters:

ParameterTypeRequiredDescription
serverIdString✅ YesGame server identifier (e.g., "server_01", "asia_1")
serverNameString?❌ NoHuman-readable server name (e.g., "Asia Server 1")
roleIdString✅ YesCharacter/role unique identifier
roleNameString?❌ NoCharacter/role display name (e.g., "DragonSlayer")
levelInt❌ NoCharacter level (default: 0)

Returns: Nothing (void)

Storage: In-memory only (cleared on logout)

Objective-C​

#import <OegSdkV2/OegSdkV2-Swift.h>

[OegSdkCore setGameRoleWithServerId:@"server_01"
serverName:@"Server 1"
roleId:@"character_123"
roleName:@"DragonSlayer"
level:50];

Note: Objective-C does not support default parameters. You must pass all arguments. Use nil for optional strings and 0 for level if not available.

// Minimal call (required fields only)
[OegSdkCore setGameRoleWithServerId:@"server_01"
serverName:nil
roleId:@"character_123"
roleName:nil
level:0];

Analytics: If a role was already active and serverId/roleId actually change, fires af_sdk_switch_role (old + new server/role). The very first call after login is treated as an initial pick, not a switch, and does not fire it.

logoutGameRole()​

Clears the active character/server context without logging the account out — call when the player returns to a server/character-select screen, before the next setGameRole() call for the newly chosen one. Optional: calling setGameRole() again directly for the new role is enough for a plain switch: use logoutGameRole() when there's a real gap (e.g. player is back at the character-select screen with no role picked yet).

The SDK only clears its own state and fires the analytics event — it does not navigate anywhere. The callback fires once that's done; use it to move the game to its own switch-server screen.

OegSdkCore.logoutGameRole {
// Game role cleared — navigate to your own switch-server screen here
}
[OegSdkCore logoutGameRoleWithCallback:^{
// Game role cleared — navigate to your own switch-server screen here
}];

Returns: Nothing (void) — reports completion via the callback

Analytics: Fires af_sdk_logout_game_role (with the role that was just cleared) — but only when a role was actually active. Calling it when no role is set is a safe no-op and does not fire the event.

How It's Used​

The SDK uses game role data in the following ways:

1. Analytics Events​

Role information is automatically included in analytics events:

  • af_sdk_recharge (IAP events): Includes role_id, role_name, server_id
  • af_logout: Includes server_id
  • af_sdk_switch_role: Fired by setGameRole() when it replaces an already-active role with a different server/role. Includes old_server_id, old_role_id, server_id (new), role_id (new)
  • af_sdk_logout_game_role: Fired by logoutGameRole() when it clears an active role. Includes server_id, role_id (the role that was cleared)
  • Custom events: Available for game-specific tracking

These af_-prefixed names are what AppsFlyer receives. Adjust receives a different, per-game opaque event token configured in the CMS for the same logical event — not these literal strings.

2. IAP Tracking​

When a player makes an in-app purchase, the SDK automatically includes role context:

// Game calls IAP
OEGPayment.shared.purchaseAndVerify(productId: productId, gameData: gameData) { result in
// SDK automatically tracks af_sdk_recharge event with:
// - role_id from setGameRole()
// - role_name from setGameRole()
// - server_id from setGameRole()
// - Falls back to gameData if setGameRole() not called
}

Objective-C games call the equivalent OEGManager IAP entry point, which already takes serverID/roleID as explicit parameters (see In-App Purchases for the full flow):

[[OEGManager sharedManager] inAppPurchaseWithServerID:serverId
roleID:roleId
levels:level
accountID:accountId
productID:productId
extInfo:nil
callback:^(OEGActionType type, id response, BOOL success, NSError *error) {
// SDK automatically tracks af_sdk_recharge event with role data from the params above
}];

3. Fallback Behavior​

If setGameRole() is not called, the SDK uses fallback data:

  • IAP events: Uses GameData parameters passed to purchaseAndVerify()
  • Other events: Uses empty strings for role fields

Best practice: Always call setGameRole() for accurate tracking.

Data Lifecycle​

Storage​

  • Location: In-memory only (not persisted to disk)
  • Scope: Current session only
  • Access: Internal to SDK (not exposed to game)

Clearing​

Call logoutGameRole() explicitly when the player returns to a server/character-select screen (fires af_sdk_logout_game_role). Game role data is also automatically cleared — silently, no event — in these scenarios:

  1. User logs out:

    OEGAuth.shared.logout() // Clears game role automatically
    [[OEGManager sharedManager] logout]; // Clears game role automatically
  2. Session expires:

    • SDK receives 401 from backend
    • Game role cleared during session cleanup
  3. Force logout (maintenance):

    • SDK force logs out user
    • Game role cleared

Persistence​

Game role data is NOT persisted across app restarts. You must call setGameRole() again after:

  • App restart
  • User logs in again
  • Session restoration

Reading Game Role (Internal)​

The game role data is stored internally and used by the SDK. Games typically don't need to read it back, but if needed:

if let gameRole = OEGAuth.shared.gameRole {
let serverId = gameRole.serverId
let serverName = gameRole.serverName
let roleId = gameRole.roleId
let roleName = gameRole.roleName
let level = gameRole.level
}

OEGGameRole is a Swift struct and isn't bridgeable to Objective-C directly, so OegSdkCore exposes it as an NSDictionary instead:

NSDictionary *gameRole = [OegSdkCore getGameRole]; // nil if none is set

if (gameRole) {
NSString *serverId = gameRole[@"serverId"];
NSString *serverName = gameRole[@"serverName"]; // absent key if not provided
NSString *roleId = gameRole[@"roleId"];
NSString *roleName = gameRole[@"roleName"]; // absent key if not provided
NSNumber *level = gameRole[@"level"]; // absent key if not set
}

Note: This is read-only. Use setGameRole() to update.

Best Practices​

✅ Do​

  • Wire setGameRole() into whichever single place your game already tracks server/character/level — don't treat login, character switch, and level-up as separate integrations
  • Include level every time, not just at login — it's the field most likely to go stale if treated as optional
  • Use meaningful IDs (e.g., "server_01", not "1")
  • Include optional fields when available (improves analytics)

❌ Don't​

  • Don't call before login completes
  • Don't use sensitive data in role names
  • Don't skip re-calling it on level-up because it "isn't a switch" — same call, just a changed value
  • Don't rely on persistence across sessions

Troubleshooting​

Role data not appearing in analytics​

Problem: IAP events show empty role fields

Solutions:

  1. Verify setGameRole() is called after login
  2. Check that it's called before IAP purchase
  3. Ensure parameters are non-empty strings
  4. Check logs for any SDK errors

Role data cleared unexpectedly​

Problem: Role data disappears during session

Cause: User logged out or session expired

Solution: Re-call setGameRole() after re-login

Multiple characters per account​

Problem: Game supports multiple characters, which one to track?

Solution: Call setGameRole() for the currently active character. Update when player switches characters.

Backend behavior: every server tracks each character separately — a second roleId on the same serverId does not replace the first, both persist. Whichever one setGameRole() was called for most recently is what Console's player roster marks as that server's current character. If your game only calls setGameRole() when the player enters a server (not on every character switch within it), Console's "current" marker goes stale — it still shows whichever character was picked at login, not the one actually being played. Analytics are unaffected either way: af_sdk_switch_role / sdk_switch_role only fires from an explicit setGameRole() call.