appero_flutter 0.1.1 copy "appero_flutter: ^0.1.1" to clipboard
appero_flutter: ^0.1.1 copied to clipboard

Flutter plugin for Appero in-app feedback collection SDK

Appero SDK for Flutter #

The in-app feedback widget that drives organic growth.

Appero helps you capture user feedback at the right moments in your app journey. Built natively for iOS and Android with a Flutter-friendly API.

Features #

Automatic Feedback Prompts - Smart triggers based on user experience ✅ Native UI Components - High-performance native dialogs on both platforms ✅ Offline Support - Queues experiences when offline, syncs automatically ✅ Customizable Themes - Full control over colors, typography, and rating icons ✅ Custom Fonts - Support for brand-consistent fonts on iOS and Android ✅ Analytics Integration - Easy integration with Firebase, GA4, and custom platforms ✅ Cross-Platform - Single Dart API for iOS (16.0+) and Android (7.0+)

Installation #

Add to your pubspec.yaml:

dependencies:
  appero_flutter: ^0.1.1

Then run:

flutter pub get

Quick Start #

1. Initialize the SDK #

Initialize in your main() function before running your app:

import 'package:flutter/material.dart';
import 'package:appero_flutter/appero.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Appero.instance.initialize(
    apiKey: 'your_api_key',
    userId: 'user_123',  // Optional but recommended
    debug: true,         // Enable debug logging
  );

  runApp(MyApp());
}

2. Log User Experiences #

Track user sentiment at key moments in your app:

// After successful action
await Appero.instance.log(
  rating: ExperienceRating.positive,
  context: 'Purchase completed successfully',
);

// After error
await Appero.instance.log(
  rating: ExperienceRating.negative,
  context: 'Checkout failed',
);

3. That's it! #

The SDK automatically handles feedback prompts based on logged experiences.

Core Concepts #

Experience Logging #

The SDK tracks user experiences and automatically determines when to show a feedback prompt based on the Experience Threshold configured in the Appero Dashboard.

Experience Ratings #

Five levels of sentiment tracking:

Rating Value Emoji Use Case
ExperienceRating.strongPositive 5 😄 Very satisfied - Feature delights user
ExperienceRating.positive 4 🙂 Satisfied - Smooth completion
ExperienceRating.neutral 3 😐 Neutral - Completed but suboptimal
ExperienceRating.negative 2 🙁 Dissatisfied - Failed operations
ExperienceRating.strongNegative 1 😡 Very dissatisfied - Critical failures

Feedback Flows #

Three distinct flows based on user sentiment:

  • Positive Flow (😄 / 🙂): Thank you message, optional text feedback
  • Neutral Flow (😐): Asks what could be improved
  • Negative Flow (😡 / 🙁): Apologizes, asks what went wrong

When to Log Experiences #

Positive Experiences (😄 / 🙂):

  • Successful completion of user flows
  • Feature usage that delights users
  • Smooth transactions or purchases
  • Positive responses to content

Negative Experiences (😡 / 🙁):

  • Failed operations or error states
  • Server errors or timeouts
  • Abandoned flows
  • User frustration indicators

Neutral Experiences (😐):

  • Completed but suboptimal flows
  • Feature discovery without engagement
  • Canceled operations

⚠️ Important: Avoid logging sensitive information (addresses, phone numbers, emails, payment details) in the context field.

API Reference #

Initialization #

await Appero.instance.initialize({
  required String apiKey,    // Your Appero API key
  String? userId,            // Optional user identifier
  bool debug = false,        // Enable debug logging
});

Logging Experiences #

await Appero.instance.log({
  required ExperienceRating rating,  // User sentiment level
  String? context,                   // Optional context description
});

Manual Feedback Prompt #

// Show feedback UI manually
await Appero.instance.showFeedbackPrompt();

// Dismiss feedback UI
await Appero.instance.dismissPrompt();

Posting Feedback #

final success = await Appero.instance.postFeedback({
  required int rating,    // 1-5
  String? feedback,       // Optional text feedback
});

Theme Customization #

await Appero.instance.setTheme(ApperoTheme theme);

// Reset to system default (auto light/dark)
await Appero.instance.setTheme(null);

Reset SDK Data #

// Clear all locally stored data
await Appero.instance.reset();

Analytics Integration #

Track user feedback interactions in your analytics platform (Firebase Analytics, Mixpanel, GA4, etc.).

Setup Analytics Delegate #

import 'package:appero_flutter/appero.dart';
import 'package:firebase_analytics/firebase_analytics.dart';

class MyAnalyticsDelegate implements ApperoAnalyticsDelegate {
  final FirebaseAnalytics analytics = FirebaseAnalytics.instance;

  @override
  void onRatingSelected(int rating) {
    // Called when user selects a rating (1-5)
    analytics.logEvent(
      name: 'appero_rating_selected',
      parameters: {'rating': rating},
    );
  }

