rampkit-expo-dev 0.0.57 → 0.0.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -8
- package/build/DeviceInfoCollector.js +2 -0
- package/build/EventManager.js +11 -2
- package/build/OnboardingResponseStorage.d.ts +24 -0
- package/build/OnboardingResponseStorage.js +70 -0
- package/build/RampKit.d.ts +30 -2
- package/build/RampKit.js +100 -22
- package/build/RampkitOverlay.js +20 -4
- package/build/constants.d.ts +1 -0
- package/build/constants.js +2 -0
- package/build/index.d.ts +1 -1
- package/build/types.d.ts +31 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,10 +38,11 @@ npx expo install rampkit-expo-dev
|
|
|
38
38
|
```ts
|
|
39
39
|
import { RampKit } from "rampkit-expo-dev";
|
|
40
40
|
|
|
41
|
-
await RampKit.
|
|
42
|
-
|
|
41
|
+
await RampKit.configure({
|
|
42
|
+
appId: "YOUR_APP_ID",
|
|
43
43
|
environment: "production", // optional
|
|
44
44
|
autoShowOnboarding: false, // optional
|
|
45
|
+
appUserID: "your-user-123", // optional - your own user ID for analytics linking
|
|
45
46
|
onOnboardingFinished: (payload) => {
|
|
46
47
|
// optional callback fired when the flow finishes
|
|
47
48
|
},
|
|
@@ -59,23 +60,82 @@ RampKit.showOnboarding();
|
|
|
59
60
|
## Configuration Options
|
|
60
61
|
|
|
61
62
|
```ts
|
|
62
|
-
await RampKit.
|
|
63
|
-
|
|
63
|
+
await RampKit.configure({
|
|
64
|
+
appId: "YOUR_APP_ID",
|
|
64
65
|
environment: "staging", // optional
|
|
65
|
-
autoShowOnboarding: true, // optional (auto-present after
|
|
66
|
+
autoShowOnboarding: true, // optional (auto-present after configure if data is available)
|
|
67
|
+
appUserID: "user-123", // optional - link with your own user database
|
|
66
68
|
onOnboardingFinished: (payload) => {
|
|
67
69
|
// optional
|
|
68
70
|
},
|
|
69
71
|
});
|
|
70
72
|
|
|
71
73
|
// Access the generated stable user id (stored securely)
|
|
72
|
-
const idFromInit = RampKit.getUserId(); // string | null (available after
|
|
74
|
+
const idFromInit = RampKit.getUserId(); // string | null (available after configure)
|
|
73
75
|
|
|
74
76
|
// Or fetch/generate it directly (always returns a string)
|
|
75
77
|
import { getRampKitUserId } from "rampkit-expo-dev";
|
|
76
78
|
const userId = await getRampKitUserId();
|
|
79
|
+
|
|
80
|
+
// Get stored onboarding responses
|
|
81
|
+
const responses = await RampKit.getOnboardingResponses();
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Custom App User ID
|
|
87
|
+
|
|
88
|
+
You can associate your own user identifier with RampKit analytics. This is useful for linking RampKit data with your own user database.
|
|
89
|
+
|
|
90
|
+
**Important:** This is an alias only - RampKit still generates and uses its own internal user ID (`appUserId`) for tracking. Your custom `appUserID` is stored alongside it for your reference.
|
|
91
|
+
|
|
92
|
+
### Set at Configuration
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
await RampKit.configure({
|
|
96
|
+
appId: "YOUR_APP_ID",
|
|
97
|
+
appUserID: "your-user-123", // Set during configuration
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Set After Configuration
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
// Set or update the app user ID at any time
|
|
105
|
+
await RampKit.setAppUserID("your-user-123");
|
|
106
|
+
|
|
107
|
+
// Get the current app user ID
|
|
108
|
+
const customId = RampKit.getAppUserID(); // string | null
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Accessing Onboarding Responses
|
|
114
|
+
|
|
115
|
+
RampKit automatically stores user responses when questions are answered during onboarding. You can retrieve these responses at any time:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
const responses = await RampKit.getOnboardingResponses();
|
|
119
|
+
|
|
120
|
+
for (const response of responses) {
|
|
121
|
+
console.log("Question:", response.questionId);
|
|
122
|
+
console.log("Answer:", response.answer);
|
|
123
|
+
console.log("Answered at:", response.answeredAt);
|
|
124
|
+
}
|
|
77
125
|
```
|
|
78
126
|
|
|
127
|
+
Each `OnboardingResponse` contains:
|
|
128
|
+
|
|
129
|
+
| Property | Type | Description |
|
|
130
|
+
|----------|------|-------------|
|
|
131
|
+
| `questionId` | `string` | Unique identifier for the question |
|
|
132
|
+
| `answer` | `any` | The user's answer (any JSON-serializable value) |
|
|
133
|
+
| `questionText` | `string?` | Optional question text shown to user |
|
|
134
|
+
| `screenName` | `string?` | Screen where question was answered |
|
|
135
|
+
| `answeredAt` | `string` | ISO 8601 timestamp |
|
|
136
|
+
|
|
137
|
+
Responses are automatically cleared when `reset()` is called.
|
|
138
|
+
|
|
79
139
|
More examples are in the docs:
|
|
80
140
|
https://rampkit.com/docs
|
|
81
141
|
|
|
@@ -90,8 +150,8 @@ import { Button } from "react-native";
|
|
|
90
150
|
|
|
91
151
|
export default function App() {
|
|
92
152
|
useEffect(() => {
|
|
93
|
-
//
|
|
94
|
-
RampKit.
|
|
153
|
+
// Configure once in your app
|
|
154
|
+
RampKit.configure({ appId: "YOUR_APP_ID" });
|
|
95
155
|
}, []);
|
|
96
156
|
|
|
97
157
|
return (
|
|
@@ -46,6 +46,7 @@ async function collectDeviceInfo() {
|
|
|
46
46
|
const deviceInfo = {
|
|
47
47
|
// User & Session Identifiers
|
|
48
48
|
appUserId: nativeInfo.appUserId,
|
|
49
|
+
appUserID: null, // Custom app user ID is set separately via config or setAppUserID()
|
|
49
50
|
vendorId: nativeInfo.vendorId,
|
|
50
51
|
appSessionId: nativeInfo.appSessionId,
|
|
51
52
|
// Launch Tracking
|
|
@@ -141,6 +142,7 @@ function getFallbackDeviceInfo() {
|
|
|
141
142
|
sessionStartTime = new Date();
|
|
142
143
|
return {
|
|
143
144
|
appUserId: fallbackUserId,
|
|
145
|
+
appUserID: null, // Custom app user ID is set separately via config or setAppUserID()
|
|
144
146
|
vendorId: null,
|
|
145
147
|
appSessionId: sessionId,
|
|
146
148
|
installDate: now,
|
package/build/EventManager.js
CHANGED
|
@@ -174,14 +174,23 @@ class EventManager {
|
|
|
174
174
|
body: JSON.stringify(event),
|
|
175
175
|
});
|
|
176
176
|
if (!response.ok) {
|
|
177
|
-
|
|
177
|
+
// Try to get error details from response body
|
|
178
|
+
let errorDetails = "";
|
|
179
|
+
try {
|
|
180
|
+
const errorBody = await response.text();
|
|
181
|
+
errorDetails = errorBody ? ` - ${errorBody}` : "";
|
|
182
|
+
}
|
|
183
|
+
catch (_a) {
|
|
184
|
+
// Ignore if we can't read the body
|
|
185
|
+
}
|
|
186
|
+
console.warn(`[RampKit] EventManager: Failed to send event: ${event.eventName}`, `\n Status: ${response.status} ${response.statusText}`, `\n URL: ${url}`, `\n AppId: ${event.appId}`, `\n UserId: ${event.appUserId}`, errorDetails ? `\n Error: ${errorDetails}` : "");
|
|
178
187
|
}
|
|
179
188
|
else {
|
|
180
189
|
console.log("[RampKit] EventManager: Event sent:", event.eventName);
|
|
181
190
|
}
|
|
182
191
|
}
|
|
183
192
|
catch (error) {
|
|
184
|
-
console.warn(
|
|
193
|
+
console.warn(`[RampKit] EventManager: Network error sending event: ${event.eventName}`, `\n Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
185
194
|
}
|
|
186
195
|
}
|
|
187
196
|
// ============================================================================
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OnboardingResponseStorage
|
|
3
|
+
* Manages persistent storage of onboarding responses
|
|
4
|
+
*/
|
|
5
|
+
import { OnboardingResponse } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* Manages persistent storage of onboarding responses
|
|
8
|
+
*/
|
|
9
|
+
export declare const OnboardingResponseStorage: {
|
|
10
|
+
/**
|
|
11
|
+
* Save a new response, merging with existing responses
|
|
12
|
+
* If a response with the same questionId exists, it will be updated
|
|
13
|
+
*/
|
|
14
|
+
saveResponse(response: OnboardingResponse): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Retrieve all stored responses
|
|
17
|
+
* @returns Array of OnboardingResponse objects, empty array if none found
|
|
18
|
+
*/
|
|
19
|
+
retrieveResponses(): Promise<OnboardingResponse[]>;
|
|
20
|
+
/**
|
|
21
|
+
* Clear all stored responses
|
|
22
|
+
*/
|
|
23
|
+
clearResponses(): Promise<void>;
|
|
24
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OnboardingResponseStorage
|
|
4
|
+
* Manages persistent storage of onboarding responses
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.OnboardingResponseStorage = void 0;
|
|
8
|
+
const RampKitNative_1 = require("./RampKitNative");
|
|
9
|
+
const constants_1 = require("./constants");
|
|
10
|
+
/**
|
|
11
|
+
* Manages persistent storage of onboarding responses
|
|
12
|
+
*/
|
|
13
|
+
exports.OnboardingResponseStorage = {
|
|
14
|
+
/**
|
|
15
|
+
* Save a new response, merging with existing responses
|
|
16
|
+
* If a response with the same questionId exists, it will be updated
|
|
17
|
+
*/
|
|
18
|
+
async saveResponse(response) {
|
|
19
|
+
try {
|
|
20
|
+
const responses = await this.retrieveResponses();
|
|
21
|
+
// Update existing response for same questionId or append new
|
|
22
|
+
const existingIndex = responses.findIndex((r) => r.questionId === response.questionId);
|
|
23
|
+
if (existingIndex >= 0) {
|
|
24
|
+
responses[existingIndex] = response;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
responses.push(response);
|
|
28
|
+
}
|
|
29
|
+
// Serialize and save
|
|
30
|
+
await (0, RampKitNative_1.setStoredValue)(constants_1.STORAGE_KEYS.ONBOARDING_RESPONSES, JSON.stringify(responses));
|
|
31
|
+
if (__DEV__) {
|
|
32
|
+
console.log(`[RampKit] Saved response for question: ${response.questionId}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
console.warn("[RampKit] Failed to save onboarding response:", error);
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
/**
|
|
40
|
+
* Retrieve all stored responses
|
|
41
|
+
* @returns Array of OnboardingResponse objects, empty array if none found
|
|
42
|
+
*/
|
|
43
|
+
async retrieveResponses() {
|
|
44
|
+
try {
|
|
45
|
+
const jsonString = await (0, RampKitNative_1.getStoredValue)(constants_1.STORAGE_KEYS.ONBOARDING_RESPONSES);
|
|
46
|
+
if (!jsonString) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
return JSON.parse(jsonString);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.warn("[RampKit] Failed to retrieve onboarding responses:", error);
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
/**
|
|
57
|
+
* Clear all stored responses
|
|
58
|
+
*/
|
|
59
|
+
async clearResponses() {
|
|
60
|
+
try {
|
|
61
|
+
await (0, RampKitNative_1.setStoredValue)(constants_1.STORAGE_KEYS.ONBOARDING_RESPONSES, "");
|
|
62
|
+
if (__DEV__) {
|
|
63
|
+
console.log("[RampKit] Cleared all onboarding responses");
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
console.warn("[RampKit] Failed to clear onboarding responses:", error);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
};
|
package/build/RampKit.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* RampKit Core SDK
|
|
3
3
|
* Main SDK class for RampKit Expo integration
|
|
4
4
|
*/
|
|
5
|
-
import { DeviceInfo, RampKitConfig, EventContext } from "./types";
|
|
5
|
+
import { DeviceInfo, RampKitConfig, EventContext, OnboardingResponse } from "./types";
|
|
6
6
|
export declare class RampKitCore {
|
|
7
7
|
private static _instance;
|
|
8
8
|
private config;
|
|
@@ -15,11 +15,34 @@ export declare class RampKitCore {
|
|
|
15
15
|
private appStateSubscription;
|
|
16
16
|
private lastAppState;
|
|
17
17
|
private initialized;
|
|
18
|
+
/** Custom App User ID provided by the developer (alias for their user system) */
|
|
19
|
+
private appUserID;
|
|
18
20
|
static get instance(): RampKitCore;
|
|
19
21
|
/**
|
|
20
|
-
*
|
|
22
|
+
* Configure the RampKit SDK
|
|
23
|
+
* @param config Configuration options including appId, callbacks, and optional appUserID
|
|
24
|
+
*/
|
|
25
|
+
configure(config: RampKitConfig): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* @deprecated Use `configure()` instead. This method will be removed in a future version.
|
|
21
28
|
*/
|
|
22
29
|
init(config: RampKitConfig): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Set a custom App User ID to associate with this user.
|
|
32
|
+
* This is an alias for your own user identification system.
|
|
33
|
+
*
|
|
34
|
+
* Note: This does NOT replace the RampKit-generated user ID (appUserId).
|
|
35
|
+
* RampKit will continue to use its own stable UUID for internal tracking.
|
|
36
|
+
* This custom ID is sent to the backend for you to correlate with your own user database.
|
|
37
|
+
*
|
|
38
|
+
* @param appUserID Your custom user identifier
|
|
39
|
+
*/
|
|
40
|
+
setAppUserID(appUserID: string): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Get the custom App User ID if one has been set.
|
|
43
|
+
* @returns The custom App User ID or null if not set
|
|
44
|
+
*/
|
|
45
|
+
getAppUserID(): string | null;
|
|
23
46
|
/**
|
|
24
47
|
* Send user/device data to the /app-users endpoint
|
|
25
48
|
*/
|
|
@@ -44,6 +67,11 @@ export declare class RampKitCore {
|
|
|
44
67
|
* Check if SDK is initialized
|
|
45
68
|
*/
|
|
46
69
|
isInitialized(): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Get all stored onboarding responses
|
|
72
|
+
* @returns Promise resolving to array of OnboardingResponse objects
|
|
73
|
+
*/
|
|
74
|
+
getOnboardingResponses(): Promise<OnboardingResponse[]>;
|
|
47
75
|
/**
|
|
48
76
|
* Show the onboarding overlay
|
|
49
77
|
*/
|
package/build/RampKit.js
CHANGED
|
@@ -12,6 +12,7 @@ const DeviceInfoCollector_1 = require("./DeviceInfoCollector");
|
|
|
12
12
|
const EventManager_1 = require("./EventManager");
|
|
13
13
|
const RampKitNative_1 = require("./RampKitNative");
|
|
14
14
|
const constants_1 = require("./constants");
|
|
15
|
+
const OnboardingResponseStorage_1 = require("./OnboardingResponseStorage");
|
|
15
16
|
class RampKitCore {
|
|
16
17
|
constructor() {
|
|
17
18
|
this.config = null;
|
|
@@ -22,6 +23,8 @@ class RampKitCore {
|
|
|
22
23
|
this.appStateSubscription = null;
|
|
23
24
|
this.lastAppState = "active";
|
|
24
25
|
this.initialized = false;
|
|
26
|
+
/** Custom App User ID provided by the developer (alias for their user system) */
|
|
27
|
+
this.appUserID = null;
|
|
25
28
|
}
|
|
26
29
|
static get instance() {
|
|
27
30
|
if (!this._instance)
|
|
@@ -29,49 +32,60 @@ class RampKitCore {
|
|
|
29
32
|
return this._instance;
|
|
30
33
|
}
|
|
31
34
|
/**
|
|
32
|
-
*
|
|
35
|
+
* Configure the RampKit SDK
|
|
36
|
+
* @param config Configuration options including appId, callbacks, and optional appUserID
|
|
33
37
|
*/
|
|
34
|
-
async
|
|
38
|
+
async configure(config) {
|
|
35
39
|
this.config = config;
|
|
36
40
|
this.appId = config.appId;
|
|
37
41
|
this.onOnboardingFinished = config.onOnboardingFinished;
|
|
38
42
|
this.onShowPaywall = config.onShowPaywall || config.showPaywall;
|
|
43
|
+
// Store custom App User ID if provided (this is an alias, not the RampKit user ID)
|
|
44
|
+
if (config.appUserID) {
|
|
45
|
+
this.appUserID = config.appUserID;
|
|
46
|
+
console.log("[RampKit] Configure: appUserID set to", this.appUserID);
|
|
47
|
+
}
|
|
39
48
|
try {
|
|
40
49
|
// Step 1: Collect device info (includes user ID generation)
|
|
41
|
-
console.log("[RampKit]
|
|
42
|
-
|
|
50
|
+
console.log("[RampKit] Configure: Collecting device info...");
|
|
51
|
+
const baseDeviceInfo = await (0, DeviceInfoCollector_1.collectDeviceInfo)();
|
|
52
|
+
// Add the custom appUserID to device info
|
|
53
|
+
this.deviceInfo = {
|
|
54
|
+
...baseDeviceInfo,
|
|
55
|
+
appUserID: this.appUserID,
|
|
56
|
+
};
|
|
43
57
|
this.userId = this.deviceInfo.appUserId;
|
|
44
|
-
console.log("[RampKit]
|
|
58
|
+
console.log("[RampKit] Configure: userId", this.userId);
|
|
45
59
|
// Step 2: Send device info to /app-users endpoint
|
|
46
|
-
console.log("[RampKit]
|
|
60
|
+
console.log("[RampKit] Configure: Sending user data to backend...");
|
|
47
61
|
await this.sendUserDataToBackend(this.deviceInfo);
|
|
48
62
|
// Step 3: Initialize event manager
|
|
49
|
-
console.log("[RampKit]
|
|
63
|
+
console.log("[RampKit] Configure: Initializing event manager...");
|
|
50
64
|
EventManager_1.eventManager.initialize(config.appId, this.deviceInfo);
|
|
51
65
|
// Step 4: Track app session started
|
|
52
66
|
EventManager_1.eventManager.trackAppSessionStarted(this.deviceInfo.isFirstLaunch, this.deviceInfo.launchCount);
|
|
53
67
|
// Step 5: Setup app state listener for background/foreground tracking
|
|
54
68
|
this.setupAppStateListener();
|
|
55
69
|
// Step 6: Start transaction observer for automatic purchase tracking
|
|
56
|
-
console.log("[RampKit]
|
|
70
|
+
console.log("[RampKit] Configure: Starting transaction observer...");
|
|
57
71
|
await RampKitNative_1.TransactionObserver.start(config.appId);
|
|
58
72
|
this.initialized = true;
|
|
59
73
|
}
|
|
60
74
|
catch (e) {
|
|
61
|
-
console.log("[RampKit]
|
|
75
|
+
console.log("[RampKit] Configure: Failed to initialize device info", e);
|
|
62
76
|
// Fallback to just getting user ID
|
|
63
77
|
try {
|
|
64
78
|
this.userId = await (0, userId_1.getRampKitUserId)();
|
|
65
79
|
}
|
|
66
80
|
catch (e2) {
|
|
67
|
-
console.log("[RampKit]
|
|
81
|
+
console.log("[RampKit] Configure: Failed to resolve user id", e2);
|
|
68
82
|
}
|
|
69
83
|
}
|
|
70
84
|
// Load onboarding data
|
|
71
|
-
console.log("[RampKit]
|
|
85
|
+
console.log("[RampKit] Configure: Starting onboarding load...");
|
|
72
86
|
try {
|
|
73
87
|
const manifestUrl = `${constants_1.MANIFEST_BASE_URL}/${config.appId}/manifest.json`;
|
|
74
|
-
console.log("[RampKit]
|
|
88
|
+
console.log("[RampKit] Configure: Fetching manifest from", manifestUrl);
|
|
75
89
|
const manifestResponse = await globalThis.fetch(manifestUrl);
|
|
76
90
|
const manifest = await manifestResponse.json();
|
|
77
91
|
if (!manifest.onboardings || manifest.onboardings.length === 0) {
|
|
@@ -79,28 +93,73 @@ class RampKitCore {
|
|
|
79
93
|
}
|
|
80
94
|
// Use the first onboarding
|
|
81
95
|
const firstOnboarding = manifest.onboardings[0];
|
|
82
|
-
console.log("[RampKit]
|
|
96
|
+
console.log("[RampKit] Configure: Using onboarding", firstOnboarding.name, firstOnboarding.id);
|
|
83
97
|
// Fetch the actual onboarding data
|
|
84
98
|
const onboardingResponse = await globalThis.fetch(firstOnboarding.url);
|
|
85
99
|
const json = await onboardingResponse.json();
|
|
86
100
|
this.onboardingData = json;
|
|
87
|
-
console.log("[RampKit]
|
|
88
|
-
console.log("[RampKit]
|
|
101
|
+
console.log("[RampKit] Configure: onboardingId", json && json.onboardingId);
|
|
102
|
+
console.log("[RampKit] Configure: Onboarding loaded");
|
|
89
103
|
}
|
|
90
104
|
catch (error) {
|
|
91
|
-
console.log("[RampKit]
|
|
105
|
+
console.log("[RampKit] Configure: Onboarding load failed", error);
|
|
92
106
|
this.onboardingData = null;
|
|
93
107
|
}
|
|
94
|
-
console.log("[RampKit]
|
|
108
|
+
console.log("[RampKit] Configure: Finished", config);
|
|
95
109
|
// Optionally auto-show onboarding overlay
|
|
96
110
|
try {
|
|
97
111
|
if (this.onboardingData && config.autoShowOnboarding) {
|
|
98
|
-
console.log("[RampKit]
|
|
112
|
+
console.log("[RampKit] Configure: Auto-show onboarding");
|
|
99
113
|
this.showOnboarding();
|
|
100
114
|
}
|
|
101
115
|
}
|
|
102
116
|
catch (_) { }
|
|
103
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* @deprecated Use `configure()` instead. This method will be removed in a future version.
|
|
120
|
+
*/
|
|
121
|
+
async init(config) {
|
|
122
|
+
console.warn("[RampKit] init() is deprecated. Use configure() instead.");
|
|
123
|
+
return this.configure(config);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Set a custom App User ID to associate with this user.
|
|
127
|
+
* This is an alias for your own user identification system.
|
|
128
|
+
*
|
|
129
|
+
* Note: This does NOT replace the RampKit-generated user ID (appUserId).
|
|
130
|
+
* RampKit will continue to use its own stable UUID for internal tracking.
|
|
131
|
+
* This custom ID is sent to the backend for you to correlate with your own user database.
|
|
132
|
+
*
|
|
133
|
+
* @param appUserID Your custom user identifier
|
|
134
|
+
*/
|
|
135
|
+
async setAppUserID(appUserID) {
|
|
136
|
+
this.appUserID = appUserID;
|
|
137
|
+
console.log("[RampKit] setAppUserID:", appUserID);
|
|
138
|
+
// Update device info with the new appUserID
|
|
139
|
+
if (this.deviceInfo) {
|
|
140
|
+
this.deviceInfo = {
|
|
141
|
+
...this.deviceInfo,
|
|
142
|
+
appUserID: appUserID,
|
|
143
|
+
};
|
|
144
|
+
// Sync updated info to backend
|
|
145
|
+
if (this.initialized) {
|
|
146
|
+
try {
|
|
147
|
+
await this.sendUserDataToBackend(this.deviceInfo);
|
|
148
|
+
console.log("[RampKit] setAppUserID: Synced to backend");
|
|
149
|
+
}
|
|
150
|
+
catch (e) {
|
|
151
|
+
console.warn("[RampKit] setAppUserID: Failed to sync to backend", e);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get the custom App User ID if one has been set.
|
|
158
|
+
* @returns The custom App User ID or null if not set
|
|
159
|
+
*/
|
|
160
|
+
getAppUserID() {
|
|
161
|
+
return this.appUserID;
|
|
162
|
+
}
|
|
104
163
|
/**
|
|
105
164
|
* Send user/device data to the /app-users endpoint
|
|
106
165
|
*/
|
|
@@ -117,14 +176,23 @@ class RampKitCore {
|
|
|
117
176
|
body: JSON.stringify(deviceInfo),
|
|
118
177
|
});
|
|
119
178
|
if (!response.ok) {
|
|
120
|
-
|
|
179
|
+
// Try to get error details from response body
|
|
180
|
+
let errorDetails = "";
|
|
181
|
+
try {
|
|
182
|
+
const errorBody = await response.text();
|
|
183
|
+
errorDetails = errorBody ? ` - ${errorBody}` : "";
|
|
184
|
+
}
|
|
185
|
+
catch (_a) {
|
|
186
|
+
// Ignore if we can't read the body
|
|
187
|
+
}
|
|
188
|
+
console.warn(`[RampKit] Configure: Failed to send user data`, `\n Status: ${response.status} ${response.statusText}`, `\n URL: ${url}`, `\n AppId: ${this.appId}`, `\n UserId: ${deviceInfo.appUserId}`, errorDetails ? `\n Error: ${errorDetails}` : "");
|
|
121
189
|
}
|
|
122
190
|
else {
|
|
123
|
-
console.log("[RampKit]
|
|
191
|
+
console.log("[RampKit] Configure: User data sent successfully");
|
|
124
192
|
}
|
|
125
193
|
}
|
|
126
194
|
catch (error) {
|
|
127
|
-
console.warn(
|
|
195
|
+
console.warn(`[RampKit] Configure: Network error sending user data`, `\n Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
128
196
|
}
|
|
129
197
|
}
|
|
130
198
|
/**
|
|
@@ -171,6 +239,13 @@ class RampKitCore {
|
|
|
171
239
|
isInitialized() {
|
|
172
240
|
return this.initialized;
|
|
173
241
|
}
|
|
242
|
+
/**
|
|
243
|
+
* Get all stored onboarding responses
|
|
244
|
+
* @returns Promise resolving to array of OnboardingResponse objects
|
|
245
|
+
*/
|
|
246
|
+
async getOnboardingResponses() {
|
|
247
|
+
return OnboardingResponseStorage_1.OnboardingResponseStorage.retrieveResponses();
|
|
248
|
+
}
|
|
174
249
|
/**
|
|
175
250
|
* Show the onboarding overlay
|
|
176
251
|
*/
|
|
@@ -323,9 +398,12 @@ class RampKitCore {
|
|
|
323
398
|
this.deviceInfo = null;
|
|
324
399
|
this.onboardingData = null;
|
|
325
400
|
this.initialized = false;
|
|
401
|
+
this.appUserID = null;
|
|
402
|
+
// Clear stored onboarding responses
|
|
403
|
+
await OnboardingResponseStorage_1.OnboardingResponseStorage.clearResponses();
|
|
326
404
|
console.log("[RampKit] Reset: Re-initializing SDK...");
|
|
327
405
|
// Re-initialize with stored config
|
|
328
|
-
await this.
|
|
406
|
+
await this.configure(this.config);
|
|
329
407
|
}
|
|
330
408
|
}
|
|
331
409
|
exports.RampKitCore = RampKitCore;
|
package/build/RampkitOverlay.js
CHANGED
|
@@ -48,6 +48,7 @@ const react_native_root_siblings_1 = __importDefault(require("react-native-root-
|
|
|
48
48
|
const react_native_pager_view_1 = __importDefault(require("react-native-pager-view"));
|
|
49
49
|
const react_native_webview_1 = require("react-native-webview");
|
|
50
50
|
const RampKitNative_1 = require("./RampKitNative");
|
|
51
|
+
const OnboardingResponseStorage_1 = require("./OnboardingResponseStorage");
|
|
51
52
|
// Reuse your injected script from App
|
|
52
53
|
exports.injectedHardening = `
|
|
53
54
|
(function(){
|
|
@@ -1652,7 +1653,7 @@ function Overlay(props) {
|
|
|
1652
1653
|
sendOnboardingStateToWebView(i);
|
|
1653
1654
|
}
|
|
1654
1655
|
}, onMessage: (ev) => {
|
|
1655
|
-
var _a, _b, _c, _d;
|
|
1656
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1656
1657
|
const raw = ev.nativeEvent.data;
|
|
1657
1658
|
console.log("raw", raw);
|
|
1658
1659
|
// Accept either raw strings or JSON payloads from your editor
|
|
@@ -1774,6 +1775,21 @@ function Overlay(props) {
|
|
|
1774
1775
|
catch (_) { }
|
|
1775
1776
|
return;
|
|
1776
1777
|
}
|
|
1778
|
+
// 7) Question answered - persist response locally
|
|
1779
|
+
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:question-answered") {
|
|
1780
|
+
const questionId = data === null || data === void 0 ? void 0 : data.questionId;
|
|
1781
|
+
if (questionId) {
|
|
1782
|
+
const response = {
|
|
1783
|
+
questionId,
|
|
1784
|
+
answer: (_c = data === null || data === void 0 ? void 0 : data.answer) !== null && _c !== void 0 ? _c : "",
|
|
1785
|
+
questionText: data === null || data === void 0 ? void 0 : data.questionText,
|
|
1786
|
+
screenName: (_d = props.screens[i]) === null || _d === void 0 ? void 0 : _d.id,
|
|
1787
|
+
answeredAt: new Date().toISOString(),
|
|
1788
|
+
};
|
|
1789
|
+
OnboardingResponseStorage_1.OnboardingResponseStorage.saveResponse(response);
|
|
1790
|
+
}
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1777
1793
|
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:continue" ||
|
|
1778
1794
|
(data === null || data === void 0 ? void 0 : data.type) === "continue") {
|
|
1779
1795
|
handleAdvance(i, (data === null || data === void 0 ? void 0 : data.animation) || "fade");
|
|
@@ -1811,7 +1827,7 @@ function Overlay(props) {
|
|
|
1811
1827
|
return;
|
|
1812
1828
|
}
|
|
1813
1829
|
}
|
|
1814
|
-
catch (
|
|
1830
|
+
catch (_g) {
|
|
1815
1831
|
// String path
|
|
1816
1832
|
if (raw === "rampkit:tap" ||
|
|
1817
1833
|
raw === "next" ||
|
|
@@ -1838,7 +1854,7 @@ function Overlay(props) {
|
|
|
1838
1854
|
if (raw === "rampkit:onboarding-finished") {
|
|
1839
1855
|
setOnboardingCompleted(true);
|
|
1840
1856
|
try {
|
|
1841
|
-
(
|
|
1857
|
+
(_e = props.onOnboardingFinished) === null || _e === void 0 ? void 0 : _e.call(props, undefined);
|
|
1842
1858
|
}
|
|
1843
1859
|
catch (_) { }
|
|
1844
1860
|
handleRequestClose({ completed: true });
|
|
@@ -1846,7 +1862,7 @@ function Overlay(props) {
|
|
|
1846
1862
|
}
|
|
1847
1863
|
if (raw === "rampkit:show-paywall") {
|
|
1848
1864
|
try {
|
|
1849
|
-
(
|
|
1865
|
+
(_f = props.onShowPaywall) === null || _f === void 0 ? void 0 : _f.call(props);
|
|
1850
1866
|
}
|
|
1851
1867
|
catch (_) { }
|
|
1852
1868
|
return;
|
package/build/constants.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export declare const STORAGE_KEYS: {
|
|
|
13
13
|
readonly INSTALL_DATE: "rk_install_date";
|
|
14
14
|
readonly LAUNCH_COUNT: "rk_launch_count";
|
|
15
15
|
readonly LAST_LAUNCH: "rk_last_launch";
|
|
16
|
+
readonly ONBOARDING_RESPONSES: "rk_onboarding_responses";
|
|
16
17
|
};
|
|
17
18
|
export declare const CAPABILITIES: readonly ["onboarding", "paywall_event_receiver", "haptic_feedback", "push_notifications"];
|
|
18
19
|
export declare const SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InV1c3RsenV2am1vY2h4a3hhdGZ4Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzU1NjQ0NjYsImV4cCI6MjA1MTE0MDQ2Nn0.5cNrph5LHmssNo39UKpULkC9n4OD5n6gsnTEQV-gwQk";
|
package/build/constants.js
CHANGED
|
@@ -18,6 +18,8 @@ exports.STORAGE_KEYS = {
|
|
|
18
18
|
INSTALL_DATE: "rk_install_date",
|
|
19
19
|
LAUNCH_COUNT: "rk_launch_count",
|
|
20
20
|
LAST_LAUNCH: "rk_last_launch",
|
|
21
|
+
// Onboarding responses (persisted)
|
|
22
|
+
ONBOARDING_RESPONSES: "rk_onboarding_responses",
|
|
21
23
|
};
|
|
22
24
|
exports.CAPABILITIES = [
|
|
23
25
|
"onboarding",
|
package/build/index.d.ts
CHANGED
|
@@ -11,5 +11,5 @@ export { default as RampKitNative } from "./RampKitNative";
|
|
|
11
11
|
export type { NativeDeviceInfo, NativeLaunchData } from "./RampKitNative";
|
|
12
12
|
export { Haptics, StoreReview, Notifications, TransactionObserver } from "./RampKitNative";
|
|
13
13
|
export type { ImpactStyle, NotificationType, NotificationOptions, NotificationPermissionResult } from "./RampKitNative";
|
|
14
|
-
export type { DeviceInfo, RampKitEvent, EventDevice, EventContext, RampKitConfig, RampKitEventName, RampKitContext, RampKitDeviceContext, RampKitUserContext, NavigationData, ScreenPosition, AppSessionStartedProperties, AppSessionEndedProperties, AppBackgroundedProperties, AppForegroundedProperties, OnboardingStartedProperties, OnboardingScreenViewedProperties, OnboardingQuestionAnsweredProperties, OnboardingCompletedProperties, OnboardingAbandonedProperties, ScreenViewProperties, CtaTapProperties, NotificationsPromptShownProperties, NotificationsResponseProperties, PaywallShownProperties, PaywallPrimaryActionTapProperties, PaywallClosedProperties, PurchaseStartedProperties, PurchaseCompletedProperties, PurchaseFailedProperties, } from "./types";
|
|
14
|
+
export type { DeviceInfo, RampKitEvent, EventDevice, EventContext, RampKitConfig, RampKitEventName, RampKitContext, RampKitDeviceContext, RampKitUserContext, NavigationData, ScreenPosition, OnboardingResponse, AppSessionStartedProperties, AppSessionEndedProperties, AppBackgroundedProperties, AppForegroundedProperties, OnboardingStartedProperties, OnboardingScreenViewedProperties, OnboardingQuestionAnsweredProperties, OnboardingCompletedProperties, OnboardingAbandonedProperties, ScreenViewProperties, CtaTapProperties, NotificationsPromptShownProperties, NotificationsResponseProperties, PaywallShownProperties, PaywallPrimaryActionTapProperties, PaywallClosedProperties, PurchaseStartedProperties, PurchaseCompletedProperties, PurchaseFailedProperties, } from "./types";
|
|
15
15
|
export { SDK_VERSION, CAPABILITIES } from "./constants";
|
package/build/types.d.ts
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export interface DeviceInfo {
|
|
5
5
|
appUserId: string;
|
|
6
|
+
/**
|
|
7
|
+
* Custom App User ID provided by the developer.
|
|
8
|
+
* This is an alias for their own user identification system.
|
|
9
|
+
* Does NOT replace appUserId - RampKit still uses its own generated ID.
|
|
10
|
+
*/
|
|
11
|
+
appUserID: string | null;
|
|
6
12
|
vendorId: string | null;
|
|
7
13
|
appSessionId: string;
|
|
8
14
|
installDate: string;
|
|
@@ -175,6 +181,16 @@ export interface RampKitConfig {
|
|
|
175
181
|
onOnboardingFinished?: (payload?: any) => void;
|
|
176
182
|
onShowPaywall?: (payload?: any) => void;
|
|
177
183
|
showPaywall?: (payload?: any) => void;
|
|
184
|
+
/**
|
|
185
|
+
* Optional custom App User ID to associate with this user.
|
|
186
|
+
* This is an alias for your own user identification system - it does NOT replace
|
|
187
|
+
* the RampKit-generated user ID (appUserId). RampKit will continue to generate
|
|
188
|
+
* and use its own stable UUID for internal tracking.
|
|
189
|
+
*
|
|
190
|
+
* Use this to link RampKit analytics with your own user database.
|
|
191
|
+
* Can also be set later via RampKit.setAppUserID().
|
|
192
|
+
*/
|
|
193
|
+
appUserID?: string;
|
|
178
194
|
}
|
|
179
195
|
/**
|
|
180
196
|
* Device context variables available in templates as ${device.xxx}
|
|
@@ -250,3 +266,18 @@ export interface ScreenPosition {
|
|
|
250
266
|
/** Row classification: "main" for main row screens, "variant" for screens below */
|
|
251
267
|
row: "main" | "variant";
|
|
252
268
|
}
|
|
269
|
+
/**
|
|
270
|
+
* Represents a single onboarding question response stored locally
|
|
271
|
+
*/
|
|
272
|
+
export interface OnboardingResponse {
|
|
273
|
+
/** Unique identifier for the question */
|
|
274
|
+
questionId: string;
|
|
275
|
+
/** The user's answer (can be any JSON-serializable value) */
|
|
276
|
+
answer: any;
|
|
277
|
+
/** Optional text of the question shown to user */
|
|
278
|
+
questionText?: string;
|
|
279
|
+
/** Screen where the question was answered */
|
|
280
|
+
screenName?: string;
|
|
281
|
+
/** ISO 8601 timestamp when the answer was recorded */
|
|
282
|
+
answeredAt: string;
|
|
283
|
+
}
|
package/package.json
CHANGED