helium_flutter 0.0.3 copy "helium_flutter: ^0.0.3" to clipboard
helium_flutter: ^0.0.3 copied to clipboard

Flutter Paywall SDK for Helium. Remotely build and auto-optimize paywalls (tryhelium.com)

helium_flutter #

Installation #

Add the helium_flutter package to your pubspec.yaml:

dependencies:
  helium_flutter: ^0.0.1

Then run:

flutter pub get

Make sure that Swift Package Manager Support is enabled:

flutter upgrade
flutter config --enable-swift-package-manager

See Google's guide on this for more details.

Configuration #

Set up your HeliumCallbacks #

To integrate Helium paywalls, create a class that implements the HeliumCallbacks interface. This class is responsible for handling the purchase logic for your paywalls.

abstract class HeliumCallbacks {
  // [REQUIRED] - Trigger the purchase of a product with the provided product ID.
  // This method should return a HeliumTransactionStatus enum.
  Future<HeliumTransactionStatus> makePurchase(String productId);

  // [OPTIONAL] - Restore any existing subscriptions.
  // This method should return a boolean indicating whether the restore was successful.
  Future<bool> restorePurchases(bool status);

  // [OPTIONAL] - Custom analytics/error logging for paywall/helium related events.
  // By default, events are logged to your analytics service, but you can override 
  // this method to add additional custom logging/handling.
  Future<void> onPaywallEvent(Map<String, dynamic> heliumPaywallEvent);
}

The HeliumTransactionStatus enum defines the possible states of a paywall transaction:

enum HeliumTransactionStatus { 
  purchased, 
  failed, 
  cancelled, 
  restored, 
  pending 
}

Example Callbacks Implementation: #

Basic Implementation

Here's a basic implementation of the HeliumCallbacks interface:

import 'package:helium_flutter/helium_flutter.dart';
import 'dart:developer';

class PaymentCallbacks implements HeliumCallbacks {
  @override
  Future<HeliumTransactionStatus> makePurchase(String productId) async {
    log('makePurchase: $productId');
    // Implement your purchase logic here
    return HeliumTransactionStatus.purchased;
  }

  @override
  Future<bool> restorePurchases(bool status) async {
    log('restorePurchases: $status');
    // Implement your restore logic here
    return status;
  }

  @override
  Future<void> onPaywallEvent(Map<String, dynamic> heliumPaywallEvent) async {
    log('onPaywallEvent: $heliumPaywallEvent');
    // Handle paywall events here
  }
}

RevenueCat Implementation

import 'package:helium_flutter/helium_flutter.dart';
import 'package:purchases_flutter/purchases_flutter.dart';
import 'dart:developer';

class RevenueCatCallbacks implements HeliumCallbacks {
  @override
  Future<HeliumTransactionStatus> makePurchase(String productId) async {
    try {
      log('RevenueCat making purchase: $productId');
      final offerings = await Purchases.getOfferings();
      
      Package? packageToPurchase;
      
      // Find the package in current offering
      if (offerings.current != null) {
        for (var package in offerings.current!.availablePackages) {
          if (package.storeProduct.identifier == productId) {
            packageToPurchase = package;
            break;
          }
        }
      }
      
      // If not found in current, search all offerings
      if (packageToPurchase == null) {
        for (var offering in offerings.all.values) {
          for (var package in offering.availablePackages) {
            if (package.storeProduct.identifier == productId) {
              packageToPurchase = package;
              break;
            }
          }
          if (packageToPurchase != null) break;
        }
      }
      
      if (packageToPurchase == null) {
        log('Product not found in any offering: $productId');
        return HeliumTransactionStatus.failed;
      }
      
      final purchaseResult = await Purchases.purchasePackage(packageToPurchase);
      
      // Check if the purchase was successful by looking at entitlements
      if (purchaseResult.customerInfo.entitlements.active.isNotEmpty) {
        return HeliumTransactionStatus.purchased;
      } else {
        return HeliumTransactionStatus.failed;
      }
    } catch (e) {
      log('RevenueCat purchase error: $e');
      if (e is PurchasesErrorCode) {
        if (e == PurchasesErrorCode.purchaseCancelledError) {
          return HeliumTransactionStatus.cancelled;
        } else if (e == PurchasesErrorCode.paymentPendingError) {
          return HeliumTransactionStatus.pending;
        }
      }
      return HeliumTransactionStatus.failed;
    }
  }

  @override
  Future<bool> restorePurchases(bool status) async {
    try {
      log('RevenueCat restoring purchases');
      final restoredInfo = await Purchases.restorePurchases();
      return restoredInfo.entitlements.active.isNotEmpty;
    } catch (e) {
      log('RevenueCat restore error: $e');
      return false;
    }
  }

