Welcome to Encatch Docs
Mobile SDK

Flutter SDK

Complete integration guide for the Encatch Flutter SDK — in-app feedback and survey collection for Flutter apps

Beta

This SDK is currently in beta. APIs may change, and we welcome your feedback. Use with caution in production environments.

Official Flutter SDK for Encatch — in-app feedback and survey collection.


Installation

Add encatch_flutter to your pubspec.yaml:

dependencies:
  encatch_flutter: ^1.0.0

Android Setup

Add internet permission to android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />

iOS Setup

No additional setup required. The SDK uses flutter_inappwebview which works out of the box.


Quick Start

1. Wrap your app with EncatchProvider

import 'package:encatch_flutter/encatch_flutter.dart';

void main() {
  runApp(
    EncatchProvider(
      apiKey: 'your-api-key',
      child: MyApp(),
    ),
  );
}

2. Identify users

await Encatch.identifyUser(
  'user@example.com',
  traits: UserTraits(
    set: {'name': 'Jane Doe', 'plan': 'pro'},
  ),
);

3. Track events

await Encatch.trackEvent('button_clicked');

4. Track screens

await Encatch.trackScreen('HomeScreen');

Add EncatchNavigatorObserver for automatic screen tracking:

MaterialApp(
  navigatorObservers: [EncatchNavigatorObserver()],
  // ...
)

5. Show a form manually

await Encatch.showForm('your-form-slug');

6. Listen to form events

final unsubscribe = Encatch.on((eventType, payload) {
  print('Event: $eventType, payload: ${payload.data}');
});

// Later, to stop listening:
unsubscribe();

7. Pre-fill responses

Encatch.addToResponse('question_id', 'pre-filled value');
await Encatch.showForm('your-form-slug');

Configuration

Configure the SDK via EncatchConfig when wrapping your app:

EncatchProvider(
  apiKey: 'your-api-key',
  config: EncatchConfig(
    theme: EncatchTheme.system,
    debugMode: true,
    isFullScreen: false,
    apiBaseUrl: 'https://app.encatch.com',
    appVersion: '1.2.3',
    onBeforeShowForm: (payload) async {
      // Return false to prevent form from showing
      return true;
    },
  ),
  child: MyApp(),
)

Configuration Options

Prop

Type


API Reference

EncatchProvider

Top-level widget that initializes the Encatch SDK. Wrap your app's root widget to initialize the SDK with your API key, start a session automatically, and mount the headless WebView form listener.

EncatchProvider(
  apiKey: 'your-api-key',
  config: EncatchConfig(...), // optional
  child: MyApp(),
)

Prop

Type


Initialization

Initialize the SDK manually. Safe to call multiple times.

await Encatch.init('your-api-key');

Prop

Type


User Identification

Identify the current user. The userName is required (can be a username, email, or unique identifier). Traits and options are optional.

await Encatch.identifyUser('user@example.com');
await Encatch.identifyUser(
  'user@example.com',
  traits: UserTraits(
    set: {'name': 'Alice', 'plan': 'pro'},
  ),
);
await Encatch.identifyUser(
  'user@example.com',
  traits: UserTraits(
    set: {'name': 'Alice', 'plan': 'pro'},
    setOnce: {'firstSeen': DateTime.now()},
    increment: {'loginCount': 1},
    decrement: {'credits': 5},
    unset: ['trialEndDate'],
  ),
);
await Encatch.identifyUser(
  'user@example.com',
  options: IdentifyOptions(
    secure: SecureOptions(
      signature: 'your-hmac-signature',
      generatedDateTimeinUTC: '2025-03-13T12:00:00Z',
    ),
  ),
);

Prop

Type

User traits support the following operations:

OperationDescription
setSet user attributes (overwrites existing values)
setOnceSet user attributes only if they don't already exist
incrementIncrement numeric user attributes
decrementDecrement numeric user attributes
unsetRemove user attributes

Secure Identification

Recommended

Using the secure option with a server-generated signature is recommended to verify that identification requests come from your backend. Keep your secret key on the server only — never expose it in client-side code.

Pass a server-generated HMAC signature so Encatch can validate the request. The generatedDateTimeinUTC timestamp limits the signature's lifespan.

await Encatch.identifyUser(
  'user@example.com',
  options: IdentifyOptions(
    secure: SecureOptions(
      signature: 'your-hmac-signature',
      generatedDateTimeinUTC: '2025-03-13T12:00:00Z',
    ),
  ),
);

Locale

Set the user's preferred language.

await Encatch.setLocale('fr');

Country

Set the user's country.

await Encatch.setCountry('FR'); // ISO 3166 country code

Theme

Set the theme for forms and surveys.

Encatch.setTheme(EncatchTheme.dark);
Encatch.setTheme(EncatchTheme.light);
Encatch.setTheme(EncatchTheme.system); // Follows system preference

