Breaking Changes in v4:
presentUpsell() renamed to presentPaywall() with new signature
hideUpsell() renamed to hidePaywall()
hideAllUpsells() renamed to hideAllPaywalls()
dontShowIfAlreadyEntitled now defaults to true
- Initialize parameters moved to
Helium.identity and Helium.config namespaces
HeliumFallbackConfig removed - use Helium.config properties instead
What’s New:
- Simplified
initialize() - just pass context and API key
- Automatic
PlayStorePaywallDelegate setup if not explicitly configured
- Cleaner namespaced APIs:
Helium.identity, Helium.config
- New
PaywallPresentationConfig consolidates presentation options
- New
PaywallNotShownReason for handling paywall failures
Installation Update
Update your version constraint to 4.x:
// app/build.gradle.kts
dependencies {
implementation("com.tryhelium.paywall:core:4.0.0")
}
// app/build.gradle.kts
dependencies {
implementation("com.tryhelium.paywall:compose-ui:4.0.0")
}
// app/build.gradle.kts
dependencies {
implementation("com.tryhelium.paywall:revenue-cat:4.0.0")
}
Then sync your Gradle files.
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.
v0 (many parameters):
val heliumPaywallDelegate = PlayStorePaywallDelegate(this)
Helium.initialize(
context = this,
apiKey = "...",
heliumPaywallDelegate = heliumPaywallDelegate,
customUserId = "user-123",
customUserTraits = HeliumUserTraits(
traits = mapOf("plan" to HeliumUserTraitsArgument.StringParam("free"))
),
fallbackConfig = HeliumFallbackConfig.withFallbackBundle(
fallbackBundleName = "fallback.json"
)
)
v4 (simplified):
// Set up user identification
Helium.identity.userId = "user-123"
Helium.identity.setUserTraits(HeliumUserTraits(
traits = mapOf("plan" to HeliumUserTraitsArgument.StringParam("free"))
))
// Set up configuration (if needed)
Helium.config.customFallbacksFileName = "fallback.json"
// Note: PlayStorePaywallDelegate is auto-created if not set
// Helium.config.heliumPaywallDelegate = PlayStorePaywallDelegate(this)
// Initialize with just context and API key
Helium.initialize(
context = this,
apiKey = "..."
)
Set identity and configuration values before calling initialize() for best results.
presentUpsell to presentPaywall
The method has been renamed and the signature has changed significantly. Parameters are now consolidated into PaywallPresentationConfig.
Helium.presentUpsell(
context = this,
trigger = "premium",
activityContext = activity,
dontShowIfAlreadyEntitled = true,
eventListener = myListener
)
Full Example with All Parameters
v4:
Helium.presentPaywall(
trigger = "premium",
config = PaywallPresentationConfig(
fromActivityContext = activity, // optional - SDK auto-tracks activities
customPaywallTraits = HeliumUserTraits(...),
dontShowIfAlreadyEntitled = true, // defaults to true
disableSystemBackNavigation = false,
presentationStyle = HeliumPresentationStyle.SLIDE_UP,
fullscreen = false
),
onEntitled = {
// User is now entitled (purchased or restored)
},
eventListener = myListener,
onPaywallNotShown = { reason ->
when (reason) {
is PaywallNotShownReason.TargetingHoldout -> {
// User is in holdout group
}
is PaywallNotShownReason.AlreadyEntitled -> {
// User already has access
}
is PaywallNotShownReason.Error -> {
// Handle error, check reason.unavailableReason
}
}
}
)
dontShowIfAlreadyEntitled now defaults to true in v4. Set it to false explicitly if you want to show paywalls to entitled users.
Method Renames
| v0 | v4 |
|---|
Helium.presentUpsell() | Helium.presentPaywall() |
Helium.hideUpsell() | Helium.hidePaywall() |
Helium.hideAllUpsells() | Helium.hideAllPaywalls() |
API Namespace Migration
Helium.identity
| v0 | v4 |
|---|
initialize(customUserId: ...) | Helium.identity.userId = ... |
initialize(customUserTraits: ...) | Helium.identity.setUserTraits(...) |
Helium.config
| v0 | v4 |
|---|
initialize(heliumPaywallDelegate: ...) | Helium.config.heliumPaywallDelegate = ... |
initialize(fallbackConfig: ...) | See Fallback Changes below |
Fallback Changes
v4 removes HeliumFallbackConfig and simplifies fallback configuration.
What’s Changed
- No more
HeliumFallbackConfig class - Use Helium.config properties directly
- No more fallback views - Use fallback bundles exclusively
- No more per-trigger config - Use global settings only
- Automatic detection - SDK auto-detects
helium-fallbacks.json in your assets
Migration
v0:
Helium.initialize(
// ... other parameters
fallbackConfig = HeliumFallbackConfig(
fallbackBundleName = "my-fallback.json",
fallbackView = myFallbackView,
useLoadingState = true,
loadingBudgetInMs = 5000,
perTriggerLoadingConfig = mapOf(...)
)
)
v4:
// Option 1: Automatic (recommended)
// Just add helium-fallbacks.json to your assets - SDK finds it automatically
// Option 2: Custom file name
Helium.config.customFallbacksFileName = "my-fallback.json"
Helium.config.defaultLoadingBudgetInMs = 5000
Helium.config.defaultLoadingView = myLoadingView // optional
Helium.initialize(
context = this,
apiKey = "..."
)
Configuration Property Mapping
| v0 (HeliumFallbackConfig) | v4 (Helium.config) |
|---|
fallbackBundleName | customFallbacksFileName |
loadingBudgetInMs | defaultLoadingBudgetInMs |
loadingView | defaultLoadingView |
useLoadingState | Computed from defaultLoadingBudgetInMs > 0 |
perTriggerLoadingConfig | Removed |
fallbackPerTrigger | Removed |
fallbackView | Removed (use fallback bundles only) |
New Classes
PaywallPresentationConfig
Consolidates all paywall presentation options into a single data class:
data class PaywallPresentationConfig(
val fromActivityContext: Activity? = null,
val customPaywallTraits: HeliumUserTraits? = null,
val dontShowIfAlreadyEntitled: Boolean = true,
val disableSystemBackNavigation: Boolean = false,
val presentationStyle: HeliumPresentationStyle = HeliumPresentationStyle.SLIDE_UP,
val fullscreen: Boolean = false
) {
companion object {
val Default: PaywallPresentationConfig
}
}
PaywallNotShownReason
Sealed class for handling paywall presentation failures:
sealed class PaywallNotShownReason {
data object TargetingHoldout : PaywallNotShownReason()
data object AlreadyEntitled : PaywallNotShownReason()
data class Error(val unavailableReason: PaywallUnavailableReason?) : PaywallNotShownReason()
}
Quick Migration Checklist
Use this checklist to ensure you’ve covered all migration steps:
- Update SDK to 4.x
- Move user ID/traits to
Helium.identity.* before initialize()
- Move delegate to
Helium.config.* before initialize() (or let SDK auto-create)
- Replace
presentUpsell() with presentPaywall() and update parameters
- Replace
hideUpsell() with hidePaywall()
- Replace
hideAllUpsells() with hideAllPaywalls()
- Remove
HeliumFallbackConfig usage, migrate to Helium.config.* properties
- Set up fallback bundle (download from dashboard, add as
helium-fallbacks.json)
- Add
onPaywallNotShown handler to presentPaywall() calls
- Test paywall presentation and purchases
Need Help?