---
title: Using the Flutter SDK
description: >-
  Survicate allows you to launch precisely targeted surveys inside your app. In
  the Survicate Panel, you can set conditions that need to be met for the
  surveys to appear.
source_url:
  html: 'https://developers.survicate.com/mobile-sdk/flutter/using-sdk/'
  md: 'https://developers.survicate.com/mobile-sdk/flutter/using-sdk.md'
---
# Using the Flutter SDK

Survicate allows you to launch precisely targeted surveys inside your app. In the Survicate Panel, you can set conditions that need to be met for the surveys to appear. Users matching conditions defined in the Survicate panel will see the survey automatically. Here's a list of conditions you can use to target your surveys:

- Name of the screen that a user currently sees
- Any application event
- User attributes and identities
- Language of the device
- Operating system

Make sure to list all the screens and events described in your application.
Once you got this covered, you or any person responsible for creating and managing surveys will be able to trigger surveys from the Survicate panel with no need for you to update the application.

## Targeting a survey by screen name

A survey can appear when a user is viewing a specific screen. For example, a survey can be triggered to show up on the application's home screen after a user spends more than ten seconds there. To set it up, you need to send information to Survicate about the user entering and leaving a screen.

_Note: Multiple active screens are allowed. In specific, calling enterScreen() does not make the previous screen to be discarded. Be sure to call leaveScreen() when you no longer want the screen to be treated as active._

```dart
// Example of tracking screen changes using the RouteObserver and Flutter Navigator

// Define the RouteObserver as a global variable:
final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();

// Set up your main app and attach the RouteObserver:
class MainApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Route Observer Example',
      navigatorObservers: [routeObserver],
      home: Screen(),
    );
  }
}

// Implement the RouteAware interface on your screen widget
// Subscribe to the route observer in the didChangeDependencies() method and unsubscribe in the dispose() method.
// Call SurvicateSdk.enterScreen() in the didPush() and didPopNext() methods.
// Call SurvicateSdk.leaveScreen() in the didPop() and didPushNext() methods.
class _ScreenState extends State<Screen> with RouteAware {
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    routeObserver.subscribe(this, ModalRoute.of(context));
  }

  @override
  void dispose() {
    routeObserver.unsubscribe(this);
    super.dispose();
  }

  @override
  void didPush() {
    // Route was pushed onto navigator, this widget is now visible
    SurvicateSdk.enterScreen("screenName");
  }

  @override
  void didPopNext() {
    // Covering route was popped off the navigator, this widget is now visible again
    SurvicateSdk.enterScreen("screenName");
  }

  @override
  void didPop() {
    // This route was popped off the navigator
    SurvicateSdk.leaveScreen("screenName");
  }

  @override
  void didPushNext() {
    // A new route was pushed onto navigator, this widget is no longer visible
    SurvicateSdk.leaveScreen("screenName");
  }
}
```

_Screen name is case sensitive. If there's any discrepancy between what's declared in the ‘Triggers’ tab of the Target section in the Survicate panel and the application code, the survey will not appear._

## Events-based survey targeting

The SDK allows you to launch surveys based on events your users trigger in your app. Your survey will show instantly after an event occurs in your app.

```dart
SurvicateSdk.invokeEvent("eventName");

Map<String, String> properties = {
  'property1': 'value1',
  'property2': 'value2',
};
SurvicateSdk.invokeEvent('Event', eventProperties: properties);
```

_Event name and property keys are case sensitive. If there is any discrepancy between what's declared in the ‘Triggers’ tab of the Target section in the Survicate panel and the application code, the survey will not appear._

## Passing user attributes

You can provide user attributes to Survicate as an extra layer of information about your users. The attributes have various use cases:

* Identification of survey participants (answers are anonymous by default).
* Directing surveys to particular users (Audience filters).
* Filtering responses.
* Recalling data in questions.

```dart
UserTrait trait = UserTrait.string("traitName", "traitValue");
SurvicateSdk.setUserTrait(trait);

UserTrait textTrait = UserTrait.string("name", "traitValue");
UserTrait numberTrait = UserTrait.num("age", 123);
UserTrait booleanTrait = UserTrait.bool("isPremium", true);
UserTrait datetimeTrait = UserTrait.dateTime("lastLogin", DateTime.now());
UserTrait timeIntervalTrait = UserTrait.dateTime("timeOfPurchase", DateTime.now());

List<UserTrait> traits = [
  textTrait,
  numberTrait
];
SurvicateSdk.setUserTraits(traits);
```

_Bear in mind that user attributes are cached. You only need to provide them once, e.g. when user logs in, not after each initilization. You can also change their values at any time to trigger a survey._

**Attribute types**
- **string**: any text.
- **num**: an integer or decimal.
- **bool**: a logic value.
- **dateTime**: a dart:core `DateTime` object which can be used with date or time interval filters in the panel (the latter measure elapsed time from a given timestamp).

**Special attributes**

- **user_id**: This corresponds to the "Logged-in status" in the panel's Audience filter. A user is considered logged-in when a trait with the "user_id" key has been set on the device, regardless of the value.

- **first_name**, **last_name**, **email**: If none of these is specified, a response will be marked as Anonymous in the panel.

**Additional notes**   
You can set your own attribute keys without any prior registration. They will show up in the panel once any response with the attribute is uploaded.

## Response attributes

Response attributes are session-scoped attributes attached to survey responses. Unlike user attributes, they are cleared at the start of each new app session and are sent to Survicate along with the user's survey answers.

To update a response attribute, call the method again with the same name and a new value. To clear an attribute, pass an empty string as the value.

