Fire on level-completion success — after the win-state animation begins, before any post-level dialog. Encode the level into the event name (level_complete_1, level_complete_2). Don't pass score, attempts, or duration.
▸Install the React Native SDK
npm install @respectlytics/react-native
# or
yarn add @respectlytics/react-native
JavaScript-only — no native modules, no auto-linking, no New Architecture migration concerns. Bundle size: ~14KB minified+gzipped. Works in any Expo project (managed or bare) without expo prebuild.
▸Initialize Respectlytics in React Native
// App.tsx (or App.js)
import { useEffect } from 'react';
import Respectlytics from '@respectlytics/react-native';
export default function App() {
useEffect(() => {
Respectlytics.configure({ appKey: '<YOUR_APP_KEY>' });
}, []);
return <YourApp />;
}
Initialize once in your top-level component. No native config; no Info.plist or AndroidManifest changes. The SDK is Hermes- and JSC-compatible.
▸Track the event in React Native
import Respectlytics from '@respectlytics/react-native';
export function reportLevelComplete(levelNumber) {
if (levelNumber <= 50) {
Respectlytics.track(`level_complete_${levelNumber}`);
} else {
const bucket = Math.floor((levelNumber - 1) / 50) * 50 + 1;
Respectlytics.track(`level_complete_${bucket}_${bucket + 49}`);
}
}
If your game has chapter-based progression instead of linear levels, encode chapter+level into the name: level_complete_chapter_3_level_2.
✦Privacy & implementation notes
Per-player progression — score curves, leaderboard positions, skill ratings, items inventory — lives in your game backend. That's where it has authority and where the gameplay logic reads from. Mirroring it into product analytics duplicates a system of record without adding signal you can't get from the game backend's own reporting.
Most game-product decisions are about rate ("is this level a difficulty wall for new players?") rather than skill ("how quickly does this player progress?"). The rate question is session-grouped. The skill question is per-player and lives in your game backend.
The React Native SDK is JavaScript-only — no Objective-C/Swift bridging on iOS, no Java/Kotlin bridging on Android. Side effects: no react-native link, no auto-linking, no New Architecture migration concerns, no platform-channel exception surfaces. Trade-off: no access to platform-only metadata (which we don't want to collect anyway).
Works in Expo managed workflow without expo prebuild. No config plugin is required. EAS Build users: nothing to configure. This is the smoothest integration path on RN — most analytics SDKs require ejecting from managed.
⇋How this compares to other analytics SDKs
| Level complete event | Firebase Analytics | Mixpanel | GameAnalytics | Respectlytics |
|---|---|---|---|---|
| Level number as parameter | Yes | Yes | Yes | Use distinct event_name |
| Score stored | Recommended | Recommended | Yes | Out of scope (game backend) |
| Attempts to complete | Recommended | Recommended | Yes | Out of scope (game backend) |
| Time-to-complete | Recommended | Recommended | Yes | Server-side derivation |
| Per-player progression curve | Yes | Yes | Yes | Out of scope (game backend) |
❓Frequently asked questions
Won't we run out of distinct event names if we have 1000 levels?
For high-level-count games, bucket: level_complete_1_50, level_complete_51_100, etc. The Respectlytics aggregation handles either shape. Per-level granular progression is a game-backend signal — your leaderboards and skill-rating system already have it.
How do we measure difficulty without per-player attempts?
Per-session. The rate of sessions where level_complete_N follows level_complete_N-1 is your level-N completion rate. Country-bucketed and device-platform-bucketed shows where the difficulty cliff sits.
What about retries?
Distinct event name: level_failed_N. The rate of level_failed_N to level_complete_N over a session is your level-N retry signal.
Should we instrument every level individually?
If you have under 50 levels, yes — distinct event names per level. Past that, bucket. The principle is to keep your event-name taxonomy navigable; 1000 distinct level event names is functionally a parameter.