Loading...
Loading...
Roblox AnalyticsService: custom events, economy tracking, funnels, rate limits, event taxonomy.
npx skill4agent add tabooharmony/roblox-brain roblox-analyticsAnalyticsServiceAnalyticsServicegame:GetService("AnalyticsService")local AnalyticsService = game:GetService("AnalyticsService")
-- Counter: tracks occurrence count + unique users automatically
AnalyticsService:LogCustomEvent(player, "MissionStarted")
-- With value: enables sum/mean/min/max aggregations
AnalyticsService:LogCustomEvent(player, "MissionCompletedDuration", 120)
-- With custom fields (up to 3): enables filtering/breakdown on dashboard
AnalyticsService:LogCustomEvent(player, "EnemyDefeated", 1, {
customFields = {
[Enum.AnalyticsCustomFieldKeys.CustomField01] = { value = "Zombie" },
[Enum.AnalyticsCustomFieldKeys.CustomField02] = { value = "Sword" },
[Enum.AnalyticsCustomFieldKeys.CustomField03] = { value = "Wave5" },
}
})-- Player EARNED currency (source)
AnalyticsService:LogEconomyEvent(
player,
Enum.AnalyticsEconomyFlowType.Source, -- Source = earned/gained
"Coins", -- Currency name (max 10 types)
50, -- Amount
player.leaderstats.Coins.Value + 50, -- Balance AFTER transaction
Enum.AnalyticsEconomyTransactionType.Gameplay.Name, -- Transaction type
"QuestReward_Daily", -- Item SKU (what triggered it)
{
customFields = {
[Enum.AnalyticsCustomFieldKeys.CustomField01] = { value = "Quest_001" },
}
}
)
-- Player SPENT currency (sink)
AnalyticsService:LogEconomyEvent(
player,
Enum.AnalyticsEconomyFlowType.Sink, -- Sink = spent/consumed
"Coins",
200,
player.leaderstats.Coins.Value - 200,
Enum.AnalyticsEconomyTransactionType.Shop.Name,
"SpeedBoost_30min"
)GameplayContextualPurchaseInAppPurchaseShopTimedRewardTrade-- Onboarding funnel: track where players drop off
AnalyticsService:LogFunnelStepEvent(player, "Onboarding", "1", "WelcomeScreen")
-- ... player progresses ...
AnalyticsService:LogFunnelStepEvent(player, "Onboarding", "2", "PickCharacter")
-- ... player progresses ...
AnalyticsService:LogFunnelStepEvent(player, "Onboarding", "3", "FirstBattle")
-- ... player progresses ...
AnalyticsService:LogFunnelStepEvent(player, "Onboarding", "4", "CompleteTutorial")
-- Shop conversion funnel
AnalyticsService:LogFunnelStepEvent(player, "ShopPurchase", "1", "OpenedShop")
AnalyticsService:LogFunnelStepEvent(player, "ShopPurchase", "2", "ViewedItem")
AnalyticsService:LogFunnelStepEvent(player, "ShopPurchase", "3", "ClickedBuy")
AnalyticsService:LogFunnelStepEvent(player, "ShopPurchase", "4", "ConfirmedPurchase")| Constraint | Limit |
|---|---|
| Total AnalyticsService calls/minute | 120 + (20 × CCU) |
| Custom event names | 100 |
| Economy resource types | 10 |
| Funnels | 10 |
| Steps per funnel | 100 |
| Custom fields per event | 3 |
| Unique values per custom field | 8,000 (then grouped as "Other") |
-- ServerScriptService/Analytics/EventBatcher.luau
local AnalyticsService = game:GetService("AnalyticsService")
local EventBatcher = {}
local batches: { [Player]: { [string]: number } } = {}
-- Accumulate events, flush periodically
function EventBatcher:increment(player: Player, eventName: string, amount: number?)
if not batches[player] then
batches[player] = {}
end
local current = batches[player][eventName] or 0
batches[player][eventName] = current + (amount or 1)
end
function EventBatcher:flush()
for player, events in batches do
if not player:IsDescendantOf(game.Players) then
batches[player] = nil
continue
end
for eventName, value in events do
AnalyticsService:LogCustomEvent(player, eventName, value)
end
end
batches = {}
end
-- Flush every 30 seconds
task.spawn(function()
while true do
task.wait(30)
EventBatcher:flush()
end
end)
-- Flush on player leaving (capture final counts)
game.Players.PlayerRemoving:Connect(function(player)
if batches[player] then
for eventName, value in batches[player] do
AnalyticsService:LogCustomEvent(player, eventName, value)
end
batches[player] = nil
end
end)
return EventBatcher-- ONE event, broken down by weapon type via custom field
AnalyticsService:LogCustomEvent(player, "EnemyKill", 1, {
customFields = {
[Enum.AnalyticsCustomFieldKeys.CustomField01] = { value = weaponType },
[Enum.AnalyticsCustomFieldKeys.CustomField02] = { value = enemyType },
}
})-- BAD: burns through your 100 event limit fast
AnalyticsService:LogCustomEvent(player, "EnemyKill_Sword")
AnalyticsService:LogCustomEvent(player, "EnemyKill_Bow")
AnalyticsService:LogCustomEvent(player, "EnemyKill_Magic")SessionStartSessionDurationDayNReturnFeatureUsedQuestCompletedLevelReached