Performance and analytics
Measure startup, session outcomes and aggregate browser performance without building a telemetry service. Performance monitoring is opt-in; it does not change your game's simulation, rendering quality or networking.
Start, inspect, report and clean up
import { Inkwell } from '@silicon-jungle/inkwell-sdk'
const stop = Inkwell.performance.start({ reportIntervalMs: 30000 })
const sample = Inkwell.performance.snapshot()
if (sample?.fps != null) console.log('Sample FPS:', sample.fps)
Inkwell.analytics.track('level.started', { level: 1, mode: 'solo' })
// Call on your actual completion condition, not merely on page load:
export function levelFinished() {
Inkwell.analytics.track('level.finished', { level: 1 })
Inkwell.session.complete()
}
// report() emits and resets; snapshot() above did neither.
export function reportNow() { return Inkwell.performance.report() }
window.addEventListener('pagehide', stop, { once: true })performance.start(options?) replaces the existing monitor and returns its cleanup function. The default reporting interval is 30 seconds, with a 10-second minimum; supply a finite positive interval. snapshot() reads without resetting. report() emits the current sample and resets accumulated frame/long-task data. Both return null if no monitor is running. stop() cancels the timer, animation frame and observer, and may emit one final accumulated sample.
In the facade the module is Inkwell.performance; a modular import exposes start, stop, snapshot, report and summariseFrameTimes. Outside a browser, start returns a no-op cleanup. Outside the trusted Inkwell frame, local browser sampling is not evidence that the platform received telemetry. These methods do not return ingestion receipts.
Exact sample fields
Scroll the table horizontally to read each metric.
| Field | Meaning |
|---|---|
fps | 1,000 divided by mean sampled requestAnimationFrame interval, rounded to one decimal; null with no frame samples. |
frameTimeP95Ms | Nearest-rank 95th percentile of retained frame intervals, rounded to one decimal; null with no samples. |
frameTimeMaxMs | Maximum retained frame interval; null with no samples. |
longTaskCount | Number of entries supplied by the browser's supported longtask observer since the last report. |
longTaskDurationMs | Sum of observed long-task duration, rounded to one decimal. |
visibility | visible or hidden at snapshot time. |
memoryUsedMb | Available browser JS heap usage, bytes divided by 1,024² and rounded to one decimal; null where unavailable. |
The SDK retains at most 3,600 frame intervals and clamps individual gaps to 1,000 ms. Frames are collected only while visible; returning from suspension can still affect the next interval. These are browser frame timings, not GPU timings or proof that an engine rendered every frame. Unsupported long-task observation produces zero counters, which does not prove no long tasks occurred. Heap data is not process memory, GPU memory, a leak diagnosis or a portable browser capability.
Where creators see results
The game's creator Analytics dashboard combines play sessions, completion/loading events, custom events and performance. Reports support 7-, 30- and 90-day windows, daily trends and performance breakdowns by recorded device category and build. Analytics are private to the authorized creator, not a public SDK query.
Hidden samples are excluded from performance aggregation. Dashboard average FPS is an average of valid sample values, not frame-weighted FPS across every player. Its average p95 is an average of per-sample percentiles, not the global 95th percentile of all frames. Missing measurements remain missing; compare sample counts and build/device mix when interpreting changes.
Current ingestion caps are 300 performance samples and 100 other custom events per play session, in addition to endpoint rate limits. A ten-second interval reaches 300 samples in about 50 minutes. Delivery is best-effort and bounded; there is no durable offline telemetry queue or unlimited raw profiler stream. Manual report calls do not bypass those caps.
Custom events, loading and completion
analytics.track(name, properties?) accepts names beginning with a letter, followed by letters, digits, underscore, dot, colon or hyphen, up to 64 characters. Properties are a flat record of scalar string/finite-number/boolean/null values; the server accepts at most 50 safe property names and 8,192 serialized characters, truncating individual string values to 1,000 characters. Do not use nested objects or arbitrary event dumps. track returns void, not a saved-event receipt.
loading.progress(ratio) takes 0–1 or null for indeterminate progress. Call ready() when the player can interact, or loading.fail(publicMessage) on terminal startup failure. session.complete() records your chosen completion condition once per page load; it is not an achievement award or a save.
Never include secrets, emails, private messages or sensitive player data. Browser metrics/events are untrusted: do not use them to authorize scores, inventory or billing. Use server-side game rules for authoritative outcomes.
Full performance signatures · Custom event types · Loading lifecycle · Analytics access