Skip to content

Flutter SDK ​

Integrate Klero feedback, roadmap, changelog, surveys, and widgets into your Flutter app.

In-App Widget - Work in Progress

The In-App Widget (KleroWidget) is currently not working properly in Flutter due to platform limitations with WebView touch passthrough and overlay rendering. This is a known issue and we are actively working on a fix. All other modules (feedback, roadmap, changelog, surveys) work as expected.

Requirements ​

  • Flutter >= 3.10.0
  • Dart >= 3.0.0

Installation ​

bash
flutter pub add klero_flutter

Quick Start ​

Any Module with KleroEmbed ​

KleroEmbed is the generic widget that supports all Klero module types. Convenience widgets are also provided.

dart
import 'package:klero_flutter/klero_flutter.dart';

// Using the generic widget
KleroEmbed(
  projectSlug: 'myproject',
  embedType: KleroEmbedType.feedback,
)

// Or use convenience widgets
KleroFeedback(projectSlug: 'myproject')
KleroRoadmap(projectSlug: 'myproject')
KleroChangelog(projectSlug: 'myproject')

Full Page Example ​

dart
import 'package:flutter/material.dart';
import 'package:klero_flutter/klero_flutter.dart';

class FeedbackPage extends StatelessWidget {
  const FeedbackPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Feedback')),
      body: const KleroFeedback(projectSlug: 'myproject'),
    );
  }
}

Survey with KleroSurvey ​

For surveys, use the dedicated KleroSurvey widget which provides survey-specific event callbacks:

dart
import 'package:klero_flutter/klero_flutter.dart';

KleroSurvey(
  projectSlug: 'myproject',
  surveyUlid: '01ABC123...',
  onComplete: (data) {
    print('Completed: ${data.responseUlid}');
    print('Answers: ${data.answers}');
  },
  onClose: (data) {
    print('Closed, completed: ${data.completed}');
  },
  onError: (error) {
    print('Error: $error');
  },
)

Programmatic Control ​

KleroEmbed ​

dart
import 'package:flutter/material.dart';
import 'package:klero_flutter/klero_flutter.dart';

class FeedbackPage extends StatefulWidget {
  const FeedbackPage({super.key});

  @override
  State<FeedbackPage> createState() => _FeedbackPageState();
}

class _FeedbackPageState extends State<FeedbackPage> {
  final _embedController = KleroEmbedController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Feedback'),
        actions: [
          IconButton(
            icon: const Icon(Icons.refresh),
            onPressed: () => _embedController.reload(),
          ),
        ],
      ),
      body: KleroEmbed(
        controller: _embedController,
        projectSlug: 'myproject',
        embedType: KleroEmbedType.feedback,
      ),
    );
  }

  @override
  void dispose() {
    _embedController.dispose();
    super.dispose();
  }
}

KleroSurvey ​

dart
final _surveyController = KleroSurveyController();

// Open the survey
_surveyController.open();

// Close the survey
_surveyController.close();

KleroSurvey(
  controller: _surveyController,
  projectSlug: 'myproject',
  surveyUlid: '01ABC123...',
)

Authentication ​

Pass a customer token to identify logged-in users:

dart
KleroFeedback(
  projectSlug: 'myproject',
  customerToken: 'your-jwt-token',
)

See the Authentication Guide for token generation.

Custom Base URL ​

For self-hosted or custom domain setups:

dart
KleroFeedback(
  projectSlug: 'myproject',
  baseUrl: 'https://feedback.mycompany.com',
)

Additional Embed Config ​

Pass extra configuration to the embed:

dart
KleroEmbed(
  projectSlug: 'myproject',
  embedType: KleroEmbedType.survey,
  embedConfig: {'surveyUlid': '01ABC123...'},
)

API Reference ​

KleroEmbed Properties ​

PropertyTypeRequiredDescription
projectSlugStringYesYour Klero project slug
embedTypeKleroEmbedTypeYesModule type (feedback, roadmap, changelog, widget, survey)
baseUrlString?NoCustom base URL
customerTokenString?NoJWT token for user identification
embedConfigMap<String, dynamic>?NoAdditional config passed to the embed
controllerKleroEmbedController?NoController for programmatic control
onLoadVoidCallback?NoCalled when WebView finishes loading

KleroEmbedController Methods ​

MethodDescription
reload()Reload the embed
dispose()Clean up resources

KleroSurvey Properties ​

PropertyTypeRequiredDescription
projectSlugStringYesYour Klero project slug
surveyUlidStringYesThe survey's unique identifier
baseUrlString?NoCustom base URL
customerTokenString?NoJWT token for user identification
controllerKleroSurveyController?NoController for programmatic control
onCompletevoid Function(SurveyCompletedEvent)?NoSurvey completed
onClosevoid Function(SurveyClosedEvent)?NoSurvey closed
onErrorvoid Function(String)?NoSurvey failed to load
onLoadVoidCallback?NoCalled when WebView finishes loading

KleroSurveyController Methods ​

MethodDescription
open([String? surveyUlid])Open the survey
close()Close the survey
dispose()Clean up resources

Convenience Widgets ​

WidgetEquivalent
KleroFeedbackKleroEmbed(embedType: KleroEmbedType.feedback)
KleroRoadmapKleroEmbed(embedType: KleroEmbedType.roadmap)
KleroChangelogKleroEmbed(embedType: KleroEmbedType.changelog)

Platform Setup ​

Android ​

Add internet permission to android/app/src/main/AndroidManifest.xml (usually already present):

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

iOS ​

No additional setup required. The SDK uses WKWebView which is available on iOS 13.0+.

Customer Feedback Management