Flutter SDK

For account IDs, backend-verified guests, token expiry, property updates, and logout, see the identity integration guide. The lifecycle APIs documented there require 0.1.4 or later.

Production   Dart 3.3+ · Flutter 3.19+

usergist_feedback provides authenticated anonymous and identified subjects, offline queues, consent controls, locally targeted campaigns, surveys, feature requests, and host-compatible APNs/FCM integration.

Flutter 0.1.4 completes initialization after local hydration; network warm-up runs in the background so it cannot hold runApp.

Startup presentation readiness

Initialize with presentationPaused: true at app launch. Analytics, consent, identity, and networking continue while campaign UI waits. After the existing startup loading and navigation have finished and the loaded screen is visible, call resumePresentation(). Mount any required UserGist UI provider before that callback. Readiness must work for both anonymous and identified users.

Call pausePresentation() before another flow that must not be interrupted. Pausing does not dismiss an already visible SDK surface. Queued feedback, surveys, and in-app messages are discarded if their consent is withdrawn or the user changes, even if consent is granted again before resuming. Repeated initialization keeps the first readiness setting; repeated resume calls do not show the same queued work twice. The option defaults to false for existing integrations, so upgrading alone does not enable startup deferral.

Do not resume from a splash screen, an app-root mount that still shows loading, a disappearing screen, or a fixed timer. Use the host's existing completion callback; the SDK cannot infer when arbitrary startup navigation has finished.

// After the loaded screen and startup navigation are ready:
UserGist.resumePresentation();

Install

# pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  usergist_feedback: ^0.1.4
flutter pub get

iOS — open the ios/ folder and run pod install. Android needs no extra step.

Initialise

Call UserGist.init in main before runApp. Place UserGistProvider below your existing Navigator, as shown below, so it can render surveys, prompts, and the requests board.

import 'package:flutter/widgets.dart';
import 'package:usergist_feedback/usergist_feedback.dart';
 
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await UserGist.init(
    writeKey: 'rk_live_REPLACE_ME',
    environment: UserGistEnvironment.production,
    debug: false,
    presentationPaused: true,
  );
  runApp(const MyApp());
}
 
class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: UserGistProvider(child: HomeScreen()),
    );
  }
}

Init options

OptionTypeDefault
writeKeyString
environmentUserGistEnvironment.production
apiUrlString?null
debugboolfalse
flushIntervalDuration15 s
flushBatchSizeint100
maxQueueSizeint1000
triggerSyncIntervalDuration5 min
presentationPausedboolfalse

Identity & events

await UserGist.identify(
  'user_42',
  properties: {'plan': 'pro'},
  subjectToken: subjectToken,
);
 
UserGist.track('checkout_completed', properties: {
  'orderId': 'ord_991',
  'amountUsd': 49,
});
 
// On logout
await UserGist.reset();
await UserGist.setConsent(const Consent(
  analytics: true,
  feedback: true,
  push: false,
  survey: true,
));

Surveys

final surveys = await UserGist.getAvailableSurveys();
if (surveys.isNotEmpty) {
  UserGist.openSurvey(surveys.first.id);
}
 
// React to responses with a stream
UserGist.onResponseStream.listen((info) {
  debugPrint('Survey ${info.surveyId} responded');
});
import 'package:app_links/app_links.dart';
 
AppLinks().uriLinkStream.listen((uri) {
  UserGist.handleSurveyDeepLink(uri);
});

Feature requests board

// Hosted board (requires UserGistProvider)
UserGist.openRequestsBoard();
 
// Or build your own UI
final result = await UserGist.getRequests();
await UserGist.voteOnRequest('req_abc123', vote: true);
await UserGist.postComment('req_abc123', 'Please ship this!');

Push notifications

Keep using your app's APNs/FCM package and forward its tokens and lifecycle callbacks to the SDK.

await Push.instance.registerDeviceToken(
  token,
  Platform.isIOS ? 'ios' : 'android',
);
 
Push.instance.setHandlers(PushHandlers(
  onOpen: (message) => openDeepLink(message.deepLink),
));

iOS NSE

Add a Notification Service Extension to your iOS project (see iOS docs). The Flutter SDK shares the same APN configuration.

On Android, create notification channels in your host app before displaying a notification. On iOS, add a Notification Service Extension when you need rich media and true delivered beacons.

Theming

UserGist.setThemeOverrides(const PromptTheme(
  colors: PromptThemeColors(
    primary: Color(0xFF6C5CE7),
    background: Color(0xFF0B1220),
  ),
  radius: 12,
));

Public surface

MethodWhat it does
UserGist.init(...)Boots the SDK.
UserGist.identify(id, properties:, subjectToken:)Securely link a stable user.
UserGist.track(name, properties)Queue an event.
UserGist.setConsent(c)Gate subsystems.
UserGist.reset()Clear state.
UserGist.flush()Force flush.
UserGist.setDebug(bool)Toggle logs.
UserGist.getAnonymousId()Returns String?.
UserGist.setThemeOverrides(theme)Brand the in-SDK UI.
UserGist.onPromptShownStream, onResponseStream, onPushEventStreamStreams.
UserGist.getAvailableSurveys()List targeted surveys.
UserGist.openSurvey(id, language?)Render a survey.
UserGist.handleSurveyDeepLink(uri)Deep-link opener.
UserGist.getRequests(...), submitRequest(...), voteOnRequest(...), followRequest(...), getComments(...), postComment(...), editComment(...), deleteComment(...)Feature request board.
Push.instance.registerDeviceToken(...) / invalidateDeviceToken(...)Forward APNs/FCM token lifecycle.
Push.instance.handleReceived(...) / handleSilentIfPresent(...)Forward push delivery callbacks.

What's next