  @override
  void onFeedbackSubmitted(int rating, String? feedback) {
    // Called when user submits feedback
    analytics.logEvent(
      name: 'appero_feedback_submitted',
      parameters: {
        'rating': rating,
        'has_feedback': feedback != null,
        'feedback_length': feedback?.length ?? 0,
      },
    );
  }
}

// Set the delegate (typically in main())
Appero.instance.setAnalyticsDelegate(MyAnalyticsDelegate());

// Remove the delegate
Appero.instance.setAnalyticsDelegate(null);

Analytics Events #

The delegate receives two types of events:

  1. Rating Selected - User taps a rating icon (1-5)

    • Fires immediately when rating is selected
    • Provides rating value only
  2. Feedback Submitted - User submits feedback form

    • Fires when user completes and submits feedback
    • Provides rating and optional text feedback

Theme Customization #

Using Predefined Themes #

import 'package:appero_flutter/appero.dart';

// System theme (auto light/dark mode)
await Appero.instance.setTheme(systemTheme);

// Custom theme 1 (purple/lime yellow)
await Appero.instance.setTheme(customTheme1);

// Custom theme 2 (rose/purple with custom font)
await Appero.instance.setTheme(customTheme2);

// Reset to default
await Appero.instance.setTheme(null);

Creating Custom Themes #

const myTheme = ApperoTheme(
  colors: ApperoColors(
    surface: Color(0xFFFFFFFF),           // Background
    onSurface: Color(0xFF000000),         // Primary text
    onSurfaceVariant: Color(0xFF666666),  // Secondary text
    primary: Color(0xFF6200EE),           // Accent color
    onPrimary: Color(0xFFFFFFFF),         // Text on accent
    textFieldBackground: Color(0xFFF5F5F5), // Optional text field background override
    cursor: Color(0xFF6200EE),              // Optional cursor color override
  ),
  typography: ApperoTypography(
    titleLargeFontSize: 22.0,
    titleLargeFontWeight: FontWeight.bold,
    bodyMediumFontSize: 16.0,
    bodyMediumFontWeight: FontWeight.normal,
    labelLargeFontSize: 16.0,
    labelLargeFontWeight: FontWeight.w500,
    bodySmallFontSize: 14.0,
    bodySmallFontWeight: FontWeight.normal,
    fontFamily: null,  // Use system font
  ),
  usesSystemMaterial: false, // Disable frosted glass/system material effect
);

await Appero.instance.setTheme(myTheme);

Material Effect Control #

ApperoTheme includes a usesSystemMaterial flag:

  • true (default): enable system material styling where supported
  • false: disable system material styling

Optional Color Overrides #

ApperoColors supports optional overrides:

  • textFieldBackground: custom text field background color
  • cursor: custom text cursor color

If omitted, native defaults are used.

Platform support:

  • iOS: supported
  • Android: currently ignored by the native bridge until SDK parity is added

Custom Rating Images #

const myRatingImages = ApperoRatingImages(
  strongNegative: 'assets/rating_1.png',
  negative: 'assets/rating_2.png',
  neutral: 'assets/rating_3.png',
  positive: 'assets/rating_4.png',
  strongPositive: 'assets/rating_5.png',
);

const myTheme = ApperoTheme(
  colors: ApperoColors(...),
  typography: ApperoTypography(...),
  ratingImages: myRatingImages,
);

await Appero.instance.setTheme(myTheme);

Custom Fonts #

The SDK supports custom fonts on both iOS and Android.

Step 1: Add Font Files #

Create a fonts directory and add your font files:

your_app/
  fonts/
    YourFont-Regular.ttf
    YourFont-Bold.ttf

Step 2: Register in pubspec.yaml #

flutter:
  fonts:
    - family: your_font_name
      fonts:
        - asset: fonts/YourFont-Regular.ttf
          weight: 400
        - asset: fonts/YourFont-Bold.ttf
          weight: 700

Step 3: Setup for Android #

Copy the font to Android resources with lowercase, underscore-separated naming:

mkdir -p android/app/src/main/res/font
cp fonts/YourFont-Regular.ttf android/app/src/main/res/font/your_font_name.ttf

Android naming rules:

  • Must be lowercase
  • Use underscores instead of hyphens or spaces
  • Should match the fontFamily name in your theme

Step 4: Use in Theme #

const myTheme = ApperoTheme(
  colors: ApperoColors(...),
  typography: ApperoTypography(
    fontFamily: 'your_font_name',  // Must match pubspec.yaml family name
  ),
);

await Appero.instance.setTheme(myTheme);

Platform Details #

iOS:

  • ✅ Fonts loaded automatically from Flutter assets
  • ✅ PostScript name extracted and registered dynamically
  • ✅ No Info.plist configuration needed
  • ✅ Supports TrueType (.ttf) and OpenType (.otf)

Android:

  • ✅ Fonts must exist in android/app/src/main/res/font/
  • ✅ Filename must be lowercase with underscores
  • ✅ Filename should match fontFamily value

Troubleshooting Fonts #