  @override
  Future<void> onPaywallEvent(Map<String, dynamic> heliumPaywallEvent) async {
    log('RevenueCat paywall event: $heliumPaywallEvent');
    // Handle specific events as needed
    final eventType = heliumPaywallEvent['type'];
    
    if (eventType == 'subscriptionSucceeded') {
      // Handle successful subscription
      final productId = heliumPaywallEvent['productKey'];
      log('Subscription succeeded for product: $productId');
      
      // Add your custom analytics tracking here
    }
  }
}

Initialize Helium and Download Paywall Configs #

In your app's initialization code (typically in main.dart or your root widget), add the following to download paywall configurations:

import 'package:helium_flutter/helium_flutter.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  
  // Create your callbacks implementation
  PaymentCallbacks paymentCallbacks = PaymentCallbacks();
  
  // Initialize Helium
  final heliumFlutter = HeliumFlutter();
  heliumFlutter.initialize(
    // You'll get this from Helium founders during setup!
    apiKey: "<your-helium-api-key>",
    
    // The callbacks implementation you created earlier
    callbacks: paymentCallbacks,
    
    // If set, a custom API endpoint (usually provided by Helium)
    customAPIEndpoint: "https://api-v2.tryhelium.com/on-launch",
    
    // If set, a custom user ID to use instead of Helium's
    customUserId: "your-custom-user-id", // Optional
    
    // Custom user traits for targeting and personalization
    customUserTraits: {
      "exampleUserTrait": "test_value",
      "subscriptionStatus": "active",
      "userIntent": "upgrade",
      "numericalValue": 3.0,
    }, // Optional
  );
  
  runApp(const MyApp());
}

Passing Custom User Traits

Custom user traits can be any key-value pairs where the value is a serializable type (String, num, bool, etc.). These traits can be used for targeting, personalization, and dynamic content in your paywalls.

Passing in a Custom User ID

By default, Helium generates a UUID per app session to identify users. You can override this with your own custom user ID (e.g., from a 3rd party analytics service) by passing it in the initialize method or by explicitly calling overrideUserId:

// Set a custom user ID
await heliumFlutter.overrideUserId(
  newUserId: "your-custom-user-id", 
  traits: {
    "exampleTrait": "value",
    "userType": "premium"
  }
);

Checking Download Status

After initialization, you can check the status of the paywall configuration download:

String downloadStatus = await heliumFlutter.getDownloadStatus() ?? 'Unknown';

The download status will be one of the following:

  • "notDownloadedYet": The download has not been initiated or is still in progress.
  • "downloadSuccess": The download was successful.
  • "downloadFailure": The download failed.

You can use this to handle different states in your app.

Checking if Paywalls are Loaded

You can also check if paywalls have been loaded successfully:

bool paywallsLoaded = await heliumFlutter.paywallsLoaded() ?? false;

Presenting Paywalls #

There are several ways to present Helium paywalls in your Flutter app:

Via Direct Method Call #

You can present a paywall programmatically using the presentUpsell method:

ElevatedButton(
  onPressed: () async {
    await heliumFlutter.presentUpsell(trigger: 'onboarding');
  },
  child: Text('Show Premium Features'),
),

The trigger parameter is a unique identifier for the paywall trigger point in your app. Helium uses this to track and optimize the paywall for each trigger point.

Via Widget Integration #

You can also use the UpsellViewForTrigger widget to embed a paywall directly in your widget tree:

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: UpsellViewForTrigger(trigger: 'onboarding'),
    );
  }
}

Hiding Paywalls #

To programmatically hide a paywall:

bool hideResult = await heliumFlutter.hideUpsell() ?? false;

Handling Custom Dismissal Actions #

You can implement custom dismissal logic by handling paywall events in your HeliumCallbacks implementation:

@override
Future<void> onPaywallEvent(Map<String, dynamic> heliumPaywallEvent) async {
  final eventType = heliumPaywallEvent['type'];
  
  if (eventType == 'ctaPressed') {
    final ctaName = heliumPaywallEvent['ctaName'];
    final triggerName = heliumPaywallEvent['triggerName'];
    
    if (ctaName == 'dismiss') {
      // Handle custom dismissal logic here
      // For example, navigate back or show a different screen
    }
  }
}

Getting User ID #

To retrieve the Helium user ID:

String userId = await heliumFlutter.getHeliumUserId() ?? 'Unknown';

Testing #

Documentation for testing will be provided separately. After integration, please message us directly to get set up with a test app + in-app test support.

0
likes
150
points
--
downloads

Publisher

unverified uploader

Weekly Downloads

Flutter Paywall SDK for Helium. Remotely build and auto-optimize paywalls (tryhelium.com)

Homepage

Documentation

API reference

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on helium_flutter