Requirements
- Flutter 3.19 or later, Dart 3.3 or later
- Android
minSdk 24or higher - A public ingest key from the Codeskop dashboard
Add the plugin
Add it to
pubspec.yaml, then runflutter pub get.pubspec.yamldependencies: codeskop_tracker: ^0.3.0The plugin brings in the native Android SDK for you. Don't add
tracker-androidto your Gradle files separately.Initialize and wrap your app
Call
Codeskop.runGuardedonce, aroundrunApp.lib/main.dartimport 'package:codeskop_tracker/codeskop_tracker.dart';import 'package:flutter/material.dart'; void main() { Codeskop.runGuarded(() async { await Codeskop.init( apiKey: 'cs_live_pk_YOUR_KEY', endpoint: 'https://api.codeskop.com', ); runApp(const MyApp()); });}runGuardedcallsWidgetsFlutterBinding.ensureInitialized()and sets up every Dart error hook for you:FlutterError.onError,PlatformDispatcher.onError, and a guarded zone for uncaught async errors. Flutter's usual red error screen and console output still work.Identify your users
Optional, but recommended.
Dart// After loginawait Codeskop.identify(user.id, traits: {'plan': user.plan}); // On logoutawait Codeskop.reset();Use your own stable user ID, never an email. As on native Android, call
identifyagain when the app restarts with a signed-in user. See Identify users.
What's captured automatically
- Uncaught Dart errors, reported as crashes, with the Dart stack trace
- Errors reported by the Flutter framework, reported as handled exceptions
- Native crashes and ANRs in the Android layer, from the native SDK (see Crash reporting and ANR monitoring)
Product analytics
On Growth and Scale, record screens and events for funnels, retention and segments. Add the navigator observer so named routes become screens, and track what matters:
MaterialApp(navigatorObservers: [CodeskopNavigatorObserver()], ...); await Codeskop.track('order_completed', properties: {'value': 49.99, 'currency': 'KES'});Report handled errors
try { await checkout();} catch (e, stack) { Codeskop.recordError(e, stack); // reported as a handled exception showErrorBanner();}Report failed HTTP calls
The plugin doesn't include an HTTP interceptor. Instead, call Codeskop.captureApiError from your own. With Dio, it looks like this:
import 'package:codeskop_tracker/codeskop_tracker.dart';import 'package:dio/dio.dart'; class CodeskopDioInterceptor extends Interceptor { @override void onError(DioException err, ErrorInterceptorHandler handler) { Codeskop.captureApiError( method: err.requestOptions.method, url: err.requestOptions.uri.toString(), status: err.response?.statusCode, errorKind: err.response == null ? 'network_error' : null, ); handler.next(err); }} final dio = Dio()..interceptors.add(CodeskopDioInterceptor());Query strings are removed from the URL before it's stored. Optional requestBytes and responseBytes arguments record payload sizes.
Advanced
Managing the zone yourself
If you already run your app in your own runZonedGuarded, call registerErrorHooks() instead of runGuarded, and forward zone errors to recordError:
void main() { runZonedGuarded(() async { WidgetsFlutterBinding.ensureInitialized(); Codeskop.registerErrorHooks(); await Codeskop.init(apiKey: 'cs_live_pk_YOUR_KEY', endpoint: 'https://api.codeskop.com'); runApp(const MyApp()); }, (error, stack) => Codeskop.recordError(error, stack, fatal: true));}Configuration on Flutter
In version 0.3.0, the Flutter API takes onlyapiKey and endpoint. Everything else uses the native SDK's defaults and remote config.