Event Tracking

Track a custom event.

await Encatch.trackEvent('button_clicked');
await Encatch.trackEvent('purchase_completed');

Screen Tracking

Track screen navigation.

await Encatch.trackScreen('HomeScreen');
await Encatch.trackScreen('CheckoutScreen');

EncatchNavigatorObserver

Add to MaterialApp.navigatorObservers for automatic screen tracking:

MaterialApp(
  navigatorObservers: [EncatchNavigatorObserver()],
  routes: {
    '/': (context) => HomeScreen(),
    '/settings': (context) => SettingsScreen(),
  },
)

Session

Manually start a new session. Called automatically by EncatchProvider.

await Encatch.startSession();

Reset User

Reset the current user identity and clear all persisted data. Reverts the SDK to anonymous mode.

await Encatch.resetUser();

Show Form

Show a specific form by slug or ID.

await Encatch.showForm('feedback-form');
await Encatch.showForm('feedback-form', options: ShowFormOptions(
  reset: ResetMode.always,
));

Prop

Type

Prop

Type

ResetModeBehavior
ResetMode.alwaysReset pre-fill and response data on every form display
ResetMode.onCompleteReset only after the form is completed
ResetMode.neverNever reset response data

Dismiss Form

Dismiss the currently displayed form.

await Encatch.dismissForm();
// Or dismiss a specific form configuration:
await Encatch.dismissForm(formConfigurationId: 'config-id');

Prepopulate Response

Pre-fill a form response before showing a form.

Encatch.addToResponse('question_id', 'pre-filled value');
Encatch.addToResponse('choice_question_id', ['option-a', 'option-b']);

await Encatch.showForm('your-form-slug');

Event Subscription

Subscribe to form lifecycle events. Returns an unsubscribe function.

final unsubscribe = Encatch.on((eventType, payload) {
  print('Event: $eventType, payload: ${payload.data}');
});

// Later, to unsubscribe:
unsubscribe();
EventDescription
EventType.formShowFired when a form is displayed
EventType.formStartedFired when a user starts interacting
EventType.formSubmitFired when a form is submitted
EventType.formCompleteFired when a form is fully completed
EventType.formCloseFired when a form is closed
EventType.formDismissedFired when a form is dismissed without completion
EventType.formErrorFired when an error occurs
EventType.formSectionChangeFired when the visible section changes
EventType.formAnsweredFired when a question is answered

Form Interceptor

Use onBeforeShowForm in EncatchConfig to conditionally block forms from showing.

EncatchProvider(
  apiKey: 'your-api-key',
  config: EncatchConfig(
    onBeforeShowForm: (payload) async {
      // Inspect payload.formId, payload.formConfig, payload.triggerType, etc.
      if (payload.triggerType == TriggerType.automatic && someCondition) {
        return false; // Block this form
      }
      return true; // Allow
    },
  ),
  child: MyApp(),
)

Custom Native Forms

Use buildSubmitRequest and Encatch.submitForm when building your own native form UI instead of the WebView overlay.

import 'package:encatch_flutter/encatch_flutter.dart';

final request = buildSubmitRequest(
  options: BuildSubmitRequestOptions(
    formConfigurationId: 'config-id',
    triggerType: TriggerType.manual,
    responseLanguageCode: 'en',
    completionTimeInSeconds: 45,
    isPartialSubmit: false,
    feedbackIdentifier: 'optional-id',
  ),
  responses: [
    NativeFormResponse(questionId: 'q1', type: 'rating', value: 5),
    NativeFormResponse(questionId: 'q2', type: 'nps', value: 9),
    NativeFormResponse(questionId: 'q3', type: 'short_answer', value: 'Great!'),
    NativeFormResponse(questionId: 'q4', type: 'long_text', value: 'Detailed feedback...'),
    NativeFormResponse(questionId: 'q5', type: 'single_choice', value: 'option-a'),
    NativeFormResponse(questionId: 'q6', type: 'multiple_choice', value: ['a', 'b']),
  ],
);

await Encatch.submitForm(request);
TypeValue typeDescription
ratingintNumeric rating
npsintNPS score
short_answerStringShort text response
long_textStringLong text response
single_choiceStringSingle option selected
multiple_choiceList<String>Multiple options selected

Requirements

  • Dart SDK: >=3.11.0 <4.0.0
  • Flutter: >=3.41.0

Dependencies

The SDK uses:

  • flutter_inappwebview — WebView for form display
  • shared_preferences — Persistence
  • device_info_plus — Device metadata
  • package_info_plus — App version
  • uuid — ID generation
  • http — API requests

Raising Issues

GitHub Repository: github.com/get-encatch/flutter-sdk

How is this guide?