Paywall Configuration Issues

0:06:00

Paywall issues typically involve display problems, missing products, or non-functional purchase buttons. This section covers common paywall configuration challenges.

Issue 1: Paywall Not Displaying

Symptoms

  • Paywall view doesn't appear.
  • Blank screen where paywall should be.
  • Crash when trying to show paywall.

Common Causes

  1. No Published Paywall: Paywall exists in draft but not published.
  2. RevenueCatUI Dependency Missing: Haven't imported the UI library.
  3. Paywall Not Linked to Offering: No paywall associated with offering.
  4. Wrong Offering Requested: Code requests offering that has no paywall.

Solution Steps

Step 1: Verify Paywall is Published

  1. Go to RevenueCat dashboard.
  2. Navigate to Paywalls.
  3. Check your paywall status:
    • Draft: Not live yet.
    • Published: Live and available.
  4. If still in draft, click Publish.

Step 2: Verify RevenueCatUI Dependency

iOS (SPM):

swift
// In your code, verify you can import:
import RevenueCat
import RevenueCatUI  // ← Must have this for paywalls

iOS (CocoaPods):

ruby
pod 'RevenueCat'
pod 'RevenueCatUI'  # ← Add this line

Android (Gradle):

kotlin
// Use purchases-ui instead of just purchases
implementation("com.revenuecat.purchases:purchases-ui:9.20.2")

Step 3: Verify Paywall is Linked to Offering

  1. In RevenueCat dashboard, go to Paywalls.
  2. Click on your paywall.
  3. Check the Offering field shows the correct offering identifier.
  4. If not set, edit and select the offering.

Step 4: Check Code Implementation

iOS (SwiftUI):

swift
import RevenueCatUI

struct ContentView: View {
    @State private var showPaywall = false

    var body: some View {
        Button("Show Paywall") {
            showPaywall = true
        }
        .presentPaywallIfNeeded(
            requiredEntitlementIdentifier: "premium",
            isPresented: $showPaywall
        )
    }
}

Android (Compose):

kotlin
import com.revenuecat.purchases.ui.revenuecatui.Paywall

@Composable
fun MyScreen() {
    var showPaywall by remember { mutableStateOf(false) }

    if (showPaywall) {
        Paywall(
            onDismiss = { showPaywall = false }
        )
    }
}

Issue 2: Products Not Showing on Paywall

Symptoms

  • Paywall displays but product cards are empty.
  • Prices show as $0.00 or blank.
  • Product titles/descriptions missing.

Common Causes

  1. Package Identifiers Mismatch: Paywall expects different package identifiers.
  2. Products Not Available: Store products can't be fetched.
  3. Missing Localization: Product info not configured for user's locale.
  4. Offering Empty: No products in the offering.

Solution Steps

Step 1: Verify Package Identifiers Match

  1. In paywall editor, check which package identifiers are used.
  2. Common package identifiers:
    • $rc_monthly.
    • $rc_annual.
    • $rc_lifetime.
  3. In Product Catalog → Offerings, verify your packages use these identifiers.
  4. If using custom identifiers, update paywall to match.

Step 2: Test Product Fetching

swift
// Test if products are being fetched
let offerings = try await Purchases.shared.offerings()

if let offering = offerings.current {
    for package in offering.availablePackages {
        print("Package: \(package.identifier)")
        print("  Product: \(package.storeProduct.localizedTitle)")
        print("  Price: \(package.storeProduct.localizedPriceString)")
    }
} else {
    print("No current offering")
}

If this prints products correctly but paywall doesn't show them, it's a paywall configuration issue.

Step 3: Check Product Localization

For iOS (App Store Connect):

  1. Go to your product in App Store Connect.
  2. Check Localization section.
  3. Add localization for user's language/region.
  4. Provide display name and description.

For Android (Google Play Console):

  1. Go to your product in Google Play Console.
  2. Check Translations.
  3. Add translations for target languages.

Issue 3: Purchase Button Not Working

Symptoms

  • Tapping purchase button does nothing.
  • Button tap shows loading but never completes.
  • Error appears when trying to purchase.

Common Causes

  1. Purchase Delegate Not Set: No handler for purchase completion.
  2. Entitlement Check Failing: User already has entitlement but UI doesn't reflect it.
  3. Transaction Not Finishing: SDK configured to not auto-finish transactions.
  4. Network Issues: Can't communicate with store servers.

Solution Steps

Step 1: Implement Purchase Callback

iOS:

swift
.presentPaywallIfNeeded(
    requiredEntitlementIdentifier: "premium",
    purchaseCompleted: { customerInfo in
        // Handle successful purchase
        print("Purchase completed! Access granted.")
    },
    restoreCompleted: { customerInfo in
        // Handle restore
        print("Restore completed!")
    }
)

Android:

kotlin
Paywall(
    onPurchaseCompleted = { customerInfo ->
        // Handle successful purchase
        Log.d("Paywall", "Purchase completed!")
    },
    onRestoreCompleted = { customerInfo ->
        // Handle restore
        Log.d("Paywall", "Restore completed!")
    },
    onDismiss = { showPaywall = false }
)

Step 2: Verify Auto-Finish is Enabled

Check your SDK configuration ensures transactions finish automatically:

