From c9fcef3d67978a5aa78039a3dc3f2755b8e52368 Mon Sep 17 00:00:00 2001 From: Jordan Morgan Date: Tue, 20 Jan 2026 14:36:12 -0600 Subject: [PATCH 1/3] Make AL requirement clear --- content/docs/integrations/figma-plugin.mdx | 8 +++++++- next-env.d.ts | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/content/docs/integrations/figma-plugin.mdx b/content/docs/integrations/figma-plugin.mdx index 3b4af61..15f8927 100644 --- a/content/docs/integrations/figma-plugin.mdx +++ b/content/docs/integrations/figma-plugin.mdx @@ -3,7 +3,13 @@ title: "Figma Plugin" description: "The Superwall Figma Plugin allows designers to convert Figma designs into fully functional paywalls with one click." --- -The Superwall Figma Import plugin can automatically import Figma designs into the paywall editor. Each component is imported individually, preserving your design structure. To see it in action, check out the video demo: +The Superwall Figma Import plugin can automatically import Figma designs into the paywall editor. Each component is imported individually, preserving your design structure. + + +Auto Layout is required in your Figma files for the import to work. + + +To see it in action, check out the video demo: diff --git a/next-env.d.ts b/next-env.d.ts index 9edff1c..c4b7818 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next/types/routes.d.ts"; +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. From 249fc80ba1ad273cc0f642bd6e457f7ec3526c58 Mon Sep 17 00:00:00 2001 From: Jordan Morgan Date: Tue, 20 Jan 2026 14:52:34 -0600 Subject: [PATCH 2/3] Copy and paste in editor. --- .../dashboard-creating-paywalls/paywall-editor-layout.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content/docs/dashboard/dashboard-creating-paywalls/paywall-editor-layout.mdx b/content/docs/dashboard/dashboard-creating-paywalls/paywall-editor-layout.mdx index 4623cda..aad4cad 100644 --- a/content/docs/dashboard/dashboard-creating-paywalls/paywall-editor-layout.mdx +++ b/content/docs/dashboard/dashboard-creating-paywalls/paywall-editor-layout.mdx @@ -75,6 +75,8 @@ From left to right, here's what each icon does: - **Square on Square:** Copies the component. - **Plus sign:** Adds a new component. +You can also select a component directly in the **live preview canvas** and use `⌘+C` (Mac) or `Ctrl+C` (Windows) to copy it, then `⌘+V` or `Ctrl+V` to paste it. + To **rename** a component, **double click** on its current name to edit it. ### Context menu From d60e7bed9d4b04107209c4911a632758370b134c Mon Sep 17 00:00:00 2001 From: Jordan Morgan Date: Tue, 20 Jan 2026 15:24:34 -0600 Subject: [PATCH 3/3] More docs --- .../sdk-reference/SuperwallDelegate.mdx | 16 +++++++++++ .../paywall-editor-notifications.mdx | 28 ++++++++++++++++--- .../paywall-editor-styling-elements.mdx | 1 + .../hooks/useSuperwallEvents.mdx | 8 ++++++ .../flutter/sdk-reference/PaywallOptions.mdx | 4 +-- 5 files changed, 51 insertions(+), 6 deletions(-) diff --git a/content/docs/android/sdk-reference/SuperwallDelegate.mdx b/content/docs/android/sdk-reference/SuperwallDelegate.mdx index 45cc0ee..631c75c 100644 --- a/content/docs/android/sdk-reference/SuperwallDelegate.mdx +++ b/content/docs/android/sdk-reference/SuperwallDelegate.mdx @@ -45,6 +45,8 @@ interface SuperwallDelegate { info: Map?, error: Throwable? ) {} + + fun userAttributesDidChange(newAttributes: Map) {} } ``` @@ -104,6 +106,11 @@ All methods are optional to implement. Key methods include: description: "Called after paywall dismissal.", required: true, }, + userAttributesDidChange: { + type: "newAttributes: Map", + description: "Called when user attributes change outside your app (for example via the `Set Attribute` paywall action).", + required: true, + }, }} /> @@ -182,6 +189,15 @@ override fun didDismissPaywall(paywallInfo: PaywallInfo) { } ``` +Handle user attributes changes: +```kotlin +override fun userAttributesDidChange(newAttributes: Map) { + // React to paywall-triggered attribute updates + println("User attributes updated: $newAttributes") + refreshProfileUI(newAttributes) +} +``` + Java usage: ```java public class MainActivity extends AppCompatActivity implements SuperwallDelegateJava { diff --git a/content/docs/dashboard/dashboard-creating-paywalls/paywall-editor-notifications.mdx b/content/docs/dashboard/dashboard-creating-paywalls/paywall-editor-notifications.mdx index 9f98a94..21d4478 100644 --- a/content/docs/dashboard/dashboard-creating-paywalls/paywall-editor-notifications.mdx +++ b/content/docs/dashboard/dashboard-creating-paywalls/paywall-editor-notifications.mdx @@ -2,11 +2,11 @@ title: "Notifications" --- -To configure a notification which displays before a free trials ends, click the **Notifications** button from the **sidebar** +To configure a notification which displays before a free trial ends, click the **Notifications** button from the **sidebar**: ![](/images/pe-editor-notification-sidebar.png) -You can add a local notification that fires after a number of days when a free trial has been purchased. After the user starts a free trial, it will ask them to enable notifications if they haven't already done so. +You can add a local notification that fires before a free trial ends. After the user starts a free trial, the app will ask them to enable notifications if they haven't already done so. In sandbox mode, the free trial reminder will fire after x minutes, instead of x days. @@ -19,10 +19,30 @@ To turn on a trial reminder notification, click **+ Add Notification**. From the 1. **Title**: Shows at the top of the notification. 2. **Subtitle**: Displays directly below the title in a smaller font. Not required. 3. **Body**: Shows in the primary body of the notification. -4. **Delay**: Any delay you'd like to apply after the free trial begins. +4. **Delay**: How many days before the trial ends the notification should fire. Here's where those values show up on a notification: ![](/images/pe-editor-notification-mapping.png) -Also, keep in mind that these will be scheduled as a local notification as soon as they are configured. +These are scheduled as local notifications as soon as they are configured. + +### Dynamic notification timing + +Requires iOS SDK v4.10.7+ or Android SDK v2.6.6+. + +The SDK automatically calculates the actual trial end date based on the product's introductory offer period from the app store. This means notifications are scheduled relative to when the trial **actually ends** — not when it starts. + +For example, if you set a delay of 3 days: + +| Product trial length | Notification fires on | +| -------------------- | --------------------- | +| 7-day trial | Day 4 (3 days before end) | +| 14-day trial | Day 11 (3 days before end) | +| 1-month trial | ~Day 27 (3 days before end) | + +This ensures users receive trial-ending reminders at the right time — when the reminder is actually relevant to their subscription decision — regardless of the product's trial length. + + +On older SDK versions (pre-4.10.7 on iOS), the notification fires X days **after** the trial starts rather than X days **before** it ends. Upgrade to the latest SDK for accurate timing. + diff --git a/content/docs/dashboard/dashboard-creating-paywalls/paywall-editor-styling-elements.mdx b/content/docs/dashboard/dashboard-creating-paywalls/paywall-editor-styling-elements.mdx index a6ea453..f8b17c1 100644 --- a/content/docs/dashboard/dashboard-creating-paywalls/paywall-editor-styling-elements.mdx +++ b/content/docs/dashboard/dashboard-creating-paywalls/paywall-editor-styling-elements.mdx @@ -61,6 +61,7 @@ Available tap actions are: - **Purchase:** Begin a purchasing flow of the selected product. - **Set/Update Variable:** Sets or updates an existing variable's value. Options specific to the variable type will also be displayed. For example, a **Number** variable will have an option to choose an **Operation** such as Set, Increment or Decrement. Or, a **Boolean** variable's **Operation** will offer to either **Set** or **Toggle** the boolean value. +- **Set Attribute:** Sets a user attribute directly from the paywall. Enter a **Key** (e.g., `preferredPlan`, `onboardingComplete`) and a **Value** (e.g., `premium`, `true`). You can add multiple attributes per tap using **+ Add Attribute**. This behaves the same as calling `setUserAttributes()` in the SDK. Common use cases include capturing user preferences from paywall surveys, tracking paywall engagement, or segmenting users for A/B tests based on their choices. _Requires iOS SDK v4.10.7+._ - **Select Product:** Puts the chosen product in a selected state. Useful for scenarios such as focusing a product in a paywall drawer, for example, when something is tapped or clicked. - **Close:** Closes the paywall. - **Restore:** Begins a purchase restore operation. Useful for restoring purchases someone may have made prior. diff --git a/content/docs/expo/sdk-reference/hooks/useSuperwallEvents.mdx b/content/docs/expo/sdk-reference/hooks/useSuperwallEvents.mdx index 1545d37..b91ecaf 100644 --- a/content/docs/expo/sdk-reference/hooks/useSuperwallEvents.mdx +++ b/content/docs/expo/sdk-reference/hooks/useSuperwallEvents.mdx @@ -39,6 +39,10 @@ The `useSuperwallEvents` hook provides a low-level way to subscribe to *any* nat type: "(status: SubscriptionStatus) => void", description: "Called when the user's subscription status changes.", }, + onUserAttributesChange: { + type: "(newAttributes: Record) => void", + description: "Called when user attributes change outside your app (for example via the `Set Attribute` paywall action).", + }, onSuperwallEvent: { type: "(eventInfo: SuperwallEventInfo) => void", description: "Called for generic Superwall events with payload metadata.", @@ -121,6 +125,10 @@ function EventLogger() { }, onPaywallPresent: (info) => { console.log('Paywall Presented (via useSuperwallEvents):', info.name); + }, + onUserAttributesChange: (newAttributes) => { + console.log('User Attributes Changed:', newAttributes); + // Sync with analytics or update in-memory state } }); diff --git a/content/docs/flutter/sdk-reference/PaywallOptions.mdx b/content/docs/flutter/sdk-reference/PaywallOptions.mdx index ae3b480..4f29c3c 100644 --- a/content/docs/flutter/sdk-reference/PaywallOptions.mdx +++ b/content/docs/flutter/sdk-reference/PaywallOptions.mdx @@ -54,8 +54,8 @@ enum TransactionBackgroundView { spinner, none } }, "restoreFailed.message": { type: "String", - description: "Message for restore-failed alert. \"`", - default: "`\"We couldn't find an active subscription for your account", + description: "Message for restore-failed alert.", + default: "We couldn't find an active subscription for your account.", }, "restoreFailed.closeButtonTitle": { type: "String",