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
17 changes: 17 additions & 0 deletions content/docs/expo/changelog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ description: "Release notes for the Superwall Expo SDK"

# Changelog

## 1.1.0

### Minor Changes

- 0c3396d: Bump native SDKs and expose new APIs.

**iOS — SuperwallKit 4.14.1 → 4.15.1**

- New `paywallPageView` event for multi-page paywall navigation tracking (with `PageViewData` payload).
- `PaywallInfo.presentationId` is now bridged so events within a single presentation can be correlated.
- Custom store products are fully bridged: `Product` now carries `store` (`APP_STORE` | `STRIPE` | `PADDLE` | `PLAY_STORE` | `SUPERWALL` | `CUSTOM` | `OTHER`) plus per-store identifier objects (`appStoreProduct`, `stripeProduct`, `paddleProduct`, `customProduct`). `onPurchase` also receives `store` so JS can route `CUSTOM` products to its own purchase logic instead of StoreKit.

**Android — Superwall-Android 2.7.11 → 2.7.12**

- Bridges the new `customerInfo` field on `PaywallInfo` (subscriptions, non-subscriptions, entitlements, userId).
- Picks up new intro-offer eligibility logic for Stripe/Paddle products and bottom-sheet dismiss fix on newer Samsung devices.

## 1.0.11

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion content/docs/expo/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ If you have feedback on any of our docs, please leave a rating and message at th

If you have any issues please [open an issue on GitHub](https://github.com/superwall/expo-superwall/issues).

<SdkLatestVersion version="v1.0.11" repoUrl="https://github.com/superwall/expo-superwall" />
<SdkLatestVersion version="v1.1.0" repoUrl="https://github.com/superwall/expo-superwall" />
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ onPurchase: async (params) => {
description: "App Store product identifier.",
required: true,
},
store: {
type: "ProductStore?",
description: "The store backing the product. When `\"CUSTOM\"`, the product is not backed by StoreKit and your purchase handler must implement the purchase itself. See ProductStore for all possible values.",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clarify iOS productId is not App Store-only

Adding store with a "CUSTOM" value means OnPurchaseParams (iOS) can now represent non-StoreKit products, but this section still describes productId as an App Store identifier. In custom-store flows, that description is incorrect and can cause integrators to treat productId as a StoreKit SKU when it may be a custom identifier, which undermines the new routing behavior documented here.

Useful? React with 👍 / 👎.

},
}}
/>

Expand Down Expand Up @@ -132,6 +136,40 @@ onPurchase: async (params) => {
}}
/>

### ProductStore
<TypeTable
type={{
APP_STORE: {
type: "\"APP_STORE\"",
description: "Apple App Store product.",
},
PLAY_STORE: {
type: "\"PLAY_STORE\"",
description: "Google Play Store product.",
},
STRIPE: {
type: "\"STRIPE\"",
description: "Stripe-managed product.",
},
PADDLE: {
type: "\"PADDLE\"",
description: "Paddle-managed product.",
},
SUPERWALL: {
type: "\"SUPERWALL\"",
description: "Manually granted entitlement from Superwall.",
},
CUSTOM: {
type: "\"CUSTOM\"",
description: "Custom product that your purchase handler must purchase outside StoreKit or Google Play Billing.",
},
OTHER: {
type: "\"OTHER\"",
description: "Unknown or unsupported store.",
},
}}
/>

### PurchaseResult
<TypeTable
type={{
Expand Down
298 changes: 298 additions & 0 deletions content/docs/expo/sdk-reference/hooks/useSuperwallEvents.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,304 @@ The `useSuperwallEvents` hook provides a low-level way to subscribe to _any_ nat
}}
/>

### SuperwallEventInfo

<TypeTable
type={{
event: {
type: "SuperwallEvent",
description: "The native Superwall event payload. For multi-page paywalls, this can be a PaywallPageViewEvent.",
required: true,
},
params: {
type: "Record<string, any>",
description: "Additional payload metadata for the event.",
required: true,
},
}}
/>

### PageViewData

<TypeTable
type={{
pageNodeId: {
type: "string",
description: "Unique identifier for the page node.",
required: true,
},
flowPosition: {
type: "number",
description: "Zero-based page position in the paywall flow.",
required: true,
},
pageName: {
type: "string",
description: "Display name for the page.",
required: true,
},
navigationNodeId: {
type: "string",
description: "Unique identifier for the navigation node.",
required: true,
},
previousPageNodeId: {
type: "string?",
description: "Previous page node identifier, when available.",
},
previousFlowPosition: {
type: "number?",
description: "Previous page position in the paywall flow, when available.",
},
navigationType: {
type: "\"entry\" | \"forward\" | \"back\" | \"auto_transition\" | string",
description: "How the user reached the page.",
required: true,
},
timeOnPreviousPageMs: {
type: "number?",
description: "Time spent on the previous page in milliseconds, when available.",
},
}}
/>

### PaywallPageViewEvent

<TypeTable
type={{
event: {
type: "\"paywallPageView\"",
description: "Identifies the multi-page paywall navigation event.",
required: true,
},
paywallInfo: {
type: "PaywallInfo",
description: "Paywall metadata associated with the page view.",
required: true,
},
data: {
type: "PageViewData",
description: "Details for the page the user navigated to.",
required: true,
},
}}
/>