swift
// iOS - this is the default, no configuration needed
Purchases.configure(withAPIKey: "appl_xxx")
kotlin
// Android - verify this is set
val builder = PurchasesConfiguration.Builder(this, "goog_xxx")
Purchases.configure(
    builder
        .purchasesAreCompletedBy(PurchasesAreCompletedBy.REVENUECAT)  // ← Important!
        .build()
)

Step 3: Enable Debug Logging

See what's happening when purchase button is tapped:

swift
// iOS
Purchases.logLevel = .debug
kotlin
// Android
Purchases.logLevel = LogLevel.DEBUG

Common Issues Quick Reference

ProblemPossible CauseSolution
Paywall not displaying Paywall is still in draft status. In RevenueCat dashboard → Paywalls, check the status column. If it shows Draft, open the paywall and click Publish. Only published paywalls are served to the SDK.
Paywall not displaying RevenueCatUI dependency not added. For iOS, add RevenueCatUI via SPM or CocoaPods. For Android, add com.revenuecat.purchases:purchases-ui to your build.gradle. The main SDK does not include paywall UI components.
Paywall not displaying Paywall not linked to an offering. In RevenueCat dashboard → Paywalls, open your paywall and check the Offering field. Select the correct offering identifier. Each paywall must be associated with an offering to be displayed.
Default/fallback paywall shows instead of custom design SDK version doesn't support Paywalls v2. Update to the latest SDK version. Paywalls v2 requires purchases-ios v5.x+ and purchases-android v8.x+. Check your dependency version and update if needed.
Default/fallback paywall shows instead of custom design Paywall named "default" causing a conflict. Rename your paywall to something other than "default" in the RevenueCat dashboard. The name "default" can conflict with internal SDK logic and cause fallback behavior. See community discussion.
Default/fallback paywall shows instead of custom design Missing string localization in paywall editor. Check debug logs for "Missing string localization for property" warnings. In the paywall editor, ensure all text fields are filled in for the user's locale. Missing localizations trigger validation errors and show the fallback paywall.
Product cards are empty on paywall Package identifiers don't match between paywall and offering. In the paywall editor, check which package identifiers are used (e.g., $rc_monthly, $rc_annual). In Product Catalog → Offerings, verify your packages use these same identifiers. Mismatches cause empty product cards.
Product cards are empty on paywall Products not available in user's storefront. Products may not be available in certain regions. In App Store Connect or Google Play Console, check product availability for the tester's country. Add missing regions if needed.
Prices show as $0.00 or blank Store can't resolve pricing for the product. Verify products are active in the store and have pricing configured. On iOS with StoreKit Configuration, ensure each product has a price and locale set. On Android, verify base plans have pricing.
Purchase button does nothing Transaction not finishing automatically. If using custom purchase handling, ensure you're calling Purchases.shared.purchase(package:) and handling the completion. With RevenueCatUI, purchases are handled automatically. Check that finishTransactions is not set to false.
Purchase button does nothing User already has an active entitlement. The SDK may silently succeed if the user already owns the product. Check customerInfo.entitlements.active before showing the paywall. Use Purchases.shared.getCustomerInfo() to verify current entitlement status.
Restore button not working on paywall No previous purchases to restore for the account. Restore only works if the store account has prior purchases. For sandbox testing, use the same sandbox tester that made the original purchase. See community discussion.
Paywall closes immediately after appearing User's entitlement check passes, triggering auto-dismiss. If using PaywallView or PaywallDialog with auto-close on entitlement, the paywall dismisses if the user already has an active subscription. Verify the user's entitlement status before presenting.
Paywall looks different on Android vs iOS Platform-specific rendering differences. Paywall templates may render slightly differently across platforms. Use the Preview feature in the paywall editor to check both iOS and Android layouts. Adjust design elements if needed for cross-platform consistency.
"No available packages" message on paywall Offering has no packages, or default offering not set. In RevenueCat dashboard → Product Catalog → Offerings, verify the offering has packages attached. Set it as the default offering (Actions → Make Default). Ensure products are approved (iOS) or active (Android). See community discussion.
PaywallView doesn't dismiss after purchase (iOS) Sandbox transaction not completing properly. Update to the latest RevenueCat SDK. Test with a fresh sandbox account and restart the device. Ensure Purchases.shared.delegate is properly set. Check debug logs for transaction processing errors. See community discussion.
RevenueCatUI.PaywallError 2 No default offering configured in the dashboard. In RevenueCat dashboard, select an offering and click the triple-dot icon under Actions → Make Default. Verify the offering contains valid packages with products. Republish the paywall. See community discussion.
Paywall references non-existent package Paywall template uses a package (e.g., $rc_annual) not in the offering. Either add the missing package to the offering in the dashboard, or remove the package component from the paywall design. Android is stricter than iOS about enforcing this. See community discussion.

Quick Paywall Troubleshooting Checklist

  • RevenueCatUI dependency added.
  • Paywall published (not draft).
  • Paywall linked to offering.
  • Package identifiers match between paywall and offering.
  • Products are fetchable (test with offerings API).
  • Product localization configured for user's locale.
  • Purchase completion callbacks implemented.
  • Auto-finish transactions enabled.
  • Debug logging enabled.
  • Testing with valid store configuration.