Font not displaying:

  • Check font is declared in pubspec.yaml
  • Run flutter clean and rebuild
  • Verify font file is not corrupted
  • Check platform-specific logs for errors

Android font issues:

  • Verify file exists in android/app/src/main/res/font/
  • Ensure lowercase filename with underscores
  • Confirm filename matches fontFamily value

Example App #

The included example demonstrates all SDK features:

cd example
flutter run

Features demonstrated:

  • SDK initialization with debug mode
  • Analytics delegate integration
  • Theme switching (System, Theme 1, Theme 2)
  • Experience logging with all rating levels
  • Manual feedback prompt triggering
  • Error handling with SnackBar notifications

Architecture #

Flutter Layer #

  • Language: Dart 3.0+
  • State Management: Streams and StreamSubscription
  • Platform Channels: MethodChannel & EventChannel

iOS Native #

  • Language: Swift
  • UI Framework: SwiftUI
  • Reactive: Combine framework
  • Minimum Version: iOS 16.0+

Android Native #

  • Language: Kotlin
  • UI Framework: Jetpack Compose
  • Coroutines: kotlinx.coroutines
  • Minimum SDK: 24 (Android 7.0)

Requirements #

  • Flutter: >=3.24.0
  • Dart: >=3.0.0 <4.0.0
  • iOS: >=16.0
  • Android: SDK 24+ (Android 7.0 Nougat)

Offline Support #

The SDK handles offline scenarios gracefully:

  • ✅ Experiences logged while offline are queued locally
  • ✅ Automatic retry when connection is restored
  • ✅ Network state monitoring
  • ✅ JSON file storage in secure app storage

Best Practices #

1. Initialize Early #

Initialize in main() before running your app to ensure the SDK is ready.

2. Use Meaningful Context #

Provide descriptive context when logging experiences to help identify patterns:

// Good ✅
await Appero.instance.log(
  rating: ExperienceRating.positive,
  context: 'Checkout completed - 3 items',
);

// Avoid ❌
await Appero.instance.log(
  rating: ExperienceRating.positive,
  context: 'success',
);

3. Set User ID #

Provide a user ID during initialization to track feedback across sessions:

await Appero.instance.initialize(
  apiKey: 'your_key',
  userId: userAuthId,  // From your auth system
);

4. Analytics Integration #

Set up analytics delegate to track engagement metrics:

Appero.instance.setAnalyticsDelegate(MyAnalyticsDelegate());

5. Handle Errors Gracefully #

Wrap SDK calls in try-catch blocks:

try {
  await Appero.instance.log(rating: rating, context: context);
} catch (e) {
  // Handle error appropriately
  debugPrint('Appero error: $e');
}

6. Theme Consistency #

Apply your theme once during initialization:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Appero.instance.initialize(apiKey: 'key');
  await Appero.instance.setTheme(myCustomTheme);

  runApp(MyApp());
}

7. Don't Log PII #

Never log personally identifiable information in the context field:

// Never do this ❌
await Appero.instance.log(
  rating: rating,
  context: 'User email: ${user.email}',  // ❌ Don't log PII
);

// Do this instead ✅
await Appero.instance.log(
  rating: rating,
  context: 'User profile updated',  // ✅ Generic context
);

Sample Use Cases #

E-commerce App #

class CheckoutPage extends StatelessWidget {
  Future<void> _completeCheckout() async {
    try {
      await processPayment();

      // Log positive experience
      await Appero.instance.log(
        rating: ExperienceRating.strongPositive,
        context: 'Checkout completed',
      );

      navigateToConfirmation();
    } catch (e) {
      // Log negative experience
      await Appero.instance.log(
        rating: ExperienceRating.negative,
        context: 'Checkout failed',
      );

      showError(e);
    }
  }
}

Content App #

class VideoPlayer extends StatefulWidget {
  void _onVideoComplete() {
    // User watched entire video - positive signal
    Appero.instance.log(
      rating: ExperienceRating.positive,
      context: 'Video watched to completion',
    );
  }

  void _onVideoError(String error) {
    // Playback failed - negative signal
    Appero.instance.log(
      rating: ExperienceRating.strongNegative,
      context: 'Video playback error',
    );
  }
}

Social App #

class PostCreation extends StatelessWidget {
  Future<void> _publishPost() async {
    final result = await api.createPost(content);

    if (result.success) {
      Appero.instance.log(
        rating: ExperienceRating.strongPositive,
        context: 'Post published successfully',
      );
    } else {
      Appero.instance.log(
        rating: ExperienceRating.negative,
        context: 'Post publication failed',
      );
    }
  }
}

Contributing #

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests if applicable
  5. Submit a pull request

License #

MIT License - See LICENSE for details.

Support #

Credits #

Developed by Pocketworks Mobile


Made with ❤️ for Flutter developers

0
likes
150
points
17
downloads

Publisher

verified publisherpocketworks.co.uk

Weekly Downloads

Flutter plugin for Appero in-app feedback collection SDK

Homepage
Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on appero_flutter

Packages that implement appero_flutter