Skip to content

Playtime & Session Tracking

The SessionTracker automatically manages player sessions, measures active duration by subtracting idle/AFK time, and categorizes sessions into engagement buckets.


Emitted immediately when a player joins the server:

{
"name": "SessionStart",
"category": "session",
"timestamp": 1727790000,
"userId": 12345678,
"sessionId": "b8f67389-1065-4f76-871d-15ec43194511",
"data": {
"accountAgeDays": 420,
"locale": "en_us"
}
}

Emitted when a player leaves the game (Players.PlayerRemoving):

{
"name": "SessionEnd",
"category": "session",
"timestamp": 1727791800,
"userId": 12345678,
"sessionId": "b8f67389-1065-4f76-871d-15ec43194511",
"data": {
"totalDurationSeconds": 1800,
"activeDurationSeconds": 1620,
"idleDurationSeconds": 180,
"durationBucket": "15-30m"
}
}

Emitted when a player transitions between active and idle states:

{
"name": "PlayerAfkStateChanged",
"category": "session",
"timestamp": 1727790600,
"userId": 12345678,
"sessionId": "b8f67389-1065-4f76-871d-15ec43194511",
"data": {
"isAfk": true,
"idleDuration": 120
}
}

sequenceDiagram
    autonumber
    actor Player
    participant ClientSDK as Client SDK
    participant Server as SessionTracker

    Player->>Server: Joins Server
    Server->>Server: Generate SessionId & emit SessionStart
    loop Normal Gameplay
        Player->>ClientSDK: Keyboard / Touch / Gamepad input
        ClientSDK-->>Server: PlayerActivityPing (throttled 30s)
        Server->>Server: Update lastActivityTime
    end
    Note over Player,Server: Player goes idle for afkThresholdSeconds (120s)
    Server->>Server: Mark session.isAfk = true
    Server->>Server: Emit PlayerAfkStateChanged (isAfk: true)
    Player->>ClientSDK: Moves mouse / presses key
    ClientSDK-->>Server: PlayerActivityPing
    Server->>Server: Deduct idle span from activeDuration
    Server->>Server: Mark session.isAfk = false
    Player->>Server: Disconnects / Leaves
    Server->>Server: Emit SessionEnd (total & active duration)
  1. Activity Pings: When user input occurs, the Client SDK sends a lightweight PlayerActivityPing to the server (throttled to at most once per 30 seconds).
  2. Idle Threshold: If a player produces no input for afkThresholdSeconds (default: 120 seconds), their session is marked AFK.
  3. Resumption: When the player produces input again, the elapsed idle time is deducted from their activeDurationSeconds.

Each finished session is categorized into one of six standard playtime buckets:

Bucket Range Description
<1m 0 – 59 seconds Immediate bounce
1-5m 1 – 4.9 minutes Quick check-in
5-15m 5 – 14.9 minutes Short session
15-30m 15 – 29.9 minutes Core gameplay loop
30-60m 30 – 59.9 minutes Deep engagement
60m+ 60+ minutes Extended play session

To get the rolling average session length for the current server:

local avgSeconds = Analytics:GetAveragePlaytimeSeconds()
print(string.format("Average session length: %.1f minutes", avgSeconds / 60))