From 5fbf5f25b82426d2f795c0d835de0b5a588e57ce Mon Sep 17 00:00:00 2001 From: Cody Kerns Date: Thu, 16 Jan 2025 12:06:21 -0500 Subject: [PATCH 01/11] prewarming and other customer changes --- docs/customers/user-ids.mdx | 121 +++++++++++------------ docs/getting-started/configuring-sdk.mdx | 88 +++++++++-------- 2 files changed, 107 insertions(+), 102 deletions(-) diff --git a/docs/customers/user-ids.mdx b/docs/customers/user-ids.mdx index ca6e31a6..0147a296 100644 --- a/docs/customers/user-ids.mdx +++ b/docs/customers/user-ids.mdx @@ -7,16 +7,16 @@ hidden: false RevenueCat provides a source of truth for a customer's [subscription status](/customers/customer-info) across different platforms. User identity is one of the most important components of many mobile applications, and it's crucial to make sure the subscription status that RevenueCat is tracking is associated with the correct user. -:::info What is a customer in RevenueCat? - For an overview of what a customer is in RevenueCat, see [What is a Customer?](/customers/user-ids). -::: + ## Anonymous App User IDs -By default, if you don't provide an App User ID when configuring the Purchases SDK, RevenueCat will generate a new random App User ID for you and cache it on the device. In the event that the user deletes and reinstalls the app, a new random App User ID will be generated. +By default, if you don't provide an App User ID when configuring the Purchases SDK, RevenueCat will generate a new random App User ID (prefixed with `$RCAnonymousID:`) for you, and will cache it on the device. +In the event that the user deletes and reinstalls the app, the cache will be cleared and a new random anonymous App User ID will be generated. +Anonymous App User IDs are **not** able to share subscription status across apps and platforms, but are suitable for many apps that don't require authentication and only support a single platform. import content1 from "!!raw-loader!@site/code_blocks/customers/user-ids_1.swift"; import content2 from "!!raw-loader!@site/code_blocks/customers/user-ids_2.m"; @@ -74,15 +74,13 @@ import contentKmpAnon from "!!raw-loader!@site/code_blocks/customers/user-ids_km ]}/> -For SDK versions 3+, anonymous App User IDs are always prefixed with `$RCAnonymousID:`, which may be useful for identifying anonymous users on your server. - -:::info Surface Anonymous IDs for Debugging +{/* :::info Surface Anonymous IDs for Debugging If your app does not enforce the use of custom App User IDs, you should consider revealing the user's App User ID in your app's support page. This will help expedite support requests, including those with RevenueCat Support. You can find the App User ID on the `CustomerInfo` [object](/customers/customer-info#get-user-information). -::: +::: */} -## Logging In with a Custom App User ID +## Custom App User IDs Setting your own App User ID will allow you to reference users in the RevenueCat dashboard, via the API, as well as in the [webhooks](/integrations/webhooks) and other integrations. @@ -91,19 +89,15 @@ Using an externally managed App User ID also provides a mechanism by which to re - When a user deletes and reinstalls your app - using the same App User ID will ensure they still have access to subscriptions previously started without requiring a [restore](/getting-started/restoring-purchases) . - When the user logs in on multiple devices - you can honor a subscription that was purchased on one device across any other platform. -:::info -App User IDs are case-sensitive. -::: - -### Provide App User ID on configuration - -:::danger iOS 15+ Prewarming +App User IDs are case-sensitive, and are scoped to a whole Project. A user logged into the same App User ID on different platforms will be considered the same user, and access the entitlements they have purchased on any platform. -In certain cases, iOS may [prewarm](https://developer.apple.com/documentation/uikit/app_and_environment/responding_to_the_launch_of_your_app/about_the_app_launch_sequence?language=objc) your app - this essentially means your app will be launched silently in the background to improve app launch times for your users. +:::info Managing Subscriptions -If you are **not** using RevenueCat's anonymous IDs as described above, and are instead providing your own app user ID on configuration, **do not** call `configure` in `application:didFinishLaunchingWithOptions:`. Instead, call the `configure` method in your root view controller's initialization method. +A user can only [manage their subscription](/subscription-guidance/managing-subscriptions) on the platform it was purchased from. ::: +### Logging in during configuration + If you have your own App User IDs at app launch, you can pass those on instantiation to _Purchases_. Make sure to not hard-code this identifier, if you do all users will be considered the same one and will share purchases. import content9 from "!!raw-loader!@site/code_blocks/customers/user-ids_9.swift"; @@ -165,10 +159,12 @@ import contentKmp from "!!raw-loader!@site/code_blocks/customers/user-ids_kmp.kt Often times, you may not have your own App User IDs until later in the application lifecycle. In these cases, you can pass the App User ID later through the `.logIn()` method. -### Provide App User ID after configuration +### Logging in after configuration If your app doesn't receive its own App User ID until later in its lifecycle, you can set (or change) the App User ID at any time by calling `.logIn()`. If the logged in identity does not already exist in RevenueCat, it will be created automatically. +This flow will generate an anonymous App User ID for the user first, then may (*see below*) alias the anonymous App User ID to the provided custom App User ID. + import content17 from "!!raw-loader!@site/code_blocks/customers/user-ids_17.swift"; import content18 from "!!raw-loader!@site/code_blocks/customers/user-ids_18.m"; import content19 from "!!raw-loader!@site/code_blocks/customers/user-ids_19.kt"; @@ -225,94 +221,97 @@ import contentKmpLogin from "!!raw-loader!@site/code_blocks/customers/user-ids_k ]}/> -##### `logIn()` method alias behavior +#### `logIn()` method alias behavior When logging in from an Anonymous ID to a provided custom App User ID, RevenueCat will decide whether the identities should be merged (aliased) into the same CustomerInfo object or not. This is decided depending on whether the provided custom App User ID already exists, and if it does exist whether it has an anonymous alias already. -| Current App User ID | Provided Custom App User ID already exists? | Provided Custom App User ID has anonymous alias? | Result | +| Current App User ID | Provided Custom App User ID already exists? | Provided Custom App User ID already has an anonymous alias? | Result | | :------------------ | :------------------------------------------ | :----------------------------------------------- | :--------------------------------------------------------- | | Anonymous | No | N/A | Anonymous ID and Provided ID have CustomerInfo merged. | | Anonymous | Yes | No | Anonymous ID and Provided ID have CustomerInfo merged. | | Anonymous | Yes | Yes | CustomerInfo transfers to Provided ID, no aliases created. | | Non-anonymous | Any | Any | CustomerInfo transfers to Provided ID, no aliases created. | -## Logging Out +### Logging Out When an identified user logs out of your application you should call the `logOut()` method within the SDK. This will generate a new anonymous App User ID for the logged out state. However, if you plan to use only custom App User ID's, you can follow the [instructions here](/customers/user-ids#how-to-only-use-custom-app-user-ids). -### Logging back in +#### Logging back in To log in a new user, the provided App User ID should be set again with `.logIn()`. -### Switching accounts +#### Switching accounts If you need to switch from one provided App User ID to another, it's okay to call the `.logIn()` method directly - you do not need to call `logOut()` first. -## Sharing Subscriptions Across Apps and Platforms +## Aliases -Apps within the same RevenueCat [Project](/projects/overview) share the same App User ID namespace, which means that they also share subscriptions. A user logged in to the same user ID in different apps of the same Project will have access to the same entitlements. This allows sharing of subscription status between different apps, even on different platforms. +If you use a combination of anonymous and custom App User IDs, it’s expected that Customers may be merged over time due to various actions they perform within the app, like [logins](/customers/user-ids#login-method-alias-behavior) or [restores](/getting-started/restoring-purchases). Scenarios explaining when merges occur are covered in more detail below, and will depend on the [restore behavior](/getting-started/restoring-purchases#restore-behavior) you select for your project. -Note that anonymous App User IDs are not able to share subscription status across apps and platforms, so you'll need to identify with a custom App User ID via your own authentication system. +When a merge of customers occurs, there will be only one App User ID within the `original_app_user_id` field. If you’re listening to [Webhooks](/integrations/webhooks), the other App User IDs associated with the customer will be within an array in the `aliases` field. -:::info Managing Subscriptions +When referenced via the [SDK](/getting-started/configuring-sdk) or [API](https://www.revenuecat.com/reference/basic), any merged App User IDs will all be treated as the same “customer”. Looking up any of the merged App User IDs in RevenueCat will return the same `CustomerInfo`, customer history, customer attributes, subscription status, etc. -A user can only [manage their subscription](/subscription-guidance/managing-subscriptions) on the platform it was purchased from. -::: +## Tips for Setting App User IDs -## Aliases +**ℹ️ App User IDs should not be guessable** -If you use a combination of anonymous and custom App User IDs, it’s expected that Customers may be merged over time due to various actions they perform within the app, like [logins](/customers/user-ids#login-method-alias-behavior) or [restores](/getting-started/restoring-purchases). Scenarios explaining when merges occur are covered in more detail below, and will depend on the [restore behavior](/getting-started/restoring-purchases#restore-behavior) you select for your project. +RevenueCat provides subscription status via the public API, having App User IDs that are easily guessed is not good. It is recommended to use a non-guessable pseudo-random ID, like a UUID (RFC 4122 version 4). -When a merge of customers occurs, there will be only one App User ID within the `original_app_user_id` field. If you’re listening to [Webhooks](/integrations/webhooks), the other App User IDs associated with the customer will be within an array in the `aliases` field. +**ℹ️ App User IDs should be shorter than 100 characters** -When referenced via the [SDK](/getting-started/configuring-sdk) or [API](https://www.revenuecat.com/reference/basic), any merged App User IDs will all be treated as the same “customer”. Looking up any of the merged App User IDs in RevenueCat will return the same `CustomerInfo`, customer history, customer attributes, subscription status, etc. +App User IDs should not be longer than 100 characters. +**⚠️ Don't set emails as App User IDs** -## How to only use Custom App User IDs +For the above reasons about guessability, and GDPR compliance, we don't recommend using email addresses as App User IDs. -To only use custom App User IDs, you must take care not to generate any anonymous App User IDs in the SDK. Anonymous App User IDs are generated when the SDK is configured without a provided custom App User ID, and are also created on `logOut()` as mentioned above. Many apps use a combination of anonymous App User IDs and their own custom App User IDs via an authentication system to provide flexibility in their user purchase flows. However, some applications are intended only to be used while using a known App User ID, without anonymous users at all. Some limits of anonymous IDs include added difficulty in personalization of user experiences, optimization of monetization strategies, and not being able to share subscriptions across platforms. Depending on the application's [transfer behavior](/getting-started/restoring-purchases), a provided user's subscription may be transferred to an anonymous ID - which can only be brought back through a [restore](/getting-started/restoring-purchases) on the original purchase platform. +**⚠️ Don't set IDFA as App User IDs** -In any case, to never see Anonymous IDs, you only need to make sure to do the following: Only configure the SDK with a custom App User ID, and never call `.logout()`. +Advertising identifiers should not be used as App User IDs since they can be easily rotated and are not unique across users if limit ad tracking is enabled. -### Only Configure the SDK with a custom App User ID +**🚨 Don't hardcode strings as App User IDs** -The most frequent place that anonymous App User IDs are created is when the SDK is first [configured](/getting-started/configuring-sdk). Calling `.configure` on the SDK without providing a known user ID will cause the SDK to generate an Anonymous ID for the current user. To avoid anonymous IDs, you will need to identify the user’s ID, before configuring the SDK. Many applications use their own authentication system, often shared on multiple platforms, to identify users and provide their unique App User IDs. +You should never hardcode a string as an App User ID, since every install will be treated as the same user in RevenueCat. **This will create problems and could unlock entitlements for users that haven't actually purchased.** -### Do not Logout the User +**Every app user ID must be unique per user.** If you don't have your own user IDs for some of your users, you should not pass any value for the App User ID on configuration which will rely on the anonymous IDs created by RevenueCat. -After the user is logged in with a known App User ID, they may want to logout or switch accounts on your application - logout and then login with a different known ID. However, calling logout in the SDK will result in an anonymous App User ID being created. Simply do not logout the SDK. In the case of switching accounts, you can call login when the user logs in to the different account with their new App User ID. +## Blocked App User IDs -## Tips for Setting App User IDs +Certain App User IDs are blocked in RevenueCat. This is by design to help developers that may be unintentionally passing non-unique strings as user identifiers. -| ℹ️ App User IDs Should Not Be Guessable | -| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| RevenueCat provides subscription status via the public API, having App User IDs that are easily guessed is not good. It is recommended to use a non-guessable pseudo-random ID, like a UUID (RFC 4122 version 4).| +The current block-list is: `'no_user'`, `'null'`, `'none'`, `'nil'`, `'(null)'`, `'NaN`, `'\\x00'`(`NULL` character), `''`(empty string), `'unidentified'`, `'undefined'`, `'unknown'`, `'anonymous'`, `'guest'`, `'-1'`, `'0'`, `'[]'`, `'{}'`, `'[object Object]'` and any App User IDs containing the character `/`. -| ℹ️ Keep App User IDs shorter than 100 characters | -| :----------------------------------------------------- | -| App User IDs should not be longer than 100 characters. | +## Advanced Topics -| ⚠️ Don't set emails as App User IDs | -| :---------------------------------------------------------------------------------------------------------------------- | -| For the above reasons about guessability, and GDPR compliance, we don't recommend using email addresses as App User IDs | +
+How to force only using Custom App User IDs -| ⚠️ Don't set IDFA as App User IDs | -| :----------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Advertising identifiers should not be used as App User IDs since they can be easily rotated and are not unique across users if limit ad tracking is enabled. | +To only use custom App User IDs, you must take care not to generate any anonymous App User IDs in the SDK. -:::danger 🚨 Don't hardcode strings as App User IDs +Anonymous App User IDs are generated when the SDK is configured without a provided custom App User ID, and are also created on `logOut()` as mentioned above. Many apps use a combination of anonymous App User IDs and their own custom App User IDs via an authentication system to provide flexibility in their user purchase flows. However, some applications are intended only to be used while using a known App User ID, without anonymous users at all. -You should never hardcode a string as an App User ID, since every install will be treated as the same user in RevenueCat. **This will create problems and could unlock entitlements for users that haven't actually purchased.** +Some limits of anonymous IDs include added difficulty in personalization of user experiences, optimization of monetization strategies, and not being able to share subscriptions across platforms. Depending on the application's [transfer behavior](/getting-started/restoring-purchases), a provided user's subscription may be transferred to an anonymous ID - which can only be brought back through a [restore](/getting-started/restoring-purchases) on the original purchase platform. -**Every app user ID must be unique per user.** If you don't have your own user IDs for some of your users, you should not pass any value for the App User ID on configuration which will rely on the anonymous IDs created by RevenueCat. +In any case, to never see Anonymous IDs, you only need to make sure to do the following: Only configure the SDK with a custom App User ID, and never call `.logout()`. -::: +#### Only Configure the SDK with a custom App User ID -## Blocked App User IDs +The most frequent place that anonymous App User IDs are created is when the SDK is first [configured](/getting-started/configuring-sdk). Calling `.configure` on the SDK without providing a known user ID will cause the SDK to generate an Anonymous ID for the current user. To avoid anonymous IDs, you will need to identify the user’s ID, before configuring the SDK. Many applications use their own authentication system, often shared on multiple platforms, to identify users and provide their unique App User IDs. -Certain App User IDs are blocked in RevenueCat. This is by design to help developers that may be unintentionally passing non-unique strings as user identifiers. +#### Do not Logout the User -The current block-list is: `'no_user'`, `'null'`, `'none'`, `'nil'`, `'(null)'`, `'NaN`, `'\\x00'`(`NULL` character), `''`(empty string), `'unidentified'`, `'undefined'`, `'unknown'`, `'anonymous'`, `'guest'`, `'-1'`, `'0'`, `'[]'`, `'{}'`, `'[object Object]'` and any App User IDs containing the character `/`. +After the user is logged in with a known App User ID, they may want to logout or switch accounts on your application - logout and then login with a different known ID. However, calling logout in the SDK will result in an anonymous App User ID being created. Simply do not logout the SDK. In the case of switching accounts, you can call login when the user logs in to the different account with their new App User ID. + +
+
+iOS 15 Prewarming + +In certain cases on iOS 15 devices, iOS may [prewarm](https://developer.apple.com/documentation/uikit/app_and_environment/responding_to_the_launch_of_your_app/about_the_app_launch_sequence?language=objc) your app - this essentially means your app will be launched silently in the background to improve app launch times for your users. + +If you are **not** using RevenueCat's anonymous IDs as described above, and are instead providing your own app user ID on configuration, **do not** call `configure` in `application:didFinishLaunchingWithOptions:`. Instead, call the `configure` method in your root view controller's initialization method. + +
## Next Steps diff --git a/docs/getting-started/configuring-sdk.mdx b/docs/getting-started/configuring-sdk.mdx index 81a9f2c8..90e32438 100644 --- a/docs/getting-started/configuring-sdk.mdx +++ b/docs/getting-started/configuring-sdk.mdx @@ -9,9 +9,7 @@ If this is your first time integrating RevenueCat into your app, we recommend fo View our migration guide to v4.x [here](/sdk-guides/ios-native-3x-to-4x-migration). ::: -## Basic Configuration - -### Initialization +## Initialization Once you've [installed](/getting-started/installation) the SDK for your app, it's time to initialize and configure it. @@ -19,6 +17,8 @@ You should only configure _Purchases_ once, usually early in your application li Make sure you configure _Purchases_ with your public SDK key only. You can read more about the different API keys available in our [Authentication guide](/projects/authentication). +**Note:** If you're using a hybrid SDK, such as React Native or Flutter, you'll need to initialize the SDK with a separate API key for each platform (i.e., iOS and Android). The keys can be found in the RevenueCat dashboard under **Project Settings > API keys > App specific keys**. + import swiftContent50 from "!!raw-loader!@site/code_blocks/getting-started/configuring-sdk_1.swift"; import swiftUIContent51 from "!!raw-loader!@site/code_blocks/getting-started/configuring-sdk_2.swift"; import objectiveCContent52 from "!!raw-loader!@site/code_blocks/getting-started/configuring-sdk_2.m"; @@ -43,11 +43,11 @@ import capacitorChinaWorkaround from "!!raw-loader!@site/code_blocks/getting-sta import unityChinaWorkaround from "!!raw-loader!@site/code_blocks/getting-started/configuring-sdk_9_china_url.cs"; -:::danger iOS 15+ Prewarming -In certain cases, calling `configure` in `application:didFinishLaunchingWithOptions:` should be avoided. See [Identifying Users](/customers/user-ids#provide-app-user-id-on-configuration) for more information. -::: - -:::info SwiftUI App Protocol -Using SwiftUI's App protocol? Check out our [resource](/platform-resources/apple-platform-resources/swiftui-helpers) on setting up the _Purchases_ SDK with SwiftUI. -::: - -### Enabling Debug Logs +## Enabling Debug Logs -Be sure to enable and view debug logs before filing a ticket with RevenueCat Support. +Be sure to enable and view debug logs while implementing the SDK and testing your app. Debug logs contain important information about what's happening behind the scenes and should be the first thing you check if your app is behaving unexpectedly. As detailed in the sample code above, debug logs can be enabled or disabled by setting the `Purchases.logLevel` property before configuring _Purchases_. Debug logs will provide detailed log output in Xcode or LogCat for what is going on behind the scenes and should be the first thing you check if your app is behaving unexpectedly, and also to confirm there aren't any unhandled warnings or errors. -### Configuration for users in Mainland China +## Additional Configuration + +The SDK allows additional configuration on first setup: + +- **API Key (required)**: The public API key that corresponds to your app, found via **Project Settings > API keys > App specific keys** in the RevenueCat dashboard. +- **App User ID (optional)**: An identifier for the current user. Pass `null` if you don't have a user identifier at the time of configuration and RevenueCat will generate an anonymous Id for you. See our [guide on identifying users](/customers/user-ids) for more information. +- **Purchases Completed By (optional)**: A boolean value to tell RevenueCat not to [complete purchases](/migrating-to-revenuecat/sdk-or-not/finishing-transactions). Only set purchase completion to your app if you have your own code handling purchases. +- **User Defaults (optional, iOS only)**: A key to override the standard user defaults used to cache `CustomerInfo`. This is required if you need to access `CustomerInfo` in an [iOS App Extension](https://developer.apple.com/app-extensions/). + +### Proxies & configuration for users in Mainland China We’ve received reports of our API being blocked in mainland China. -While we work on a long-term solution, if your app has a significant user base in this region, set the proxyURL property to `https://api.rc-backup.com/` before initializing the RevenueCat SDK. Ensure this configuration occurs prior to SDK setup to prevent connection issues for users in mainland China. +While we work on a long-term solution, if your app has a significant user base in this region, set the `proxyURL` property to `https://api.rc-backup.com/` before initializing the RevenueCat SDK. Ensure this configuration occurs prior to SDK setup to prevent connection issues for users in mainland China. :::caution If you already have a proxy server If you have your own proxy server and already use the `proxyURL` API, you don't need any further configuration. @@ -87,7 +88,7 @@ If you have your own proxy server and already use the `proxyURL` API, you don't { type: 'swift', content: swiftChinaWorkaround, name: 'Swift' }, { type: 'objc', content: objectiveCChinaWorkaround, name: 'Objective-C' }, { type: 'kotlin', content: kotlinChinaWorkaround, name: 'Kotlin' }, - { type: 'kotlin', content: kotlinChinaWorkaround, name: 'Kotlin Multiplatform' }, + { type: 'kotlin', content: kotlinChinaWorkaround, name: 'Kotlin MP' }, { type: 'java', content: javaChinaWorkaround, name: 'Java' }, { type: 'flutter', content: flutterChinaWorkaround, name: 'Flutter' }, { type: 'rn', content: reactChinaWorkaround, name: 'React Native' }, @@ -96,46 +97,51 @@ If you have your own proxy server and already use the `proxyURL` API, you don't { type: 'unity', content: unityChinaWorkaround, name: 'Unity' }, ]} /> -### Additional Configuration Options -The SDK allows additional configuration on first setup: +### iOS -- **API Key (required)**: The public API key that corresponds to your app, found via **Project Settings > API keys > App specific keys** in the RevenueCat dashboard. -- **App User ID (optional)**: An identifier for the current user. Pass `null` if you don't have a user identifier at the time of configuration and RevenueCat will generate an anonymous Id for you. See our [guide on identifying users](/customers/user-ids) for more information. -- **Purchases Completed By (optional)**: A boolean value to tell RevenueCat not to [complete purchases](/migrating-to-revenuecat/sdk-or-not/finishing-transactions). Only set purchase completion to your app if you have your own code handling purchases. -- **User Defaults (optional, iOS only)**: A key to override the standard user defaults used to cache `CustomerInfo`. This is required if you need to access `CustomerInfo` in an [iOS App Extension](https://developer.apple.com/app-extensions/). +#### Listening for CustomerInfo updates -## Advanced Configuration +:::info Note +RevenueCat doesn't push new data to the SDK, so this method is only called when CustomerInfo is updated from another SDK method or after a purchase is made. +::: -Additional configuration options on the `.shared` instance of _Purchases_. +Implement the following delegate method to receive updates to the `CustomerInfo` object: -### iOS +``` +purchases:receivedUpdated +``` -#### Delegates +Called whenever _Purchases_ receives an updated `CustomerInfo` object. This may happen periodically throughout the life of the app if new information becomes available (e.g. after making a purchase). -##### `DELEGATE` `purchases:receivedUpdated` +#### Handling Promoted Purchases -Called whenever _Purchases_ receives an updated `CustomerInfo` object. This may happen periodically throughout the life of the app if new information becomes available (e.g. after making a purchase). +Implement the following delegate method to handle promoted purchases: +``` +purchases:readyForPromotedProduct +``` -:::info -Note: RevenueCat doesn't push new data to the SDK, so this method is only called when CustomerInfo is updated from another SDK method or after a purchase is made. -::: +Called when a user initiates a promoted in-app purchase from the App Store. If your app is able to handle a purchase at the current time, run the `defermentBlock` in this method. -##### `DELEGATE` `purchases:readyForPromotedProduct` +If the app is not in a state to make a purchase: cache the `defermentBlock`, then call the `defermentBlock` when the app is ready to make the promoted purchase. -Called when a user initiates a promoted in-app purchase from the App Store. If your app is able to handle a purchase at the current time, run the `defermentBlock` in this method. If the app is not in a state to make a purchase: cache the `defermentBlock`, then call the `defermentBlock` when the app is ready to make the promoted purchase. If the purchase should never be made, you don't need to ever call the `defermentBlock` and _Purchases_ will not proceed with promoted purchases. +If the purchase should never be made, you don't need to ever call the `defermentBlock` and _Purchases_ will not proceed with promoted purchases. ### Android -#### Listeners +#### Listening for CustomerInfo updates + +:::info Note +RevenueCat doesn't push new data to the SDK, so this method is only called when CustomerInfo is updated from another SDK method or after a purchase is made. +::: -##### `LISTENER` `UpdatedCustomerInfoListener` +Implement the following listener to receive updates to the `CustomerInfo` object: -Called whenever _Purchases_ receives an updated `CustomerInfo` object. This may happen periodically throughout the life of the app if new information becomes available (e.g. after making a purchase). +``` +UpdatedCustomerInfoListener +``` -:::info -Note: RevenueCat doesn't push new data to the SDK, so this method is only called when CustomerInfo is updated from another SDK method or after a purchase is made. -::: +Called whenever _Purchases_ receives an updated `CustomerInfo` object. This may happen periodically throughout the life of the app if new information becomes available (e.g. after making a purchase). ## Next steps From 40e9eb31a227a71f0bcfebadc4719da6ae868f91 Mon Sep 17 00:00:00 2001 From: Cody Kerns Date: Thu, 16 Jan 2025 12:12:55 -0500 Subject: [PATCH 02/11] tweaks --- docs/customers/user-ids.mdx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/customers/user-ids.mdx b/docs/customers/user-ids.mdx index 0147a296..74823e8e 100644 --- a/docs/customers/user-ids.mdx +++ b/docs/customers/user-ids.mdx @@ -221,7 +221,8 @@ import contentKmpLogin from "!!raw-loader!@site/code_blocks/customers/user-ids_k ]}/> -#### `logIn()` method alias behavior +
+`logIn()` method alias behavior When logging in from an Anonymous ID to a provided custom App User ID, RevenueCat will decide whether the identities should be merged (aliased) into the same CustomerInfo object or not. This is decided depending on whether the provided custom App User ID already exists, and if it does exist whether it has an anonymous alias already. @@ -232,6 +233,8 @@ When logging in from an Anonymous ID to a provided custom App User ID, RevenueCa | Anonymous | Yes | Yes | CustomerInfo transfers to Provided ID, no aliases created. | | Non-anonymous | Any | Any | CustomerInfo transfers to Provided ID, no aliases created. | +
+ ### Logging Out When an identified user logs out of your application you should call the `logOut()` method within the SDK. This will generate a new anonymous App User ID for the logged out state. However, if you plan to use only custom App User ID's, you can follow the [instructions here](/customers/user-ids#how-to-only-use-custom-app-user-ids). @@ -254,11 +257,15 @@ When referenced via the [SDK](/getting-started/configuring-sdk) or [API](https:/ ## Tips for Setting App User IDs +**ℹ️ Every app user ID must be unique per user.** + +If you don't have your own user IDs for some of your users, you should not pass any value for the App User ID on configuration which will rely on the anonymous IDs created by RevenueCat. + **ℹ️ App User IDs should not be guessable** RevenueCat provides subscription status via the public API, having App User IDs that are easily guessed is not good. It is recommended to use a non-guessable pseudo-random ID, like a UUID (RFC 4122 version 4). -**ℹ️ App User IDs should be shorter than 100 characters** +**ℹ️ Length limitations** App User IDs should not be longer than 100 characters. @@ -274,8 +281,6 @@ Advertising identifiers should not be used as App User IDs since they can be eas You should never hardcode a string as an App User ID, since every install will be treated as the same user in RevenueCat. **This will create problems and could unlock entitlements for users that haven't actually purchased.** -**Every app user ID must be unique per user.** If you don't have your own user IDs for some of your users, you should not pass any value for the App User ID on configuration which will rely on the anonymous IDs created by RevenueCat. - ## Blocked App User IDs Certain App User IDs are blocked in RevenueCat. This is by design to help developers that may be unintentionally passing non-unique strings as user identifiers. From abff87ddabff7bc2a6acbcb03467d00bcb5583f2 Mon Sep 17 00:00:00 2001 From: Cody Kerns Date: Thu, 16 Jan 2025 12:23:10 -0500 Subject: [PATCH 03/11] supporting customers --- docs/customers/user-ids.mdx | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/customers/user-ids.mdx b/docs/customers/user-ids.mdx index 74823e8e..d1b15e84 100644 --- a/docs/customers/user-ids.mdx +++ b/docs/customers/user-ids.mdx @@ -9,7 +9,6 @@ RevenueCat provides a source of truth for a customer's [subscription status](/cu For an overview of what a customer is in RevenueCat, see [What is a Customer?](/customers/user-ids). - ## Anonymous App User IDs By default, if you don't provide an App User ID when configuring the Purchases SDK, RevenueCat will generate a new random App User ID (prefixed with `$RCAnonymousID:`) for you, and will cache it on the device. @@ -74,12 +73,6 @@ import contentKmpAnon from "!!raw-loader!@site/code_blocks/customers/user-ids_km ]}/> -{/* :::info Surface Anonymous IDs for Debugging -If your app does not enforce the use of custom App User IDs, you should consider revealing the user's App User ID in your app's support page. This will help expedite support requests, including those with RevenueCat Support. - -You can find the App User ID on the `CustomerInfo` [object](/customers/customer-info#get-user-information). -::: */} - ## Custom App User IDs Setting your own App User ID will allow you to reference users in the RevenueCat dashboard, via the API, as well as in the [webhooks](/integrations/webhooks) and other integrations. @@ -247,6 +240,14 @@ To log in a new user, the provided App User ID should be set again with `.logIn( If you need to switch from one provided App User ID to another, it's okay to call the `.logIn()` method directly - you do not need to call `logOut()` first. +## Supporting your customers + +We strongly recommend revealing the App User ID to your customers somewhere within your app. Typically, developers choose to display the App User ID in a settings screen. + +Allowing your customers to view and copy their App User ID can help with troubleshooting and support if they need to contact you or your support team. + +You can retrieve the currently identified App User ID via the `Purchases.shared.appUserID` property. + ## Aliases If you use a combination of anonymous and custom App User IDs, it’s expected that Customers may be merged over time due to various actions they perform within the app, like [logins](/customers/user-ids#login-method-alias-behavior) or [restores](/getting-started/restoring-purchases). Scenarios explaining when merges occur are covered in more detail below, and will depend on the [restore behavior](/getting-started/restoring-purchases#restore-behavior) you select for your project. From 6c5a1b4d5bff287b985c4222e423020da33026fb Mon Sep 17 00:00:00 2001 From: Cody Kerns <44073103+codykerns@users.noreply.github.com> Date: Thu, 16 Jan 2025 14:19:37 -0500 Subject: [PATCH 04/11] Update docs/customers/user-ids.mdx --- docs/customers/user-ids.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/customers/user-ids.mdx b/docs/customers/user-ids.mdx index d1b15e84..317619fe 100644 --- a/docs/customers/user-ids.mdx +++ b/docs/customers/user-ids.mdx @@ -82,7 +82,7 @@ Using an externally managed App User ID also provides a mechanism by which to re - When a user deletes and reinstalls your app - using the same App User ID will ensure they still have access to subscriptions previously started without requiring a [restore](/getting-started/restoring-purchases) . - When the user logs in on multiple devices - you can honor a subscription that was purchased on one device across any other platform. -App User IDs are case-sensitive, and are scoped to a whole Project. A user logged into the same App User ID on different platforms will be considered the same user, and access the entitlements they have purchased on any platform. +App User IDs are case-sensitive and are scoped to a whole Project. A user logged into the same App User ID on different platforms will be considered the same user and can access the entitlements they have purchased on any platform. :::info Managing Subscriptions From 6b52247c6657e5c517930a2d83948e6df951a08e Mon Sep 17 00:00:00 2001 From: Cody Kerns <44073103+codykerns@users.noreply.github.com> Date: Thu, 16 Jan 2025 14:19:57 -0500 Subject: [PATCH 05/11] Update docs/customers/user-ids.mdx --- docs/customers/user-ids.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/customers/user-ids.mdx b/docs/customers/user-ids.mdx index 317619fe..44c5982d 100644 --- a/docs/customers/user-ids.mdx +++ b/docs/customers/user-ids.mdx @@ -256,7 +256,7 @@ When a merge of customers occurs, there will be only one App User ID within the When referenced via the [SDK](/getting-started/configuring-sdk) or [API](https://www.revenuecat.com/reference/basic), any merged App User IDs will all be treated as the same “customer”. Looking up any of the merged App User IDs in RevenueCat will return the same `CustomerInfo`, customer history, customer attributes, subscription status, etc. -## Tips for Setting App User IDs +## Tips for Setting Custom App User IDs **ℹ️ Every app user ID must be unique per user.** From c8ed81698378f35322eadace2b1691af3fe8ea4b Mon Sep 17 00:00:00 2001 From: Cody Kerns Date: Thu, 16 Jan 2025 14:14:02 -0500 Subject: [PATCH 06/11] current device purchases --- docs/getting-started/configuring-sdk.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/getting-started/configuring-sdk.mdx b/docs/getting-started/configuring-sdk.mdx index 90e32438..8e0637a4 100644 --- a/docs/getting-started/configuring-sdk.mdx +++ b/docs/getting-started/configuring-sdk.mdx @@ -103,7 +103,7 @@ If you have your own proxy server and already use the `proxyURL` API, you don't #### Listening for CustomerInfo updates :::info Note -RevenueCat doesn't push new data to the SDK, so this method is only called when CustomerInfo is updated from another SDK method or after a purchase is made. +RevenueCat doesn't push new data to the SDK, so this method is only called when CustomerInfo is updated from another SDK method or after a purchase is made on the current device. ::: Implement the following delegate method to receive updates to the `CustomerInfo` object: @@ -132,7 +132,7 @@ If the purchase should never be made, you don't need to ever call the `deferment #### Listening for CustomerInfo updates :::info Note -RevenueCat doesn't push new data to the SDK, so this method is only called when CustomerInfo is updated from another SDK method or after a purchase is made. +RevenueCat doesn't push new data to the SDK, so this method is only called when CustomerInfo is updated from another SDK method or after a purchase is made on the current device. ::: Implement the following listener to receive updates to the `CustomerInfo` object: From 9902911cd7bc5485fdbc0a043c766fa622717b86 Mon Sep 17 00:00:00 2001 From: Cody Kerns <44073103+codykerns@users.noreply.github.com> Date: Thu, 16 Jan 2025 14:21:26 -0500 Subject: [PATCH 07/11] Update docs/customers/user-ids.mdx --- docs/customers/user-ids.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/customers/user-ids.mdx b/docs/customers/user-ids.mdx index 44c5982d..f6f47b89 100644 --- a/docs/customers/user-ids.mdx +++ b/docs/customers/user-ids.mdx @@ -264,7 +264,7 @@ If you don't have your own user IDs for some of your users, you should not pass **ℹ️ App User IDs should not be guessable** -RevenueCat provides subscription status via the public API, having App User IDs that are easily guessed is not good. It is recommended to use a non-guessable pseudo-random ID, like a UUID (RFC 4122 version 4). +RevenueCat provides subscription status via the public API; it is not good to have App User IDs that are easily guessed. A non-guessable pseudo-random ID, like a UUID (RFC 4122 version 4), is recommended. **ℹ️ Length limitations** From 6d1ae556aa1024e514b88b91f62c1a47ec16f795 Mon Sep 17 00:00:00 2001 From: Cody Kerns <44073103+codykerns@users.noreply.github.com> Date: Thu, 16 Jan 2025 14:22:32 -0500 Subject: [PATCH 08/11] Update docs/customers/user-ids.mdx --- docs/customers/user-ids.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/customers/user-ids.mdx b/docs/customers/user-ids.mdx index f6f47b89..18ca5623 100644 --- a/docs/customers/user-ids.mdx +++ b/docs/customers/user-ids.mdx @@ -260,7 +260,7 @@ When referenced via the [SDK](/getting-started/configuring-sdk) or [API](https:/ **ℹ️ Every app user ID must be unique per user.** -If you don't have your own user IDs for some of your users, you should not pass any value for the App User ID on configuration which will rely on the anonymous IDs created by RevenueCat. +If you don't have your own user IDs for some of your users, you should not pass any value for the App User ID on configuration, which will then rely on the anonymous IDs created by RevenueCat. **ℹ️ App User IDs should not be guessable** From dccf805f12c39c9bf0a6e55bb7421ed4be411601 Mon Sep 17 00:00:00 2001 From: Cody Kerns <44073103+codykerns@users.noreply.github.com> Date: Thu, 16 Jan 2025 14:23:55 -0500 Subject: [PATCH 09/11] Update docs/customers/user-ids.mdx --- docs/customers/user-ids.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/customers/user-ids.mdx b/docs/customers/user-ids.mdx index 18ca5623..32080645 100644 --- a/docs/customers/user-ids.mdx +++ b/docs/customers/user-ids.mdx @@ -303,7 +303,7 @@ In any case, to never see Anonymous IDs, you only need to make sure to do the fo #### Only Configure the SDK with a custom App User ID -The most frequent place that anonymous App User IDs are created is when the SDK is first [configured](/getting-started/configuring-sdk). Calling `.configure` on the SDK without providing a known user ID will cause the SDK to generate an Anonymous ID for the current user. To avoid anonymous IDs, you will need to identify the user’s ID, before configuring the SDK. Many applications use their own authentication system, often shared on multiple platforms, to identify users and provide their unique App User IDs. +The most frequent place that anonymous App User IDs are created is when the SDK is first [configured](/getting-started/configuring-sdk). Calling `.configure` on the SDK without providing a known user ID will cause the SDK to generate an anonymous ID for the current user. To avoid anonymous IDs, you will need to identify the user’s ID before configuring the SDK. Many applications use their own authentication system, often shared on multiple platforms, to identify users and provide their unique App User IDs. #### Do not Logout the User From 229304df1848e8ce057913065c46cf3f18f3f6a6 Mon Sep 17 00:00:00 2001 From: Cody Kerns <44073103+codykerns@users.noreply.github.com> Date: Thu, 16 Jan 2025 14:25:38 -0500 Subject: [PATCH 10/11] Update docs/customers/user-ids.mdx --- docs/customers/user-ids.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/customers/user-ids.mdx b/docs/customers/user-ids.mdx index 32080645..9eb69ad2 100644 --- a/docs/customers/user-ids.mdx +++ b/docs/customers/user-ids.mdx @@ -307,7 +307,7 @@ The most frequent place that anonymous App User IDs are created is when the SDK #### Do not Logout the User -After the user is logged in with a known App User ID, they may want to logout or switch accounts on your application - logout and then login with a different known ID. However, calling logout in the SDK will result in an anonymous App User ID being created. Simply do not logout the SDK. In the case of switching accounts, you can call login when the user logs in to the different account with their new App User ID. +After the user is logged in with a known App User ID, they may want to logout or switch accounts on your application (e.g., logout and then login with a different known ID). However, calling logout in the SDK will result in an anonymous App User ID being created. To resolve this, simply **do not logout the SDK**. In the case of switching accounts, you can call login when the user logs in to the different account with their new App User ID.
From 33da1c379874a47a02f125cae25477aed1f8e3c4 Mon Sep 17 00:00:00 2001 From: Cody Kerns <44073103+codykerns@users.noreply.github.com> Date: Thu, 16 Jan 2025 14:26:44 -0500 Subject: [PATCH 11/11] Update docs/getting-started/configuring-sdk.mdx --- docs/getting-started/configuring-sdk.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/configuring-sdk.mdx b/docs/getting-started/configuring-sdk.mdx index 8e0637a4..2f4d744c 100644 --- a/docs/getting-started/configuring-sdk.mdx +++ b/docs/getting-started/configuring-sdk.mdx @@ -70,7 +70,7 @@ Debug logs will provide detailed log output in Xcode or LogCat for what is going The SDK allows additional configuration on first setup: - **API Key (required)**: The public API key that corresponds to your app, found via **Project Settings > API keys > App specific keys** in the RevenueCat dashboard. -- **App User ID (optional)**: An identifier for the current user. Pass `null` if you don't have a user identifier at the time of configuration and RevenueCat will generate an anonymous Id for you. See our [guide on identifying users](/customers/user-ids) for more information. +- **App User ID (optional)**: An identifier for the current user. Pass `null` if you don't have a user identifier at the time of configuration, RevenueCat will generate an anonymous App User ID for you. See our [guide on identifying users](/customers/user-ids) for more information. - **Purchases Completed By (optional)**: A boolean value to tell RevenueCat not to [complete purchases](/migrating-to-revenuecat/sdk-or-not/finishing-transactions). Only set purchase completion to your app if you have your own code handling purchases. - **User Defaults (optional, iOS only)**: A key to override the standard user defaults used to cache `CustomerInfo`. This is required if you need to access `CustomerInfo` in an [iOS App Extension](https://developer.apple.com/app-extensions/).