```dart
// set a single attribute
SurvicateSdk.setResponseAttribute(ResponseAttribute.string('plan', 'premium'));

// or multiple attributes at once
SurvicateSdk.setResponseAttributes([
  ResponseAttribute.string('plan', 'premium'),
  ResponseAttribute.bool('isTrialExpired', false),
  ResponseAttribute.num('seats', 5),
  ResponseAttribute.dateTime('renewalDate', DateTime.now()),
]);
```

`ResponseAttribute` accepts the following parameters:
- **name** (required): The key that identifies the attribute.
- **value** (required): The attribute value. Pass an empty string to clear an existing attribute.
- **provider** (optional): The name of the external service where this data comes from (e.g., "hubspot", "intercom"). This helps integrations identify and match your survey respondents with their profiles in that service.

**Attribute types**
- **string**: any text.
- **num**: an integer or decimal.
- **bool**: a logic value.
- **dateTime**: a dart:core `DateTime` object.

## Setting the locale

Survicate SDK automatically detects the device locale and uses it both to choose the translation of a survey and to evaluate any Device language targeting filters.

If your app allows users to change the locale independently of the system settings, you can override the default by calling:

```dart
SurvicateSdk.setLocale("en-US");
```

The argument must be a valid IETF language tag such as:

- A two‑letter ISO 639 code (e.g., "en", "fr")
- A three-letter code for languages without the two-letter equivalent (e.g., "haw", "yue")
- A language tag with region (e.g., "en-US", "pt-BR")

_Note: The specified locale setting applies only to the current application session. To preserve the preference after an app restart, make sure to call `setLocale(...)` again, anytime after `Survicate.initializeSdk(...)`._

## Theme mode

When your survey has a theme with both light and dark modes, the SDK will select the proper variant following the system setting by default.

Optionally, you can enforce a specific theme mode with the `setThemeMode` method:

```dart
// light, dark, or auto
SurvicateSdk.setThemeMode(ThemeMode.auto);
```

## Custom Fonts

Using the `SurvicateSdk.setFonts` method you can specify custom fonts for survey presentation. You need to provide a font path for each font style required by the SDK.

Place your font files in the `assets/` directory of your project:
```
assets/
  fonts/
    MyFont-Regular.ttf
    MyFont-Italic.ttf
    MyFont-Bold.ttf
    MyFont-BoldItalic.ttf
```

Declare your font files under the `assets:` section in `pubspec.yaml`:

```yaml
flutter:
  assets:
    - assets/fonts/MyFont-Regular.ttf
    - assets/fonts/MyFont-Italic.ttf
    - assets/fonts/MyFont-Bold.ttf
    - assets/fonts/MyFont-BoldItalic.ttf
```

Call `SurvicateSdk.setFonts()` with a `SurvicateFontSystem`. The paths must match **exactly** what you declared in `pubspec.yaml`:

```dart
import 'package:survicate_sdk/survicate_sdk.dart';

SurvicateSdk.setFonts(SurvicateFontSystem(
  regular: 'assets/fonts/MyFont-Regular.ttf',
  regularItalic: 'assets/fonts/MyFont-Italic.ttf',
  bold: 'assets/fonts/MyFont-Bold.ttf',
  boldItalic: 'assets/fonts/MyFont-BoldItalic.ttf',
));
```

## Event listeners

SDK allows you to utilize event listeners. You may find them useful to trigger actions in your application based on actions performed by respondents. Here's a list of events you can subscribe to:

* onSurveyDisplayed - occurs when survey is loaded and appears in the User Interface
* onQuestionAnswered - occurs after a question is answered ( Survicate stores incomplete survey submissions )
* onSurveyClosed - occurs when a user closes the survey using the close button
* onSurveyCompleted - occurs when a user finishes the survey

```dart
import 'package:survicate_sdk/survicate_sdk.dart';

SurvicateEventListener listener = SurvicateEventListener(
  onSurveyDisplayed: (SurveyDisplayedEvent event) { },  // onSurveyDisplayed
  onQuestionAnswered: (QuestionAnsweredEvent event) { }, // onQuestionAnswered
  onSurveyClosed: (SurveyClosedEvent event) { },  // onSurveyClosed
  onSurveyCompleted: (SurveyCompletedEvent event) { }, // onSurveyCompleted
);
SurvicateSdk.addSurvicateEventListener(listener);
SurvicateSdk.removeSurvicateEventListener(listener);
```

### _SurvicateAnswer_ properties (_QuestionAnsweredEvent.answer_)

| Property | Type        | Description                                                                                    |
|:---------|:------------|:-----------------------------------------------------------------------------------------------|
| type     | String?      | Answer type. One of: ['text', 'single', 'multiple', 'smiley_scale', 'rating', 'csat', 'numerical_scale', 'nps', 'date', 'form', 'matrix', 'button_close', 'button_next', 'button_link']. |
| id       | int?       | Answer ID. **Applicable only for types: ['single', 'smiley_scale', 'csat', 'rating', 'numerical_scale'].** |
| ids      | List&lt;int&gt; | Selected answer IDs. **Applicable only for type = ['multiple'].** |
| value    | String?    | Text representation of an answer, e.g. "Happy" for smiley scale. A `null` value in case of a skipped question. **Not applicable for call-to-action answers: ['button_close', 'button_next', 'button_link'].** |

_The `id`, `ids` and `value` properties are provided only for the cases enlisted in the table above. Therefore, expect that there might be answer objects that consist only of the `type` property._

## Reseting user data for testing purposes

If you need to test surveys on your device, the `reset()` method can be useful. It clears all user data stored on the device — including survey views, attributes, and information about answered surveys — as well as the current in-memory state of the SDK.

```dart
SurvicateSdk.reset();
```
