Skip to content

Setting Up the Feedback SDK

What you'll learn

  • Generating the Feedback SDK with optional feature voting
  • Configuring the feedback endpoint via a DI module
  • Submitting bug reports and general feedback with screenshot attachments
  • Using shake-to-feedback and the offline queue
  • Letting users vote on feature requests

Prerequisites

Pro Feature

feedback_sdk requires an active Pro subscription. Run archipelago auth status to confirm your tier.

Step 1: Generate the Feedback SDK

bash
archipelago generate feedback_sdk

You will be prompted for:

  • includeFeatureVotingtrue to scaffold feature-request voting endpoints (default: true)
  • defaultEndpoint — your feedback API URL, e.g. https://api.yourapp.com/feedback (default: empty — configure in DI instead)

Or use a config file:

json
{
  "includeFeatureVoting": true,
  "defaultEndpoint": ""
}
bash
archipelago generate feedback_sdk --config feedback_config.json

Step 2: Understand the Generated Structure

features/feedback/
├── feedback_api/
│   └── lib/src/
│       ├── feedback_sdk.dart             # Abstract SDK contract
│       ├── feedback_submission.dart      # Submission value object
│       ├── feedback_category.dart        # FeedbackCategory enum
│       ├── feedback_config.dart          # Config value object
│       └── models/
│           └── feature_request.dart      # (when includeFeatureVoting=true)
└── feedback_impl/
    └── lib/src/
        ├── feedback_sdk_impl.dart        # HTTP + offline queue impl
        └── di/                           # GetIt module

Step 3: Configure the Endpoint

Provide FeedbackConfig in a DI module before FeedbackImplPackageModule is registered. Create app_feedback_module.dart in your shell app:

dart
@module
abstract class AppFeedbackModule {
  @lazySingleton
  FeedbackConfig get feedbackConfig => const FeedbackConfig(
    endpoint: 'https://api.yourapp.com/feedback',
    attachAppVersion: true,
    attachDeviceInfo: true,
  );
}

Then register in bootstrap.dart:

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

FeatureRegistry.register(FeedbackImpl());

Step 4: Submit Feedback

Inject FeedbackSDK via GetIt and call submit():

dart
final feedbackSDK = getIt<FeedbackSDK>();

await feedbackSDK.submit(
  FeedbackSubmission(
    text: 'The checkout button is hard to find',
    category: FeedbackCategory.bug,
    screenshotPath: await _captureScreenshot(),
  ),
);

FeedbackCategory values: bug, general, featureRequest, question.

Leave screenshotPath null to submit without an attachment.

Step 5: Offline Queue

The SDK queues submissions in SharedPreferences when the device is offline. No extra setup is required — the queue drains automatically when connectivity is restored.

If you have the Connectivity SDK installed, wire the state stream in for faster drain triggering:

dart
connectivitySDK.stateStream.listen((state) {
  feedbackSDK.recordConnectivity(online: state.isOnline);
});

Without this wiring, the SDK polls on the next submit() call.

Step 6: Shake-to-Feedback (Optional)

Add the shake package to your shell app's pubspec.yaml:

yaml
dependencies:
  shake: ^2.2.0

Then start the detector after your DI is ready:

dart
ShakeDetector.autoStart(
  onPhoneShake: () async {
    final text = await _promptUserForText();
    await feedbackSDK.submit(
      FeedbackSubmission(
        text: text,
        category: FeedbackCategory.general,
      ),
    );
  },
);

_promptUserForText() should show a dialog — use whatever UI pattern fits your app.

Step 7: Feature Voting (when includeFeatureVoting=true)

Fetch open feature requests and let users upvote them:

dart
final requests = await feedbackSDK.getFeatureRequests();

// Display in a list, then on tap:
final result = await feedbackSDK.voteOnFeatureRequest(requests.first.id);

Votes are locally deduplicated: calling voteOnFeatureRequest() a second time for the same requestId returns FeatureRequestVoteResult.alreadyVoted without hitting the network.

dart
switch (result) {
  case FeatureRequestVoteResult.success:
    showSnackbar('Thanks for your vote!');
  case FeatureRequestVoteResult.alreadyVoted:
    showSnackbar('You\'ve already voted for this.');
  case FeatureRequestVoteResult.error:
    showSnackbar('Something went wrong, try again.');
}

Common Customizations

CustomizationWhere to Change
Add user identity to submissionsSet userId on FeedbackConfig in your DI module
Custom categoriesExtend FeedbackCategory in a local fork of the api package
Rate-limit shake triggerTrack last submission timestamp before calling submit()
Disable in release buildsWrap ShakeDetector.autoStart with !kReleaseMode

Next Steps

Built by Banua Coder