Respectlytics Respect lytics
Menu
Flutter Level complete Privacy-first

How to track level-complete events in Flutter games without personal data

Level complete is the central progression event in mobile games and the place game analytics SDKs default to building per-player skill graphs (level number, time-to-complete, attempts, score, items used). Respectlytics helps developers avoid collecting personal data in the first place: in Flutter, level complete is one named event per level, with the level encoded into the event name. Below: how to keep your level taxonomy bounded, why time-to-complete becomes a server-side derivation, and what stays in your game backend.

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 Flutter SDK

yaml Respectlytics
# pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  respectlytics_flutter: ^3.0.0

Pure Dart — no platform channels for analytics. Same code on every platform Flutter compiles to (iOS, Android, web, macOS, Windows, Linux). On web, events are sent via the REST API; mobile platforms use the same path.

Initialize Respectlytics in Flutter

dart Respectlytics
import 'package:flutter/material.dart';
import 'package:respectlytics_flutter/respectlytics_flutter.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Respectlytics.configure(appKey: '<YOUR_APP_KEY>');
  runApp(const MyApp());
}

Initialize in main() after WidgetsFlutterBinding.ensureInitialized() and before runApp(). The future completes immediately on configuration; events queued before completion are flushed once the network is available.

Track the event in Flutter

dart Respectlytics
import 'package:respectlytics_flutter/respectlytics_flutter.dart';

void reportLevelComplete(int levelNumber) {
  if (levelNumber <= 50) {
    Respectlytics.track('level_complete_$levelNumber');
  } else {
    final bucket = ((levelNumber - 1) ~/ 50) * 50 + 1;
    Respectlytics.track('level_complete_${bucket}_${bucket + 49}');
  }
}

Pair with level_failed_N events to surface difficulty walls — the failed/complete ratio per level is the highest-leverage games-product signal.

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 Flutter SDK is pure Dart. No MethodChannel, no platform-specific iOS or Android plugin code. The same code runs on every platform Flutter supports — including web and desktop targets. This eliminates one common audit surface ("what's the Android implementation doing?").

Always initialize after WidgetsFlutterBinding.ensureInitialized() and before runApp(). If you skip the binding step, the configure call will throw on platforms that need a binding for asynchronous I/O. The SDK documentation example uses this pattern by default.

How this compares to other analytics SDKs

Level complete eventFirebase AnalyticsMixpanelGameAnalyticsRespectlytics
Level number as parameterYesYesYesUse distinct event_name
Score storedRecommendedRecommendedYesOut of scope (game backend)
Attempts to completeRecommendedRecommendedYesOut of scope (game backend)
Time-to-completeRecommendedRecommendedYesServer-side derivation
Per-player progression curveYesYesYesOut 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.

Related guides

Track what matters. Collect nothing you don't.

Five-field event schema, RAM-only event queue, no IDFA, no AAID, no persistent user IDs. Helps developers avoid collecting personal data in the first place.