### PaywallInfo

<TypeTable
type={{
identifier: {
type: "string",
description: "Paywall identifier from the Superwall dashboard.",
required: true,
},
name: {
type: "string",
description: "Paywall name from the Superwall dashboard.",
required: true,
},
url: {
type: "string",
description: "Hosted paywall URL.",
required: true,
},
presentationId: {
type: "string?",
description: "Identifier used to correlate events within one paywall presentation lifecycle.",
},
products: {
type: "Product[]",
description: "Products available on the paywall.",
required: true,
},
productIds: {
type: "string[]",
description: "Product identifiers available on the paywall.",
required: true,
},
presentedBy: {
type: "string",
description: "Source that initiated the paywall presentation.",
required: true,
},
state: {
type: "Record<string, any>",
description: "Paywall state captured on dismiss.",
required: true,
},
customerInfo: {
type: "CustomerInfo?",
description: "Android 2.7.12+ snapshot of the user's subscription and entitlement state. Undefined on iOS.",
},
}}
/>

### Product

<TypeTable
type={{
id: {
type: "string",
description: "Product identifier.",
required: true,
},
name: {
type: "string?",
description: "Product display name, when available.",
},
entitlements: {
type: "Entitlement[]",
description: "Entitlements granted by purchasing this product.",
required: true,
},
store: {
type: "ProductStore?",
description: "Store that backs this product. Use `\"CUSTOM\"` to route purchases to your own purchase logic.",
},
appStoreProduct: {
type: "{ id: string }?",
description: "App Store product identifier data when `store` is `\"APP_STORE\"`.",
},
stripeProduct: {
type: "{ id: string; trialDays?: number }?",
description: "Stripe product identifier data when `store` is `\"STRIPE\"`.",
},
paddleProduct: {
type: "{ id: string }?",
description: "Paddle product identifier data when `store` is `\"PADDLE\"`.",
},
customProduct: {
type: "{ id: string }?",
description: "Custom product identifier data when `store` is `\"CUSTOM\"`.",
},
}}
/>

### CustomerInfo (Android)

<TypeTable
type={{
userId: {
type: "string",
description: "User ID at the time the snapshot was taken.",
required: true,
},
subscriptions: {
type: "SubscriptionTransaction[]",
description: "Subscription transactions ordered by purchase date.",
required: true,
},
nonSubscriptions: {
type: "NonSubscriptionTransaction[]",
description: "Non-subscription transactions ordered by purchase date.",
required: true,
},
entitlements: {
type: "Entitlement[]",
description: "Entitlements available to the user.",
required: true,
},
}}
/>

### SubscriptionTransaction (Android)

<TypeTable
type={{
transactionId: {
type: "string",
description: "Unique transaction identifier.",
required: true,
},
productId: {
type: "string",
description: "Subscription product identifier.",
required: true,
},
purchaseDate: {
type: "string",
description: "ISO-8601 purchase timestamp.",
required: true,
},
willRenew: {
type: "boolean",
description: "Whether the subscription is set to renew.",
required: true,
},
isRevoked: {
type: "boolean",
description: "Whether the transaction has been revoked.",
required: true,
},
isInGracePeriod: {
type: "boolean",
description: "Whether the subscription is in a billing grace period.",
required: true,
},
isInBillingRetryPeriod: {
type: "boolean",
description: "Whether the subscription is in a billing retry period.",
required: true,
},
isActive: {
type: "boolean",
description: "Whether the subscription is currently active.",
required: true,
},
expirationDate: {
type: "string | null",
description: "ISO-8601 expiration timestamp, or null for non-renewing subscriptions.",
},
store: {
type: "string",
description: "Store the transaction came from, such as `\"PLAY_STORE\"`.",
required: true,
},
offerType: {
type: "\"trial\" | \"code\" | \"subscription\" | \"promotional\" | \"winback\" | \"revoked\"",
description: "Offer type applied to the subscription, when available.",
},
}}
/>

### NonSubscriptionTransaction (Android)

<TypeTable
type={{
transactionId: {
type: "string",
description: "Unique transaction identifier.",
required: true,
},
productId: {
type: "string",
description: "Product identifier.",
required: true,
},
purchaseDate: {
type: "string",
description: "ISO-8601 purchase timestamp.",
required: true,
},
isConsumable: {
type: "boolean",
description: "Whether the purchase is consumable.",
required: true,
},
isRevoked: {
type: "boolean",
description: "Whether the transaction has been revoked.",
required: true,
},
store: {
type: "string",
description: "Store the transaction came from, such as `\"PLAY_STORE\"`.",
required: true,
},
}}
/>

## Returned Values

This hook does not return any values (`void`). Its purpose is to set up and tear down event listeners.
Expand Down
2 changes: 1 addition & 1 deletion content/docs/expo/sdk-reference/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ If you have feedback on any of our docs, please leave a rating and message at th

If you have any issues with the SDK, please [open an issue on GitHub](https://github.com/superwall/expo-superwall/issues).

<SdkLatestVersion version="v1.0.11" repoUrl="https://github.com/superwall/expo-superwall" />
<SdkLatestVersion version="v1.1.0" repoUrl="https://github.com/superwall/expo-superwall" />
Loading