Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@ For documentation-writing guidelines (tone, content conventions, etc.), see `con

## Non-negotiable rules
- **Never deploy without explicit user approval.**
- **Edit source docs only**: update files in `content/docs/**` (and `content/shared/**` if used).
**Never edit `public/**`** (it is generated and will be overwritten).
- **Content vs. engineering changes**:
- **Content changes**: update files in `content/docs/**` (and `content/shared/**` if used).
- **Engineering changes**: you may edit other parts of the repo as needed.
- **Never edit `public/**`** (it is generated and will be overwritten).
- **SDK references first**: if a task needs SDK APIs/changelogs, run `bun run download:references` before writing.
- **SDK reference tables**: use the Fumadocs-style `TypeTable` for parameters/types; do not use `<ParamTable>`.
- **Test**: run `bun run build:cf` and `bun test` after making changes to ensure you didn't break anything

## Common commands (run from repo root)
```bash
Expand Down Expand Up @@ -124,4 +128,4 @@ This clones/pulls SDK repos into `reference/` (gitignored). Use the source to co

## Troubleshooting
- **Build failures**: check MDX syntax; validate `meta.json`; ensure listed pages exist; run `bun run build` for full errors.
- **Dev server issues**: `rm -rf .next`, `bun run clear:cache`, verify port 8293 is free, reinstall dependencies if needed.
- **Dev server issues**: `rm -rf .next`, `bun run clear:cache`, verify port 8293 is free, reinstall dependencies if needed.
1 change: 1 addition & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions cli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "node_modules/@fumadocs/cli/dist/schema/src.json",
"aliases": {
"uiDir": "./components/ui",
"componentsDir": "./components",
"blockDir": "./components",
"cssDir": "./styles",
"libDir": "./lib"
},
"baseDir": "src",
"uiLibrary": "radix-ui",
"commands": {}
}
92 changes: 74 additions & 18 deletions content/docs/android/sdk-reference/PaywallOptions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,80 @@ class PaywallOptions {
```

## Parameters
<ParamTable>
| Property | Type | Description |
|----------|------|-------------|
| `isHapticFeedbackEnabled` | `Boolean` | Enables haptic feedback when users purchase/restore, open links, or close the paywall. Defaults to `true`. |
| `restoreFailed` | `RestoreFailed` | Messaging for the restore-failed alert. |
| `restoreFailed.title` | `String` | Title for restore-failed alert. Defaults to "No Subscription Found". |
| `restoreFailed.message` | `String` | Message for restore-failed alert. Defaults to "We couldn't find an active subscription for your account." |
| `restoreFailed.closeButtonTitle` | `String` | Close button title for restore-failed alert. Defaults to "Okay". |
| `shouldShowPurchaseFailureAlert` | `Boolean` | Shows an alert after a purchase fails. Set to `false` if you handle failures via a `PurchaseController`. Defaults to `true`. |
| `shouldPreload` | `Boolean` | Preloads and caches trigger paywalls and products during SDK initialization. Set to `false` for just-in-time loading. Defaults to `true`. |
| `useCachedTemplates` | `Boolean` | Loads paywall template websites from disk when available. Defaults to `false`. |
| `automaticallyDismiss` | `Boolean` | Automatically dismisses the paywall on successful purchase or restore. Defaults to `true`. |
| `transactionBackgroundView` | `TransactionBackgroundView?` | View shown behind the system payment sheet during a transaction. Use `null` for no view. Defaults to `.SPINNER`. |
| `overrideProductsByName` | `Map<String, String>` | Overrides products on all paywalls using name→identifier mapping (e.g., `"primary"` → `"com.example.premium_monthly"`). |
| `optimisticLoading` | `Boolean` | Hides shimmer optimistically. Defaults to `false`. |
| `timeoutAfter` | `Duration?` | Duration until a paywall timeout is invoked. When not using fallback loading, setting this triggers a timeout instead of retrying. |
| `onBackPressed` | `((PaywallInfo?) -> Boolean)?` | Callback invoked when back button is pressed (requires `reroute_back_button` enabled in paywall settings). Return `true` to consume the back press, `false` to use SDK default behavior. Defaults to `null`. |
</ParamTable>
<TypeTable
type={{
isHapticFeedbackEnabled: {
type: "Boolean",
description: "Enables haptic feedback when users purchase/restore, open links, or close the paywall.",
default: "true",
},
restoreFailed: {
type: "RestoreFailed",
description: "Messaging for the restore-failed alert.",
required: true,
},
"restoreFailed.title": {
type: "String",
description: "Title for restore-failed alert.",
default: "No Subscription Found",
},
"restoreFailed.message": {
type: "String",
description: "Message for restore-failed alert.",
default: "We couldn't find an active subscription for your account.",
},
"restoreFailed.closeButtonTitle": {
type: "String",
description: "Close button title for restore-failed alert.",
default: "Okay",
},
shouldShowPurchaseFailureAlert: {
type: "Boolean",
description: "Shows an alert after a purchase fails. Set to `false` if you handle failures via a `PurchaseController`.",
default: "true",
},
shouldPreload: {
type: "Boolean",
description: "Preloads and caches trigger paywalls and products during SDK initialization. Set to `false` for just-in-time loading.",
default: "true",
},
useCachedTemplates: {
type: "Boolean",
description: "Loads paywall template websites from disk when available.",
default: "false",
},
automaticallyDismiss: {
type: "Boolean",
description: "Automatically dismisses the paywall on successful purchase or restore.",
default: "true",
},
transactionBackgroundView: {
type: "TransactionBackgroundView?",
description: "View shown behind the system payment sheet during a transaction. Use `null` for no view.",
default: ".SPINNER",
},
overrideProductsByName: {
type: "Map<String, String>",
description: "Overrides products on all paywalls using name\u2192identifier mapping (e.g., `\"primary\"` \u2192 `\"com.example.premium_monthly\"`).",
required: true,
},
optimisticLoading: {
type: "Boolean",
description: "Hides shimmer optimistically.",
default: "false",
},
timeoutAfter: {
type: "Duration?",
description: "Duration until a paywall timeout is invoked. When not using fallback loading, setting this triggers a timeout instead of retrying.",
},
onBackPressed: {
type: "((PaywallInfo?) -> Boolean)?",
description: "Callback invoked when back button is pressed (requires `reroute_back_button` enabled in paywall settings). Return `true` to consume the back press, `false` to use SDK default behavior.",
default: "null",
},
}}
/>


## Usage
```kotlin
Expand Down
23 changes: 16 additions & 7 deletions content/docs/android/sdk-reference/PurchaseController.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,21 @@ public interface PurchaseController {
```

## Parameters
<ParamTable>
| Method | Parameters | Return Type | Description |
|--------|------------|-------------|-------------|
| `purchase` | `activity: Activity`, `product: StoreProduct` | `PurchaseResult` | Called when user initiates purchasing. Implement your purchase logic here. Activity is needed for Google Play Billing. |
| `restorePurchases` | None | `RestorationResult` | Called when user initiates restore. Implement your restore logic here. |
</ParamTable>
<TypeTable
type={{
purchase: {
type: "activity: Activity, product: StoreProduct",
description: "Called when user initiates purchasing. Implement your purchase logic here. Activity is needed for Google Play Billing. Returns `PurchaseResult`.",
required: true,
},
restorePurchases: {
type: "None",
description: "Called when user initiates restore. Implement your restore logic here. Returns `RestorationResult`.",
required: true,
},
}}
/>


## Returns / State
- `purchase()` returns a `PurchaseResult` (`.Purchased`, `.Failed(Throwable)`, `.Cancelled`, or `.Pending`)
Expand All @@ -54,4 +63,4 @@ When using a PurchaseController, you must also manage [`subscriptionStatus`](/an

## Usage

For implementation examples and detailed guidance, see [Using RevenueCat](/android/guides/using-revenuecat).
For implementation examples and detailed guidance, see [Using RevenueCat](/android/guides/using-revenuecat).
53 changes: 41 additions & 12 deletions content/docs/android/sdk-reference/SuperwallDelegate.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,46 @@ public interface SuperwallDelegateJava {
## Parameters
All methods are optional to implement. Key methods include:

<ParamTable>
| Method | Parameters | Description |
|--------|------------|-------------|
| `subscriptionStatusDidChange` | `from`, `to` | Called when subscription status changes. |
| `handleSuperwallEvent` | `eventInfo` | Called for all internal analytics events. Use for tracking in your own analytics. |
| `handleCustomPaywallAction` | `name` | Called when user taps elements with `data-pw-custom` tags. |
| `willPresentPaywall` | `paywallInfo` | Called before paywall presentation. |
| `didPresentPaywall` | `paywallInfo` | Called after paywall presentation. |
| `willDismissPaywall` | `paywallInfo` | Called before paywall dismissal. |
| `didDismissPaywall` | `paywallInfo` | Called after paywall dismissal. |
</ParamTable>
<TypeTable
type={{
subscriptionStatusDidChange: {
type: "from: SubscriptionStatus, to: SubscriptionStatus",
description: "Called when subscription status changes.",
required: true,
},
handleSuperwallEvent: {
type: "eventInfo: SuperwallEventInfo",
description: "Called for all internal analytics events. Use for tracking in your own analytics.",
required: true,
},
handleCustomPaywallAction: {
type: "name: String",
description: "Called when user taps elements with `data-pw-custom` tags.",
required: true,
},
willPresentPaywall: {
type: "paywallInfo: PaywallInfo",
description: "Called before paywall presentation.",
required: true,
},
didPresentPaywall: {
type: "paywallInfo: PaywallInfo",
description: "Called after paywall presentation.",
required: true,
},
willDismissPaywall: {
type: "paywallInfo: PaywallInfo",
description: "Called before paywall dismissal.",
required: true,
},
didDismissPaywall: {
type: "paywallInfo: PaywallInfo",
description: "Called after paywall dismissal.",
required: true,
},
}}
/>


## Returns / State
All delegate methods return `Unit`. They provide information about Superwall events and state changes.
Expand Down Expand Up @@ -172,4 +201,4 @@ public class MainActivity extends AppCompatActivity implements SuperwallDelegate
updateUI(to);
}
}
```
```
71 changes: 56 additions & 15 deletions content/docs/android/sdk-reference/SuperwallOptions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,61 @@ public class SuperwallOptions {
```

## Parameters
<ParamTable>
| Property | Type | Description |
|----------|------|-------------|
| `paywalls` | [`PaywallOptions`](/android/sdk-reference/PaywallOptions) | Controls paywall presentation, preload, and alert behavior. |
| `shouldObservePurchases` | `Boolean` | Set to `true` to have Superwall observe Google Play purchases you make outside the SDK. |
| `networkEnvironment` | `NetworkEnvironment` | Overrides the API environment. **Only change if instructed by Superwall.** |
| `isExternalDataCollectionEnabled` | `Boolean` | Allows Superwall to send non-paywall analytics events to the backend. Defaults to `true`. |
| `localeIdentifier` | `String?` | Overrides the locale used for rule evaluation (e.g., `"en_GB"`). |
| `isGameControllerEnabled` | `Boolean` | Forwards game controller events to paywalls. |
| `passIdentifiersToPlayStore` | `Boolean` | When `true`, Google Play receives the raw `userId` as `obfuscatedExternalAccountId`; otherwise Superwall sends a SHA-256 hash. |
| `enableExperimentalDeviceVariables` | `Boolean` | Enables experimental device variables (subject to change). |
| `logging` | `Logging` | Sets log level and scopes printed to Logcat. |
| `useMockReviews` | `Boolean` | Shows mock Google Play review dialogs for testing. |
</ParamTable>
<TypeTable
type={{
paywalls: {
type: "PaywallOptions",
typeDescriptionLink: "/android/sdk-reference/PaywallOptions",
description: "Controls paywall presentation, preload, and alert behavior.",
required: true,
},
shouldObservePurchases: {
type: "Boolean",
description: "Set to `true` to have Superwall observe Google Play purchases you make outside the SDK.",
required: true,
},
networkEnvironment: {
type: "NetworkEnvironment",
description: "Overrides the API environment. **Only change if instructed by Superwall.**",
required: true,
},
isExternalDataCollectionEnabled: {
type: "Boolean",
description: "Allows Superwall to send non-paywall analytics events to the backend.",
default: "true",
},
localeIdentifier: {
type: "String?",
description: "Overrides the locale used for rule evaluation (e.g., `\"en_GB\"`).",
},
isGameControllerEnabled: {
type: "Boolean",
description: "Forwards game controller events to paywalls.",
required: true,
},
passIdentifiersToPlayStore: {
type: "Boolean",
description: "When `true`, Google Play receives the raw `userId` as `obfuscatedExternalAccountId`; otherwise Superwall sends a SHA-256 hash.",
required: true,
},
enableExperimentalDeviceVariables: {
type: "Boolean",
description: "Enables experimental device variables (subject to change).",
required: true,
},
logging: {
type: "Logging",
description: "Sets log level and scopes printed to Logcat.",
required: true,
},
useMockReviews: {
type: "Boolean",
description: "Shows mock Google Play review dialogs for testing.",
required: true,
},
}}
/>


## How `passIdentifiersToPlayStore` affects Google Play
Superwall always calls `BillingFlowParams.Builder.setObfuscatedAccountId(Superwall.instance.externalAccountId)` when launching a billing flow.
Expand All @@ -84,4 +125,4 @@ Superwall.configure(
```

## Related
- [`PaywallOptions`](/android/sdk-reference/PaywallOptions)
- [`PaywallOptions`](/android/sdk-reference/PaywallOptions)
37 changes: 28 additions & 9 deletions content/docs/android/sdk-reference/advanced/PaywallBuilder.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,34 @@ class PaywallBuilder(private val placement: String) {
```

## Parameters
<ParamTable>
| Name | Type | Description |
|------|------|-------------|
| `placement` | `String` | The name of the placement as defined on the Superwall dashboard. |
| `params` | `Map<String, Any>?` | Optional parameters to pass with your placement for audience filters. Keys beginning with `$` are reserved and will be dropped. |
| `overrides` | `PaywallOverrides?` | Optional overrides for products and presentation style. |
| `delegate` | `PaywallViewCallback` | A delegate to handle user interactions with the retrieved PaywallView. |
| `activity` | `Activity` | The activity context required for the PaywallView. |
</ParamTable>
<TypeTable
type={{
placement: {
type: "String",
description: "The name of the placement as defined on the Superwall dashboard.",
required: true,
},
params: {
type: "Map<String, Any>?",
description: "Optional parameters to pass with your placement for audience filters. Keys beginning with `$` are reserved and will be dropped.",
},
overrides: {
type: "PaywallOverrides?",
description: "Optional overrides for products and presentation style.",
},
delegate: {
type: "PaywallViewCallback",
description: "A delegate to handle user interactions with the retrieved PaywallView.",
required: true,
},
activity: {
type: "Activity",
description: "The activity context required for the PaywallView.",
required: true,
},
}}
/>


## Returns / State
Returns a `Result<PaywallView>` that you can add to your view hierarchy. If presentation should be skipped, returns a failure result.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,16 @@ public void setSubscriptionStatus(SubscriptionStatus status)
```

## Parameters
<ParamTable>
| Name | Type | Description |
|------|------|-------------|
| `status` | `SubscriptionStatus` | The subscription status to set. Can be `SubscriptionStatus.Unknown`, `SubscriptionStatus.Active(entitlements)`, or `SubscriptionStatus.Inactive`. |
</ParamTable>
<TypeTable
type={{
status: {
type: "SubscriptionStatus",
description: "The subscription status to set. Can be `SubscriptionStatus.Unknown`, `SubscriptionStatus.Active(entitlements)`, or `SubscriptionStatus.Inactive`.",
required: true,
},
}}
/>


## Returns / State
This function returns `Unit`. The new status will be reflected in the [`subscriptionStatus`](/android/sdk-reference/subscriptionStatus) StateFlow and will trigger the [`SuperwallDelegate.subscriptionStatusDidChange`](/android/sdk-reference/SuperwallDelegate) callback.
Expand Down
Loading