Skip to main content
Breaking Changes in v4:
  • presentUpsell() renamed to presentPaywall() with required onPaywallNotShown handler
  • dontShowIfAlreadyEntitled now defaults to true
  • Initialize parameters moved to Helium.identify and Helium.config namespaces
  • Fallback views removed - use fallback bundles only
What’s New:
  • Simplified initialize() - just pass your API key
  • Automatic fallback bundle detection (helium-fallbacks.json)
  • Cleaner namespaced APIs: Helium.identify, Helium.config, Helium.experiments, Helium.entitlements
  • New HeliumPaywall SwiftUI component for embedded paywalls
  • HeliumRevenueCat is now a separate SPM package (CocoaPods unchanged)

Installation Update

Update your version constraint to ~> 4.0:
Update the Dependency Rule in Xcode to allow 4.x versions, or remove and re-add the package with the new version constraint.
RevenueCat users: HeliumRevenueCat is now a separate SPM package. After updating to v4, you may see a build error:
Product 'HeliumRevenueCat' not found in package 'helium-swift'
To fix this:
  1. In your target’s Frameworks, Libraries, and Embedded Content, remove the broken HeliumRevenueCat reference
  2. Go to Package Dependencies and add the new package:
    https://github.com/cloudcaptainai/helium-swift-revenuecat.git
    
  3. Add the HeliumRevenueCat product from the new package to your app’s main target

Initialize Migration

The biggest change in v4 is the simplified initialization. Configuration that was previously passed to initialize() is now set on dedicated namespaces beforehand. v3 (many parameters):
// Deprecated v3 initialize
Helium.shared.initialize(
    apiKey: "...",
    heliumPaywallDelegate: RevenueCatDelegate(),
    customUserId: "user-123",
    customUserTraits: HeliumUserTraits(["plan": "free"]),
    fallbackConfig: .withFallbackBundle(bundleURL)
)
v4 (simplified):
// Set up user identification
Helium.identify.userId = "user-123"
Helium.identify.setUserTraits(HeliumUserTraits(["plan": "free"]))
// If using RevenueCat
Helium.identify.revenueCatAppUserId = Purchases.shared.appUserID 

// Set up advanced configuration (if needed)
Helium.config.customFallbacksURL = Bundle.main.url(
    forResource: "fallback-bundle-2026-01-25",
    withExtension: "json"
)
Helium.config.purchaseDelegate = RevenueCatDelegate()

// Initialize with just API key
Helium.shared.initialize(apiKey: "...")
Set identity and configuration values before calling initialize() for best results.
See the quickstart for more details.

presentUpsell to presentPaywall

The method has been renamed and now requires an onPaywallNotShown handler.
Helium.shared.presentUpsell(trigger: "premium")

Full Example with All Parameters

v4:
Helium.shared.presentPaywall(
    trigger: "premium",
    config: PaywallPresentationConfig(
        presentFromViewController: viewController,
        customPaywallTraits: ["source": "settings"],
        dontShowIfAlreadyEntitled: true, // defaults to true
        loadingBudget: nil, // use default
    ),
    eventHandlers: PaywallEventHandlers()
        .onPurchaseSucceeded { event in
            print("Purchased!")
        },
    onEntitled: {
        // User is now entitled (purchased or restored)
    }
) { paywallNotShownReason in
    switch paywallNotShownReason {
    case .targetingHoldout:
        break
    case .alreadyEntitled:
        // User already has access
        break
    default:
        // Handle rare failure cases
        break
    }
}
dontShowIfAlreadyEntitled now defaults to true in v4. Set it to false explicitly if you want to show paywalls to entitled users.

API Namespace Migration

Helium.identify

v3v4
initialize(customUserId:)Helium.identify.userId = ...
overrideUserId()Helium.identify.userId = ...
getHeliumUserId()Helium.identify.userId
setAppAttributionToken()Helium.identify.appAccountToken = ...
setRevenueCatAppUserId()Helium.identify.revenueCatAppUserId = ...

Helium.config

v3v4
initialize(heliumPaywallDelegate:)Helium.config.purchaseDelegate = ...
setLightDarkModeOverride()Helium.config.lightDarkModeOverride = ...
Helium.restorePurchaseConfigHelium.config.restorePurchasesDialog

Helium.experiments

v3v4
getExperimentInfoForTrigger()Helium.experiments.infoForTrigger()
enrolledExperiments()Helium.experiments.enrolled()
allExperiments()Helium.experiments.all()

Helium.entitlements

v3v4
hasAnyEntitlement()Helium.entitlements.hasAny()
hasAnyActiveSubscription()Helium.entitlements.hasAnyActiveSubscription()
hasEntitlementForPaywall()Helium.entitlements.hasForPaywall()
hasActiveEntitlementFor()Helium.entitlements.hasActiveFor()
purchasedProductIds()Helium.entitlements.purchasedProductIds()
activeSubscriptions()Helium.entitlements.activeSubscriptions()

Fallback Changes

v4 removes fallback views and simplifies fallback configuration.

What’s Changed

  • No more fallback views - Use fallback bundles exclusively
  • Automatic detection - SDK auto-detects helium-fallbacks.json in your main bundle
  • Optional override - Use Helium.config.customFallbacksURL if needed

Migration

v3:
let fallbackConfig = HeliumFallbackConfig(
    fallbackView: YourFallbackView(),
    fallbackBundle: Bundle.main.url(
        forResource: "fallback-bundle",
        withExtension: "json"
    )
)

Helium.shared.initialize(
    apiKey: "...",
    fallbackConfig: fallbackConfig
)
v4:
// Option 1: Automatic (recommended)
// Just add helium-fallbacks.json to your bundle - SDK finds it automatically

// Option 2: Custom location
Helium.config.customFallbacksURL = Bundle.main.url(
    forResource: "my-fallbacks",
    withExtension: "json"
)

Helium.shared.initialize(apiKey: "...")
Download your fallbacks from the Helium dashboard. See the Fallback Bundle Guide for details.

Embedded Paywall Views

The SwiftUI view for embedding paywalls has been replaced.
let paywallView = Helium.shared.upsellViewForTrigger("premium")
See ways to show a paywall for more information.

Removed APIs

The following APIs have been removed in v4:
Removed APIReplacement
getHeliumExperimentInfo() (map version)Helium.experiments.all()
HeliumFallbackConfig classUse Helium.config.customFallbacksURL
All fallback* parameters from initializeAdd helium-fallbacks.json to bundle
upsellViewForTrigger()HeliumPaywall component

Quick Migration Checklist

Use this checklist to ensure you’ve covered all migration steps:
  • Update SDK to 4.x (~> 4.0)
  • Move user ID/traits to Helium.identify.* before initialize()
  • Move delegate/config to Helium.config.* before initialize()
  • Replace presentUpsell() with presentPaywall() and add required handler
  • Set up fallback bundle (download from dashboard, add as helium-fallbacks.json)
  • Update experiment calls to Helium.experiments.*
  • Update entitlement calls to Helium.entitlements.*
  • Replace upsellViewForTrigger() with HeliumPaywall component
  • Test paywall presentation and purchases

Need Help?