Skip to content

Commit 7e7ad96

Browse files
vegaroJayShortway
andauthored
Customer center various improvements (#700)
* react native * remove useless text * add samples * rc-ignore-offer * fix custom_url case * fix sentence * fix headers * Update docs/tools/customer-center/customer-center-integration-android.mdx Co-authored-by: JayShortway <[email protected]> * fix type * Update code_blocks/tools/customer-center-events-android-global.kt Co-authored-by: JayShortway <[email protected]> * fix showcustomercenter * add import --------- Co-authored-by: JayShortway <[email protected]>
1 parent 65a34da commit 7e7ad96

10 files changed

+207
-7
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
private fun createCustomerCenterListener(): CustomerCenterListener {
2+
return object : CustomerCenterListener {
3+
override fun onManagementOptionSelected(action: CustomerCenterManagementOption) {
4+
when (action) {
5+
CustomerCenterManagementOption.MissingPurchase -> {
6+
// User selected missing purchase option
7+
}
8+
CustomerCenterManagementOption.Cancel -> {
9+
// User selected cancel option
10+
}
11+
is CustomerCenterManagementOption.CustomUrl -> {
12+
val uri: Uri = action.uri
13+
// User selected a custom URL option
14+
}
15+
}
16+
}
17+
18+
override fun onRestoreStarted() {
19+
// Restore purchases process started
20+
}
21+
22+
override fun onRestoreCompleted(customerInfo: CustomerInfo) {
23+
// Restore purchases completed successfully
24+
}
25+
26+
override fun onRestoreFailed(error: PurchasesError) {
27+
// Restore purchases failed
28+
}
29+
30+
override fun onShowingManageSubscriptions() {
31+
// Manage subscriptions screen is displayed
32+
}
33+
34+
override fun onFeedbackSurveyCompleted(feedbackSurveyOptionId: String) {
35+
// User completed a feedback survey
36+
}
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Create and set the global listener
2+
val customerInfoListener = createCustomerCenterListener()
3+
Purchases.sharedInstance.customerCenterListener = customerInfoListener
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
val customerCenterListener = remember { createCustomerCenterListener() }
2+
3+
if (isCustomerCenterVisible) {
4+
CustomerCenter(
5+
modifier = Modifier.fillMaxSize(),
6+
options = CustomerCenterOptions.Builder()
7+
.setListener(customerCenterListener)
8+
.build(),
9+
) {
10+
isCustomerCenterVisible = false
11+
}
12+
return
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { RevenueCatUI } from 'react-native-purchases-ui';
2+
import { CustomerInfo, PurchasesError, REFUND_REQUEST_STATUS, CustomerCenterManagementOptionEvent } from 'react-native-purchases';
3+
4+
await RevenueCatUI.presentCustomerCenter({
5+
callbacks: {
6+
onFeedbackSurveyCompleted: ({ feedbackSurveyOptionId }: { feedbackSurveyOptionId: string }) => {
7+
// User completed a feedback survey
8+
},
9+
onShowingManageSubscriptions: () => {
10+
// Manage subscriptions screen is displayed
11+
},
12+
onRestoreStarted: () => {
13+
// Restore purchases process started
14+
},
15+
onRestoreCompleted: ({ customerInfo }: { customerInfo: CustomerInfo }) => {
16+
// Restore purchases completed successfully
17+
},
18+
onRestoreFailed: ({ error }: { error: PurchasesError }) => {
19+
// Restore purchases failed
20+
},
21+
onRefundRequestStarted: ({ productIdentifier }: { productIdentifier: string }) => {
22+
// iOS only
23+
// Refund request initiated
24+
},
25+
onRefundRequestCompleted: ({
26+
productIdentifier,
27+
refundRequestStatus
28+
}: {
29+
productIdentifier: string;
30+
refundRequestStatus: REFUND_REQUEST_STATUS
31+
}) => {
32+
// iOS only
33+
// Refund request completed
34+
},
35+
onManagementOptionSelected: ({option, url}: CustomerCenterManagementOptionEvent) => {
36+
// User selected a management option
37+
// url is only present for custom_url options
38+
},
39+
}
40+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import com.revenuecat.purchases.ui.revenuecatui.customercenter.ShowCustomerCenter
2+
3+
class MyActivity : ComponentActivity() {
4+
private val customerCenter = registerForActivityResult(ShowCustomerCenter()) {
5+
// Handle the dismissal
6+
}
7+
8+
fun showCustomerCenter() {
9+
customerCenter.launch()
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import androidx.compose.material3.MaterialTheme
2+
3+
val isDarkTheme = isSystemInDarkTheme()
4+
val colorScheme = if (isDarkTheme) darkColorScheme() else lightColorScheme()
5+
6+
MaterialTheme(
7+
colorScheme = colorScheme,
8+
) {
9+
CustomerCenter(
10+
modifier = Modifier.fillMaxSize(),
11+
onDismiss = { isCustomerCenterVisible = false }
12+
)
13+
}

docs/tools/customer-center/customer-center-integration-android.mdx

+70
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,76 @@ import usageViewKotlin from "!!raw-loader!@site/code_blocks/tools/customer-cente
2828
]}
2929
/>
3030

31+
Alternatively, you can instantiate the Customer Center as an Activity:
32+
33+
import usageActivityKotlin from "!!raw-loader!@site/code_blocks/tools/customer-center-usage-2.kt";
34+
35+
<RCCodeBlock
36+
tabs={[
37+
{ type: "kotlin", content: usageActivityKotlin, name: "Kotlin" },
38+
]}
39+
/>
40+
41+
### Ensuring Proper Theming for Customer Center
42+
43+
To ensure that Customer Center displays correctly with the right colors, contrast, and theme consistency, it needs to be wrapped in Material 3's `MaterialTheme`.
44+
This allows it to dynamically adapt to dark and light mode while applying the correct Material Design colors to all UI elements.
45+
If your app already uses Material 3's `MaterialTheme` with appropriate color schemes for dark and light mode, no additional changes are needed.
46+
However, if CustomerCenter is the only composable in your hierarchy, if you're using Material 2, or if you're using another theming system, you may need to explicitly wrap it in Material 3's `MaterialTheme` to ensure proper theming.
47+
48+
import usageThemeKotlin from "!!raw-loader!@site/code_blocks/tools/customer-center-usage-3.kt";
49+
50+
<RCCodeBlock
51+
tabs={[
52+
{ type: "kotlin", content: usageThemeKotlin, name: "Kotlin" },
53+
]}
54+
/>
55+
56+
### Listening to Customer Center Events
57+
58+
You can listen to Customer Center events in two ways: using a global listener, or using a local listener through the CustomerCenter composable options.
59+
60+
First, create a CustomerCenterListener implementation:
61+
62+
import eventsBaseKotlin from "!!raw-loader!@site/code_blocks/tools/customer-center-events-android-base.kt";
63+
64+
<RCCodeBlock
65+
tabs={[
66+
{ type: "kotlin", content: eventsBaseKotlin, name: "Kotlin" },
67+
]}
68+
/>
69+
70+
Then, you can use it in one of two ways:
71+
72+
1. As a global listener that will be called for all Customer Center instances:
73+
74+
import eventsGlobalKotlin from "!!raw-loader!@site/code_blocks/tools/customer-center-events-android-global.kt";
75+
76+
<RCCodeBlock
77+
tabs={[
78+
{ type: "kotlin", content: eventsGlobalKotlin, name: "Kotlin" },
79+
]}
80+
/>
81+
82+
2. As a local listener through the CustomerCenter composable options:
83+
84+
import eventsLocalKotlin from "!!raw-loader!@site/code_blocks/tools/customer-center-events-android-local.kt";
85+
86+
<RCCodeBlock
87+
tabs={[
88+
{ type: "kotlin", content: eventsLocalKotlin, name: "Kotlin" },
89+
]}
90+
/>
91+
92+
The following events are available:
93+
94+
- `onManagementOptionSelected`: Called when a user selects a management option (missing purchase, cancel, or custom URL)
95+
- `onRestoreStarted`: Called when the restore process begins
96+
- `onRestoreCompleted`: Called when the restore process completes successfully
97+
- `onRestoreFailed`: Called when the restore process fails
98+
- `onShowingManageSubscriptions`: Called when the manage subscriptions screen is shown
99+
- `onFeedbackSurveyCompleted`: Called when a user completes a feedback survey
100+
31101
## Setup promotional offers
32102

33103
Promotional Offers allow developers to apply custom pricing and trials to new customers and to existing and lapsed subscriptions. Unique promotional offers can be assigned to different paths and survey responses in the Customer Center, but first they must be setup in Google Play Console.

docs/tools/customer-center/customer-center-integration-ios.mdx

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ import usageModifier from "!!raw-loader!@site/code_blocks/tools/customer-center-
6969
tabs={[{ type: "swift", content: usageModifier, name: "SwiftUI" }]}
7070
/>
7171

72-
#### Listening to events
72+
### Listening to events
7373

74-
We've added a way to listen to events that occur within the `CustomerCenterView`. For now, we are not posting any event to our backend (like feedback survey selections). We are going to be adding way more events in the future, but these are what are available for now:
74+
We've added a way to listen to events that occur within the `CustomerCenterView`:
7575

7676
import customerCenterEvents from "!!raw-loader!@site/code_blocks/tools/customer-center-events.swift";
7777

docs/tools/customer-center/customer-center-promo-offers-google.mdx

+7-5
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ hidden: false
77

88
Promotional Offers allow developers to apply custom pricing and trials to new customers and to existing and lapsed subscriptions. Unique promotional offers can be assigned to different paths and survey responses in the Customer Center, but first they must be setup in Play Store.
99

10-
The Customer Center will automatically show offers based on specific user actions. By default we have defined it for cancellations but it can be modified to any of the defined paths. Heres how it works:
10+
The Customer Center will automatically show offers based on specific user actions. By default we have defined it for cancellations but it can be modified to any of the defined paths. Here's how it works:
1111

1212
![Promotional Offers Configuration](/images/customer-center-promo-offers-config.png)
1313

1414
- **Cancellation Retention Discount**: By default, for responses in the cancellation survey, RevenueCat will use a promotional offer that you can customize in the Offers tab of the Customer Center settings.
1515

16-
This setup enables RevenueCat to automatically match the right offer based on a users actions, providing a seamless experience when user tries to cancel their active subscription.
16+
This setup enables RevenueCat to automatically match the right offer based on a user's actions, providing a seamless experience when user tries to cancel their active subscription.
1717

18-
The SDK will automatically match the right offer based on a users actions and its active subscription. If the SDK cannot locate a matching promotional offer id for the currently active user's subscription, it will bypass the survey and proceed with the users requested action—either canceling or refunding the subscription.
18+
The SDK will automatically match the right offer based on a user's actions and its active subscription. If the SDK cannot locate a matching promotional offer id for the currently active user's subscription, it will bypass the survey and proceed with the user's requested action—either canceling or refunding the subscription.
1919

2020
**These promotional offers must be created in App Store Connect and Google Play Store in order to be shown to customers**
2121

@@ -29,10 +29,12 @@ Unique promotional offers can be assigned to different paths and survey response
2929

3030
Offers on the Play Store allow you to provide a custom price or a trial (or both) for a product. There are [different types of offers](/subscription-guidance/subscription-offers/google-play-offers#eligibility-criteria) that can be created in the Play Store. For the Customer Center, you will be using the **Developer determined** type.
3131

32-
Additionally, **add the `rc-customer-center` tag** to the developer determined offer from your product so that the offer is only available to Customer Center **and not used as a default offer when purchasing the product**.
32+
Additionally, **add both the `rc-customer-center` and `rc-ignore-offer` tags** to the developer determined offer from your product. The `rc-customer-center` tag ensures the offer is only available to Customer Center **and not used as a default offer when purchasing the product**, while the `rc-ignore-offer` tag prevents the offer from being shown to users with older SDK versions.
3333

3434
:::warning Offers must be created in Google Play Console and tagged
35-
Don't forget to add the tag `rc-customer-center` to the offer so that the offer is only available to Customer Center and not used as a default offer when purchasing the product or in Paywalls.
35+
Don't forget to add both tags:
36+
- `rc-customer-center`: Makes the offer only available in the Customer Center and not used as a default offer when purchasing the product or in Paywalls
37+
- `rc-ignore-offer`: Prevents the offer from being shown to users with older SDK versions that don't support the Customer Center
3638
:::
3739

3840
![Play Store Offer Setup](/images/customer-center/play-store-offer.png)

docs/tools/customer-center/customer-center-react-native.mdx

+10
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ Opening the customer center is as simple as:
2929
await RevenueCatUI.presentCustomerCenter();
3030
```
3131

32+
### Listening to events
33+
34+
We've added a way to listen to events that occur within the Customer Center. For now, we are not posting any event to our backend (like feedback survey selections). We are going to be adding way more events in the future, but these are what are available for now:
35+
36+
import customerCenterEventsReactNative from "!!raw-loader!@site/code_blocks/tools/customer-center-events-react-native.tsx";
37+
38+
<RCCodeBlock
39+
tabs={[{ type: "tsx", content: customerCenterEventsReactNative, name: "React Native" }]}
40+
/>
41+
3242
## Setup promotional offers
3343

3444
Promotional Offers allow developers to apply custom pricing and trials to new customers and to existing and lapsed subscriptions. Unique promotional offers can be assigned to different paths and survey responses in the Customer Center, but first they must be setup in App Store Connect and Google Play Store.

0 commit comments

Comments
 (0)