-
Notifications
You must be signed in to change notification settings - Fork 3
Add new reserved subscriber attribute $onesignalUserId and add deprecation note to $onesignalId #408
Add new reserved subscriber attribute $onesignalUserId and add deprecation note to $onesignalId #408
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Linter error not related with this change and caused by this snippet:
- /Users/distiller/project/code_blocks/🛠 Tools/paywalls/paywalls_4.swift
Lint fix: #410 |
Purchases.configure(withAPIKey: "<revenuecat_api_key>", appUserID: nil) | ||
|
||
OneSignal.initialize("<onesignal_app_id>", withLaunchOptions: launchOptions) | ||
OneSignal.add(self as OSSubscriptionObserver) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is required since AppDelegate
conforms to OSSubscriptionObserver
OneSignal.add(self as OSSubscriptionObserver) | |
OneSignal.add(self) |
func application(_ application: UIApplication, | ||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { | ||
|
||
Purchases.configure(withAPIKey: "<revenuecat_api_key>", appUserID: nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we try to not have this in quotes to force users to add the api key since that would fail to compile otherwise:
Purchases.configure(withAPIKey: "<revenuecat_api_key>", appUserID: nil) | |
Purchases.configure(withAPIKey: <revenuecat_api_key>, appUserID: nil) |
…signal-integration-changes
PreviewsSee contentsTo set up products for Android devices, start by logging into Google Play Console. Google Play Console is Google's central hub for managing app releases, testing, in-app purchases, and more. This guide assumes basic knowledge of Google Play Console, as well as having an app set up and ready for adding in-app purchases. For more information, visit Google's documentation and guides for Google Play Console. Create an In-App Product or Subscription
To create an in-app product or subscription, go to Google Play Console's 'All Applications' page and select your app from the list. In the sidebar, select the Products dropdown. Depending on your in-app product type, you will either choose In-app products or Subscriptions. After clicking Create, provide a couple pieces of metadata to Google:
Tips for creating robust product IDsAfter you use a Product ID for one product in Google Play Console, it can’t be used again across any of your apps, even if the product is deleted. It helps to be a little organized here from the beginning - we recommend using a consistent naming scheme across all of your product identifiers such as:
For example, using this format the identifier for your first product that grants access to a "premium" subscription would be:
Create a base planFor subscription products, you'll need to add a base plan. Base plans define a billing period, price, and renewal type for purchasing your subscription. Customers never purchase a subscription product directly, they always purchase a base plan of a subscription. Click "Add base plan" and fill out the associated fields. Make sure to set a price, and click "Activate". Since Google introduced multiple base plans with Billing Client 5, it's good practice to be as clear as possible when naming your plans, such as: [block:callout] [block:callout] [block:callout] (Optional) Create an offerIf you wish to create an offer for your base plan, you can do so from the subscription page by clicking "Add offer". Offers can be free trials, discounts, or simply special price setups that apply when a customer first purchases a subscription. You can then select a product ID, eligibility, and offer phases. Making Subscriptions Editable, InAppProduct APIRevenueCat does not use the InAppProduct API for subscriptions. You are safe to make subscriptions editable, unless you are manually using this API outside of RevenueCat. This is related to this notice: If you are relying solely on RevenueCat for your subscriptions, you can safely select "Make editable". Integrate with RevenueCatIf you're ready to integrate your new Google Play in-app product with RevenueCat, continue our product setup guide . See contents
OneSignal can be a useful integration tool for understanding what stage a customer is in to react accordingly. RevenueCat can automatically update user tags in OneSignal with their latest subscription status. With our OneSignal integration, you can:
With accurate and up-to-date subscription data in OneSignal, you'll be set to turbocharge your campaigns ⚡️ For every auto-renewing subscription event in RevenueCat, the following tags get added or updated on the user in OneSignal. By leaving the tag blank in the RevenueCat dashboard, you can choose to not send any value for specific tag(s). [block:parameters]
Integration at a Glance
EventsThe OneSignal integration tracks the following events: [block:parameters] 1. Send device data to RevenueCatOneSignal API versions v9.0 and below (deprecated)The OneSignal integration requires some device-specific data. RevenueCat will only update users in OneSignal if the below data has been added as Subscriber Attributes for the user.
This property can be set manually, like any other Subscriber Attributes, or through the helper method You can listen for changes to the OneSignal Id through their SDK, and send the value to RevenueCat. If you already have OneSignal set up, you should make sure that you're also sending the OneSignal Id for users that are updating to the latest version of your app. class AppDelegate: UIResponder, UIApplicationDelegate, OSSubscriptionObserver {
var window: UIWindow?
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Purchases.configure(withAPIKey: "<revenuecat_api_key>", appUserID: nil)
OneSignal.initWithLaunchOptions(launchOptions, appId: "<onesignal_app_id>")
OneSignal.add(self as OSSubscriptionObserver)
// If you've already set up OneSignal, then users should already have
// a OneSignal Id. We can check if it's available and send it to RevenueCat
if let onesignalId = OneSignal.getUserDevice()?.getUserId() {
Purchases.shared.attribution.setOnesignalID(onesignalId)
}
return true
}
// Add this method to update the $onesignalId in RevenueCat whenever it changes
// This code should be sufficient to capture all new users if you're setting
// up OneSignal for the first time.
func onOSSubscriptionChanged(_ stateChanges: OSSubscriptionStateChanges!) {
if !stateChanges.from.subscribed && stateChanges.to.subscribed {
// The user is subscribed
// Either the user subscribed for the first time
Purchases.shared.attribution.setOnesignalID(stateChanges.to.userId)
}
}
} OneSignal API versions v11.0 and aboveThe OneSignal integration requires some user-specific data. RevenueCat will only update users in OneSignal if the below data has been added as Subscriber Attributes for the user.
This property can be set manually, like any other Subscriber Attributes, or through the helper method You can listen for changes to the OneSignal User ID through their SDK, and send the value to RevenueCat. If you already have OneSignal set up, you should make sure that you're also sending the OneSignal ID for users that are updating to the latest version of your app. class AppDelegate: UIResponder, UIApplicationDelegate, OSSubscriptionObserver {
var window: UIWindow?
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Purchases.configure(withAPIKey: "<revenuecat_api_key>", appUserID: nil)
OneSignal.initialize("<onesignal_app_id>", withLaunchOptions: launchOptions)
OneSignal.add(self as OSSubscriptionObserver)
// If you've already set up OneSignal, then users should already have
// a OneSignal Id. We can check if it's available and send it to RevenueCat
if let onesignalUserId = OneSignal.User.onesignal_id {
Purchases.shared.attribution.setOnesignalUserID(onesignalUserId)
}
return true
}
// Add this method to update the $onesignalUserId in RevenueCat whenever it changes
// This code should be sufficient to capture all new users if you're setting
// up OneSignal for the first time.
func onOSSubscriptionChanged(_ stateChanges: OSSubscriptionStateChanges!) {
if !stateChanges.from.subscribed && stateChanges.to.subscribed {
// The user is subscribed
// Either the user subscribed for the first time
Purchases.shared.attribution.setOnesignalUserID(stateChanges.to.userId)
}
}
} 2. Send RevenueCat events into OneSignalAfter you've set up the Purchases SDK to send device data to RevenueCat, you can "turn on" the integration and configure the tag names from the RevenueCat dashboard.
[block:image] 3. Testing the OneSignal integrationYou can test the OneSignal integration end-to-end before going live. It's recommended that you test the integration is working properly for new users, and any existing users that may update their app to a new version. Make a sandbox purchase with a new userSimulate a new user installing your app, and go through your app flow to complete a sandbox purchase. Check that the required device data is collectedNavigate the the Customer View for the test user that just made a purchase. Make sure that all of the required data from step 1 above is listed as attributes for the user. Check that the OneSignal event delivered successfullyWhile still on the Customer View, click into the test purchase event in the Customer History and make sure that the OneSignal integration event exists and was delivered successfully. Sample EventsBelow are sample JSONs that are delivered to OneSignal for events. {
"app_id": "12345678-1234-1234-1234-123456789012",
"tags": {
"user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
"period_type": "NORMAL",
"purchased_at": 1600016247,
"expiration_at": 1602608247,
"store": "APP_STORE",
"environment": "PRODUCTION",
"last_event_type": "initial_purchase",
"last_event_at": 1600016250,
"product_id": "monthly_sub",
"entitlement_ids": "Pro"
}
} {
"app_id": "12345678-1234-1234-1234-123456789012",
"tags": {
"user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
"period_type": "TRIAL",
"purchased_at": 1600031584,
"expiration_at": 1600290784,
"store": "APP_STORE",
"environment": "PRODUCTION",
"last_event_type": "trial_started",
"last_event_at": 1600031586,
"product_id": "three_month_sub_trial",
"entitlement_ids": "Pro"
}
} {
"app_id": "12345678-1234-1234-1234-123456789012",
"tags": {
"app_user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
"period_type": "NORMAL",
"purchased_at": 1602136340,
"expiration_at": 1602741140,
"store": "APP_STORE",
"environment": "PRODUCTION",
"last_event_type": "trial_converted",
"last_event_at": 1602114850,
"product_id": "weekly_sub_trial",
"entitlement_ids": null
}
} {
"app_id": "12345678-1234-1234-1234-123456789012",
"tags": {
"app_user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
"period_type": "TRIAL",
"purchased_at": 1602051920,
"expiration_at": 1602311120,
"store": "APP_STORE",
"environment": "PRODUCTION",
"last_event_type": "trial_cancelled",
"last_event_at": 1602129368,
"product_id": "weekly_sub_trial",
"entitlement_ids": null
}
} {
"app_id": "12345678-1234-1234-1234-123456789012",
"tags": {
"app_user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
"period_type": "NORMAL",
"purchased_at": 1602125078,
"expiration_at": 1604807078,
"store": "APP_STORE",
"environment": "PRODUCTION",
"last_event_type": "renewal",
"last_event_at": 1602122793,
"product_id": "monthly_sub",
"entitlement_ids": "Pro"
}
} {
"app_id": "12345678-1234-1234-1234-123456789012",
"tags": {
"app_user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
"period_type": "NORMAL",
"purchased_at": 1602086660,
"expiration_at": 1602691460,
"store": "APP_STORE",
"environment": "PRODUCTION",
"last_event_type": "cancellation",
"last_event_at": 1602118600,
"product_id": "weekly_sub",
"entitlement_ids": null
}
} {
"app_id": "12345678-1234-1234-1234-123456789012",
"tags": {
"app_user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
"period_type": "TRIAL",
"purchased_at": 1663445025,
"expiration_at": 1664049825,
"store": "APP_STORE",
"environment": "PRODUCTION",
"last_event_type": "uncancellation",
"last_event_at": 1663969096,
"product_id": "annual_sub",
"entitlement_ids": "Premium"
}
} {
"app_id": "12345678-1234-1234-1234-123456789012",
"tags": {
"app_user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
"purchased_at": 1602086660,
"store": "APP_STORE",
"environment": "PRODUCTION",
"last_event_type": "non_renewing_purchase",
"last_event_at": 1602118600,
"product_id": "one_time_purchase_product",
"entitlement_ids": null
}
} {
"app_id": "12345678-1234-1234-1234-123456789012",
"tags": {
"app_user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
"period_type": "NORMAL",
"purchased_at": 1602086660,
"expiration_at": 1602691460,
"store": "PLAY_STORE",
"environment": "PRODUCTION",
"last_event_type": "subscription_paused",
"last_event_at": 1602118600,
"product_id": "weekly_sub",
"auto_resume_at": 1602119600,
"entitlement_ids": null
}
} {
"app_id": "12345678-1234-1234-1234-123456789012",
"tags": {
"period_type": "NORMAL",
"purchased_at": 1652374230,
"expiration_at": 1652979030,
"last_event_type": "expiration",
"last_event_at": 1652988735
}
} {
"app_id": "12345678-1234-1234-1234-123456789012",
"tags": {
"app_user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
"period_type": "TRIAL",
"purchased_at": 1652383957,
"expiration_at": 1654371157,
"store": "APP_STORE",
"environment": "PRODUCTION",
"last_event_type": "billing_issue",
"last_event_at": 1652988776,
"product_id": "annual_sub",
"entitlement_ids": "Premium"
}
} {
"app_id": "12345678-1234-1234-1234-123456789012",
"tags": {
"app_user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
"period_type": "NORMAL",
"purchased_at": 1602086660,
"expiration_at": 1602691460,
"store": "APP_STORE",
"environment": "PRODUCTION",
"last_event_type": "product_change",
"last_event_at": 1602118600,
"product_id": "weekly_sub",
"new_product_id": "monthly_sub",
"entitlement_ids": null
}
}
Subscription Status AttributeWhenever RevenueCat sends an event to OneSignal, we'll send a
For customers with multiple active subscriptions, this attribute will represent the status of only the subscription for which the most recent event occurred. Please note that since this attribute is set and updated when events are delivered, subscribers with events prior to our release of this attribute (during November 2023) will not have this attribute set until/unless a future event (renewal, cancellation, etc) occurs. See contentsSubscriber attributes are useful for storing additional, structured information on a user. For example, you could store your user's email address and additional system identifiers directly in RevenueCat. Attributes will not be seen by your users unless you choose to explicitly show them yourself.
Setting AttributesSubscriber attributes can be set through the SDK by passing a dictionary of strings to the Purchases.shared.attribution.setAttributes(["age": "24",
"custom_group_id": "abc123"]) [RCPurchases.sharedPurchases.attribution setAttributes:@{
@"age": @"24",
@"custom_group_id": @"abc123"
}]; Purchases.sharedInstance.setAttributes(mapOf("age" to "24", "custom_group_id" to "abc123")) Map<String, String> attributes = new HashMap<String, String>();
attributes.put("age", "24");
attributes.put("custom_group_id", "abc123");
Purchases.getSharedInstance().setAttributes(attributes); Purchases.setAttributes({ "age" : "24", "custom_group_id" : "abc123" }); Purchases.setAttributes({ "age" : "24", "custom_group_id" : "abc123" }); var purchases = GetComponent<Purchases>();
var attributes = new Dictionary<string, string>
{
{ "age", "24" },
{ "custom_group_id", "abc123" }
};
purchases.SetAttributes(attributes);
RestrictionsYou can specify up to 50 attributes, with key names up to 40 characters long and values up to 500 characters long. Keys cannot start with Attribute key checklist: Reserved attributesAttribute keys beginning with General
Device Identifiers
Third-party Identifiers
Braze User Alias Object
Iterable Data
Attribution Data
Reserved attributes can be written directly by setting the key (don't forget the Purchases.shared.attribution.setEmail("test@example.com")
Purchases.shared.attribution.setPhoneNumber("+16505551234")
Purchases.shared.attribution.setDisplayName("John Appleseed") [RCPurchases.sharedPurchases.attribution setEmail:@"test@example.com"];
[RCPurchases.sharedPurchases.attribution setPhoneNumber:@"+16505551234"];
[RCPurchases.sharedPurchases.attribution setDisplayName:@"John Appleseed"]; Purchases.sharedInstance.setEmail("test@example.com")
Purchases.sharedInstance.setPhoneNumber("+16505551234")
Purchases.sharedInstance.setDisplayName("John Appleseed") Purchases.setEmail("test@example.com")
Purchases.setPhoneNumber("+16505551234")
Purchases.setDisplayName("John Appleseed") Purchases.setEmail("test@example.com")
Purchases.setPhoneNumber("+16505551234")
Purchases.setDisplayName("John Appleseed") var purchases = GetComponent<Purchases>();
purchases.SetEmail("asdf@asdfa.com");
purchases.SetPhoneNumber("asdga");
purchases.SetDisplayName("asdgas"); Setting push tokensPush tokens can be used to engage with your users through Apple apns or Google cloud messaging. These can be saved in RevenueCat through system callbacks after the user accepts the push notification permissions in your app. func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Purchases.shared.attribution.setPushToken(deviceToken)
} - (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[RCPurchases.sharedPurchases.attribution setPushToken:deviceToken];
} Purchases.sharedInstance.setPushToken(deviceToken) Purchases.setPushToken(deviceToken); Purchases.setPushToken(deviceToken) var purchases = GetComponent<Purchases>();
purchases.SetPushToken(deviceToken); Deleting AttributesAny attribute can be cleared by passing Purchases.shared.attribution.setAttributes(["age": ""]) [RCPurchases.sharedPurchases.attribution setAttributes:@{@"age": @""}]; Purchases.sharedInstance.setAttributes(mapOf("age" to "")) Purchases.setAttributes({"age" : ""}); Purchases.setAttributes({"age" : ""}) var purchases = GetComponent<Purchases>();
var attributes = new Dictionary<string, string>
{
{ "age", "" },
{ "custom_group_id", "" }
};
purchases.SetAttributes(attributes); Reading AttributesYou can access subscriber attributes through the REST API using a secret key, in webhooks, and through analytics integrations (Amplitude, Mixpanel, Segment). The customer view dashboard will also show a list of attributes for the individual user that you can edit.
Next Steps
|
Motivation / Description
We are migrating OneSignal API to User Centric v11.0. We are adding a new reserved attribute $onesignalUserId to allow developers to provide the user id required by the new API, and adding a note that the existing $onesignalId (subscription id) is deprecated for OneSignal APIs >v9.0.
Changes introduced
Linear ticket (if any)
Additional comments