Skip to main content

Background

Get set up with the Helium SDK for Flutter. Reach out over your Helium slack channel or email founders@tryhelium.com for any questions.

Installation

The minimum version of Flutter supported by this SDK is 3.24.0.
To add the Helium package, run:
flutter pub add helium_flutter
Or if you prefer, you can add the helium_flutter package to your pubspec.yaml:
dependencies:
  helium_flutter: ^3.1.3
then run:
flutter pub get
Recommended - Make sure that Swift Package Manager support is enabled:
flutter upgrade
flutter config --enable-swift-package-manager
See this Flutter documentation for more details about Swift Package Manager.
You can still use Cocoapods for your dependencies if preferred. If you need to disable Swift Package Manager dependencies after having enabled it, refer to that same Flutter documentation.
If you are using RevenueCat, you should also install the helium_revenuecat package so RevenueCat can handle purchases. See the section titled RevenueCat Purchase Delegate in this guide.

iOS Settings

Helium requires iOS 15+. If your app already has a minimum of iOS 15 or higher, you’re all set. This can be specified in your ios/Podfile with:
platform :ios, '15.0'
If you still see errors related to minimum iOS version, consider updating to 15.0 or higher directly in the Xcode project.

Initialize Helium

Find your API key here
In your app’s initialization code (typically in main.dart or your root widget), add the following to configure Helium and prepare your paywalls:
import 'package:helium_flutter/helium_flutter.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final heliumFlutter = HeliumFlutter();
  await heliumFlutter.initialize(
    apiKey: "<your-helium-api-key>",
//    fallbackPaywall: Text("your fallback paywall"),
//    fallbackBundleAssetPath: "fallback-bundle-xxxx-xx-xx.json",
  );

  runApp(const MyApp());
}
Including a fallback option is highly recommended. See the Fallbacks section on this page.
initialize
method
You can set a custom user ID and custom user traits with the initialize method or by calling:
await heliumFlutter.overrideUserId(
  newUserId: "your-custom-user-id",
  traits: {
    "exampleTrait": "value",
    "userType": "premium"
  }
);
Set these values before or during initialize to ensure consistency in analytics events and for the best experimentation results.

Presenting Paywalls

You must have a trigger and workflow configured in the dashboard in order to show a paywall.
You can present a paywall programmatically using the presentUpsell method:
ElevatedButton(
  onPressed: () {
    final heliumFlutter = HeliumFlutter();
    heliumFlutter.presentUpsell(context: context, trigger: 'insert-trigger-here');
  },
  child: Text('Show Premium Features'),
),
Do not call presentUpsell in Widget build() as this can have unpredictable behavior.
You can also pass in event handlers and custom paywall traits directly to presentUpsell:
HeliumFlutter().presentUpsell(
  trigger: 'my_paywall',
  context: context,
  eventHandlers: PaywallEventHandlers(
    onOpen: (event) {
      log('${event.type} - trigger: ${event.triggerName}');
    },
    onClose: (event) {
      log('${event.type} - trigger: ${event.triggerName}');
    },
    onDismissed: (event) {
      log('${event.type} - trigger: ${event.triggerName}');
    },
    onPurchaseSucceeded: (event) {
      log('${event.type} - trigger: ${event.triggerName}');
    },
    onAnyEvent: (event) {
      // A handler for all paywall-related events.
      // Note that if you have other handlers (i.e. onOpen) set up,
      // both that handler AND this one will fire during paywall open.
    },
  ),
  customPaywallTraits: {
    "has_seen_intro_video": true,
  }
);
Looking for alternative presentation methods? Check out the guide on Ways to Show a Paywall.
You should now be able to see Helium paywalls in your app! Well done! 🎉

Helium Events

To handle various paywall-related events, implement HeliumCallbacks and pass it to initialize:
abstract class HeliumCallbacks {
  Future<void> onPaywallEvent(HeliumPaywallEvent heliumPaywallEvent);
}
For example:
class LogCallbacks implements HeliumCallbacks {
  @override
  Future<void> onPaywallEvent(HeliumPaywallEvent heliumPaywallEvent) async {
    log('onPaywallEvent: ${heliumPaywallEvent.type} - trigger: ${heliumPaywallEvent.triggerName}');
  }
}

Handling Purchases

By default, Helium will handle purchase logic for you. If you want a custom implementation, you’ll want to implement HeliumPurchaseDelegate and pass that into initialize.
abstract class HeliumPurchaseDelegate {
  Future<HeliumPurchaseResult> makePurchase(String productId);

  Future<bool> restorePurchases();
}

RevenueCat Purchase Delegate

If you are using RevenueCat, we recommend you use our built-in RevenueCat purchase delegate:
import 'package:helium_revenuecat/helium_revenuecat.dart';

final heliumFlutter = HeliumFlutter();
await heliumFlutter.initialize(
  apiKey: "<your-helium-api-key>",
  purchaseDelegate: RevenueCatPurchaseDelegate(),
);
Make sure to configure RevenueCat before initializing Helium. You will need to add the helium_revenuecat package in addition to helium_flutter.

Checking Subscription Status & Entitlements

If you use an external payment processor like Stripe, Helium’s entitlement helpers may not be reliable. We recommend implementing your own entitlement checking in that case. If you use Stripe with RevenueCat, we recommend using RevenueCat’s entitlement APIs instead.
Use these methods to check current user subscription status.
/// Checks if the user has any active subscription (including non-renewable)
Future<bool> hasAnyActiveSubscription();

/// Checks if the user has any entitlement
Future<bool> hasAnyEntitlement();

/// Checks if the user has an active entitlement for any product attached to the paywall that will show for provided trigger.
/// - Parameter trigger: Trigger that would be used to show the paywall.
/// - Returns: `true` if the user has bought one of the products on the paywall.
///            `false` if not. Returns `null` if not known (i.e. the paywall is not downloaded yet).
Future<bool?> hasEntitlementForPaywall(String trigger);

Example Usage

Check entitlements before showing paywalls to avoid showing a paywall to a user who should not see it.
heliumFlutter.presentUpsell(
  trigger: 'my_paywall',
  context: context,
  dontShowIfAlreadyEntitled: true
);

Fallbacks

The Flutter SDK currently has two fallback options - 1) Fallback bundle and 2) a fallback view. Fallback situations should be quite rare, but to be safe, it is highly recommended that you implement a fallback bundle or custom fallback view.

Advanced

In most cases there is no need to check download status. Helium will display a loading indication if a paywall is presented before download has completed.
You can listen to the status of the paywalls download via a stream:
HeliumFlutter.downloadStatus.listen((status) {
  print('Download status: ${status.name}');
});
The download status will be one of the following:
  • notDownloadedYet: The download has not been initiated.
  • inProgress: The download is in progress.
  • downloadSuccess: The download was successful.
  • downloadFailure: The download failed.
You can also check if paywalls have been downloaded with await heliumFlutter.paywallsLoaded()
Reset Helium entirely so you can call initialize again. Only for advanced use cases.
await HeliumFlutter().resetHelium();