respectlytics-react-native 2.0.0 → 2.1.0
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 +46 -24
- package/lib/commonjs/NetworkClient.js +3 -8
- package/lib/commonjs/NetworkClient.js.map +1 -1
- package/lib/commonjs/Respectlytics.js +21 -82
- package/lib/commonjs/Respectlytics.js.map +1 -1
- package/lib/commonjs/types.js +10 -8
- package/lib/commonjs/types.js.map +1 -1
- package/lib/module/NetworkClient.js +3 -8
- package/lib/module/NetworkClient.js.map +1 -1
- package/lib/module/Respectlytics.js +22 -83
- package/lib/module/Respectlytics.js.map +1 -1
- package/lib/module/types.js +10 -8
- package/lib/module/types.js.map +1 -1
- package/lib/typescript/NetworkClient.d.ts +1 -1
- package/lib/typescript/NetworkClient.d.ts.map +1 -1
- package/lib/typescript/Respectlytics.d.ts +7 -10
- package/lib/typescript/Respectlytics.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +8 -11
- package/lib/typescript/types.d.ts.map +1 -1
- package/package.json +4 -1
- package/src/NetworkClient.ts +2 -7
- package/src/Respectlytics.ts +24 -89
- package/src/types.ts +10 -13
package/README.md
CHANGED
|
@@ -6,13 +6,24 @@
|
|
|
6
6
|
|
|
7
7
|
Official Respectlytics SDK for React Native. Privacy-first, session-based analytics with automatic session management, offline event queuing, and zero device identifier collection.
|
|
8
8
|
|
|
9
|
+
## Philosophy: Return of Avoidance (ROA)
|
|
10
|
+
|
|
11
|
+
Respectlytics helps developers avoid collecting personal data in the first place. We believe the best way to handle sensitive data is to never collect it.
|
|
12
|
+
|
|
13
|
+
Our SDK collects only 4 fields:
|
|
14
|
+
- `event_name` - What happened
|
|
15
|
+
- `timestamp` - When it happened
|
|
16
|
+
- `session_id` - Groups events in a session (RAM-only, auto-rotates)
|
|
17
|
+
- `platform` - iOS or Android
|
|
18
|
+
|
|
19
|
+
That's it. No device identifiers, no fingerprinting, no persistent tracking.
|
|
20
|
+
|
|
9
21
|
## Features
|
|
10
22
|
|
|
11
23
|
- 🔒 **Privacy-First**: No device identifiers (IDFA, GAID, Android ID)
|
|
12
24
|
- ⚡ **Simple Integration**: 2 lines of code to get started
|
|
13
25
|
- 📡 **Offline Support**: Events queue automatically and sync when online
|
|
14
26
|
- 🔄 **Automatic Sessions**: RAM-only, 2-hour rotation, new session on app restart
|
|
15
|
-
- ✅ **Designed for GDPR/ePrivacy compliance** - Potentially consent-free
|
|
16
27
|
- 📱 **Cross-Platform**: iOS and Android support
|
|
17
28
|
|
|
18
29
|
## Requirements
|
|
@@ -53,7 +64,7 @@ Respectlytics.configure('your-api-key');
|
|
|
53
64
|
|
|
54
65
|
// 2. Track events
|
|
55
66
|
Respectlytics.track('purchase');
|
|
56
|
-
Respectlytics.track('view_product'
|
|
67
|
+
Respectlytics.track('view_product');
|
|
57
68
|
```
|
|
58
69
|
|
|
59
70
|
That's it! Session management is fully automatic.
|
|
@@ -68,13 +79,13 @@ Initialize the SDK with your API key. Call once at app startup.
|
|
|
68
79
|
Respectlytics.configure('your-api-key');
|
|
69
80
|
```
|
|
70
81
|
|
|
71
|
-
### `track(eventName: string
|
|
82
|
+
### `track(eventName: string)`
|
|
72
83
|
|
|
73
|
-
Track an event
|
|
84
|
+
Track an event.
|
|
74
85
|
|
|
75
86
|
```typescript
|
|
76
87
|
Respectlytics.track('button_clicked');
|
|
77
|
-
Respectlytics.track('checkout_started'
|
|
88
|
+
Respectlytics.track('checkout_started');
|
|
78
89
|
```
|
|
79
90
|
|
|
80
91
|
### `flush()`
|
|
@@ -94,13 +105,16 @@ Session IDs are managed entirely by the SDK - no configuration needed.
|
|
|
94
105
|
| **New session on app launch** | Every time your app starts, a fresh session begins |
|
|
95
106
|
| **2-hour rotation** | Sessions automatically rotate after 2 hours of use |
|
|
96
107
|
| **RAM-only storage** | Session IDs are never written to disk |
|
|
97
|
-
| **No cross-session tracking** | Each session is independent and
|
|
108
|
+
| **No cross-session tracking** | Each session is independent and anonymized |
|
|
98
109
|
|
|
99
|
-
|
|
110
|
+
## Privacy Architecture
|
|
100
111
|
|
|
101
|
-
|
|
112
|
+
Respectlytics uses anonymized identifiers stored only in device memory (RAM) that rotate automatically every two hours or upon app restart. IP addresses are processed transiently for approximate country lookup and immediately discarded—no personal data is ever persisted.
|
|
102
113
|
|
|
103
|
-
|
|
114
|
+
Our system is:
|
|
115
|
+
- **Transparent** - Clear about what data is collected
|
|
116
|
+
- **Defensible** - Minimal data surface by design
|
|
117
|
+
- **Clear** - Explicit reasoning for each field
|
|
104
118
|
|
|
105
119
|
| What we DON'T collect | Why |
|
|
106
120
|
|----------------------|-----|
|
|
@@ -108,16 +122,18 @@ Your privacy is our priority. Our mobile analytics solution is meticulously desi
|
|
|
108
122
|
| Device fingerprints | Can be used to identify users without consent |
|
|
109
123
|
| IP addresses | Processed transiently for geolocation, then discarded |
|
|
110
124
|
| Custom properties | Prevents accidental PII collection |
|
|
111
|
-
| Persistent user IDs | Cross-session tracking
|
|
125
|
+
| Persistent user IDs | Cross-session tracking is unnecessary |
|
|
112
126
|
|
|
113
127
|
| What we DO collect | Purpose |
|
|
114
128
|
|-------------------|---------|
|
|
115
129
|
| Event name | Analytics |
|
|
116
|
-
|
|
|
130
|
+
| Timestamp | When the event occurred |
|
|
117
131
|
| Random session ID (RAM-only) | Group events in a session |
|
|
118
|
-
| Platform
|
|
119
|
-
|
|
120
|
-
|
|
132
|
+
| Platform | iOS or Android |
|
|
133
|
+
|
|
134
|
+
### Server-Side Only
|
|
135
|
+
|
|
136
|
+
Country is derived server-side from IP addresses, then IP is immediately discarded.
|
|
121
137
|
|
|
122
138
|
## Automatic Behaviors
|
|
123
139
|
|
|
@@ -140,23 +156,29 @@ Events are automatically queued when offline and sent when connectivity returns:
|
|
|
140
156
|
3. Queue is flushed when connectivity is restored
|
|
141
157
|
4. Failed sends are retried with exponential backoff
|
|
142
158
|
|
|
143
|
-
## Migration from
|
|
159
|
+
## Migration from v2.0.x
|
|
144
160
|
|
|
145
|
-
###
|
|
161
|
+
### Changes in v2.1.0
|
|
146
162
|
|
|
147
|
-
- `
|
|
148
|
-
-
|
|
149
|
-
-
|
|
163
|
+
- `track()` method now takes only `eventName` - the `screen` parameter has been removed
|
|
164
|
+
- The SDK now sends only 4 fields to the API (down from 10)
|
|
165
|
+
- Deprecated fields (`screen`, `os_version`, `app_version`, `locale`, `device_type`, `region`) are no longer collected
|
|
150
166
|
|
|
151
167
|
### What to do
|
|
152
168
|
|
|
153
|
-
1.
|
|
154
|
-
|
|
155
|
-
|
|
169
|
+
1. Update any `track()` calls that pass a second parameter:
|
|
170
|
+
```typescript
|
|
171
|
+
// Before
|
|
172
|
+
Respectlytics.track('view_product', 'ProductScreen');
|
|
173
|
+
|
|
174
|
+
// After
|
|
175
|
+
Respectlytics.track('view_product');
|
|
176
|
+
```
|
|
177
|
+
2. That's it!
|
|
156
178
|
|
|
157
|
-
|
|
179
|
+
## Legal Note
|
|
158
180
|
|
|
159
|
-
|
|
181
|
+
Respectlytics provides a technical solution focused on privacy. Regulations vary by jurisdiction. Consult your legal team to determine your specific requirements.
|
|
160
182
|
|
|
161
183
|
## License
|
|
162
184
|
|
|
@@ -7,7 +7,7 @@ exports.networkClient = exports.NetworkError = exports.NetworkClient = void 0;
|
|
|
7
7
|
/**
|
|
8
8
|
* NetworkClient.ts
|
|
9
9
|
* Respectlytics React Native SDK
|
|
10
|
-
*
|
|
10
|
+
*
|
|
11
11
|
* Handles HTTP communication with the Respectlytics API.
|
|
12
12
|
* Copyright (c) 2025 Respectlytics. All rights reserved.
|
|
13
13
|
*/
|
|
@@ -130,19 +130,14 @@ class NetworkClient {
|
|
|
130
130
|
|
|
131
131
|
/**
|
|
132
132
|
* Convert Event object to API payload format
|
|
133
|
-
*
|
|
133
|
+
* v2.1.0: Only 4 fields are sent
|
|
134
134
|
*/
|
|
135
135
|
eventToPayload(event) {
|
|
136
136
|
return {
|
|
137
137
|
event_name: event.eventName,
|
|
138
138
|
timestamp: event.timestamp,
|
|
139
139
|
session_id: event.sessionId,
|
|
140
|
-
|
|
141
|
-
platform: event.platform,
|
|
142
|
-
os_version: event.osVersion,
|
|
143
|
-
app_version: event.appVersion,
|
|
144
|
-
locale: event.locale,
|
|
145
|
-
device_type: event.deviceType
|
|
140
|
+
platform: event.platform
|
|
146
141
|
};
|
|
147
142
|
}
|
|
148
143
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["API_ENDPOINT","MAX_RETRIES","TIMEOUT_MS","NetworkError","exports","NetworkClient","apiKey","configure","isConfigured","send","events","Error","NotConfigured","event","sendEvent","attempt","controller","AbortController","timeoutId","setTimeout","abort","response","fetch","method","headers","body","JSON","stringify","eventToPayload","signal","clearTimeout","ok","status","Unauthorized","BadRequest","delay","Math","pow","RateLimited","ServerError","InvalidResponse","error","message","name","Timeout","event_name","eventName","timestamp","session_id","sessionId","
|
|
1
|
+
{"version":3,"names":["API_ENDPOINT","MAX_RETRIES","TIMEOUT_MS","NetworkError","exports","NetworkClient","apiKey","configure","isConfigured","send","events","Error","NotConfigured","event","sendEvent","attempt","controller","AbortController","timeoutId","setTimeout","abort","response","fetch","method","headers","body","JSON","stringify","eventToPayload","signal","clearTimeout","ok","status","Unauthorized","BadRequest","delay","Math","pow","RateLimited","ServerError","InvalidResponse","error","message","name","Timeout","event_name","eventName","timestamp","session_id","sessionId","platform","ms","Promise","resolve","networkClient"],"sourceRoot":"../../src","sources":["NetworkClient.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -11,28 +11,27 @@ var _EventQueue = require("./EventQueue");
|
|
|
11
11
|
/**
|
|
12
12
|
* Respectlytics.ts
|
|
13
13
|
* Respectlytics React Native SDK
|
|
14
|
-
*
|
|
14
|
+
*
|
|
15
15
|
* Main entry point for the SDK.
|
|
16
16
|
* Copyright (c) 2025 Respectlytics. All rights reserved.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Main entry point for the Respectlytics SDK.
|
|
21
|
-
*
|
|
22
|
-
* v2.
|
|
21
|
+
*
|
|
22
|
+
* v2.1.0 uses session-based analytics only:
|
|
23
23
|
* - Session IDs are generated automatically in RAM
|
|
24
24
|
* - Sessions rotate every 2 hours
|
|
25
25
|
* - New session on every app restart
|
|
26
|
-
* -
|
|
27
|
-
*
|
|
26
|
+
* - Only 4 fields sent: event_name, timestamp, session_id, platform
|
|
27
|
+
*
|
|
28
28
|
* Usage:
|
|
29
29
|
* ```typescript
|
|
30
30
|
* // 1. Configure at app launch
|
|
31
31
|
* Respectlytics.configure('your-api-key');
|
|
32
|
-
*
|
|
32
|
+
*
|
|
33
33
|
* // 2. Track events
|
|
34
34
|
* Respectlytics.track('purchase');
|
|
35
|
-
* Respectlytics.track('view_product', 'ProductScreen');
|
|
36
35
|
* ```
|
|
37
36
|
*/
|
|
38
37
|
class RespectlyticsSDK {
|
|
@@ -41,12 +40,13 @@ class RespectlyticsSDK {
|
|
|
41
40
|
this.networkClient = new _NetworkClient.NetworkClient();
|
|
42
41
|
this.eventQueue = new _EventQueue.EventQueue(this.networkClient);
|
|
43
42
|
this.sessionManager = new _SessionManager.SessionManager();
|
|
43
|
+
this.platform = _reactNative.Platform.OS === 'ios' ? 'iOS' : 'Android';
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
47
|
* Initialize the SDK with your API key.
|
|
48
48
|
* Call once at app startup.
|
|
49
|
-
*
|
|
49
|
+
*
|
|
50
50
|
* @param apiKey Your Respectlytics API key from the dashboard
|
|
51
51
|
*/
|
|
52
52
|
configure(apiKey) {
|
|
@@ -57,19 +57,18 @@ class RespectlyticsSDK {
|
|
|
57
57
|
this.networkClient.configure(apiKey);
|
|
58
58
|
this.eventQueue.start();
|
|
59
59
|
this.isConfigured = true;
|
|
60
|
-
console.log('[Respectlytics] ✓ SDK configured');
|
|
60
|
+
console.log('[Respectlytics] ✓ SDK configured (v2.1.0)');
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
|
-
* Track an event
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
64
|
+
* Track an event.
|
|
65
|
+
*
|
|
66
|
+
* Custom properties are NOT supported - this is by design for privacy.
|
|
67
|
+
* The API uses a strict 4-field allowlist.
|
|
68
|
+
*
|
|
69
69
|
* @param eventName Name of the event (e.g., "purchase", "button_clicked")
|
|
70
|
-
* @param screen Optional screen name where the event occurred
|
|
71
70
|
*/
|
|
72
|
-
track(eventName
|
|
71
|
+
track(eventName) {
|
|
73
72
|
if (!this.isConfigured) {
|
|
74
73
|
console.log('[Respectlytics] ⚠️ SDK not configured. Call configure(apiKey) first.');
|
|
75
74
|
return;
|
|
@@ -82,7 +81,12 @@ class RespectlyticsSDK {
|
|
|
82
81
|
console.log('[Respectlytics] ⚠️ Event name too long (max 100 characters)');
|
|
83
82
|
return;
|
|
84
83
|
}
|
|
85
|
-
const event =
|
|
84
|
+
const event = {
|
|
85
|
+
eventName,
|
|
86
|
+
timestamp: new Date().toISOString(),
|
|
87
|
+
sessionId: this.sessionManager.getSessionId(),
|
|
88
|
+
platform: this.platform
|
|
89
|
+
};
|
|
86
90
|
this.eventQueue.add(event);
|
|
87
91
|
}
|
|
88
92
|
|
|
@@ -93,71 +97,6 @@ class RespectlyticsSDK {
|
|
|
93
97
|
async flush() {
|
|
94
98
|
await this.eventQueue.flush();
|
|
95
99
|
}
|
|
96
|
-
|
|
97
|
-
// MARK: - Private Helpers
|
|
98
|
-
|
|
99
|
-
createEvent(eventName, screen) {
|
|
100
|
-
const metadata = this.collectMetadata();
|
|
101
|
-
return {
|
|
102
|
-
eventName,
|
|
103
|
-
timestamp: new Date().toISOString(),
|
|
104
|
-
sessionId: this.sessionManager.getSessionId(),
|
|
105
|
-
screen: screen || null,
|
|
106
|
-
...metadata
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
collectMetadata() {
|
|
110
|
-
// Determine platform
|
|
111
|
-
const platform = _reactNative.Platform.OS === 'ios' ? 'iOS' : 'Android';
|
|
112
|
-
|
|
113
|
-
// Get OS version
|
|
114
|
-
const osVersion = String(_reactNative.Platform.Version);
|
|
115
|
-
|
|
116
|
-
// Get app version - try to get from native modules
|
|
117
|
-
let appVersion = 'unknown';
|
|
118
|
-
try {
|
|
119
|
-
// React Native provides app info through different native modules
|
|
120
|
-
const {
|
|
121
|
-
PlatformConstants
|
|
122
|
-
} = _reactNative.NativeModules;
|
|
123
|
-
if (PlatformConstants?.reactNativeVersion) {
|
|
124
|
-
// This is React Native version, not app version
|
|
125
|
-
// App version should come from the host app
|
|
126
|
-
}
|
|
127
|
-
// For now, use 'unknown' as we can't reliably get app version without additional dependencies
|
|
128
|
-
// In a real app, the developer would configure this
|
|
129
|
-
} catch {
|
|
130
|
-
appVersion = 'unknown';
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Get locale
|
|
134
|
-
let locale = 'en_US';
|
|
135
|
-
try {
|
|
136
|
-
// React Native doesn't expose locale directly, but we can get it from platform
|
|
137
|
-
if (_reactNative.Platform.OS === 'ios') {
|
|
138
|
-
locale = _reactNative.NativeModules.SettingsManager?.settings?.AppleLocale || _reactNative.NativeModules.SettingsManager?.settings?.AppleLanguages?.[0] || 'en_US';
|
|
139
|
-
} else {
|
|
140
|
-
locale = _reactNative.NativeModules.I18nManager?.localeIdentifier || 'en_US';
|
|
141
|
-
}
|
|
142
|
-
} catch {
|
|
143
|
-
locale = 'en_US';
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Determine device type based on screen size
|
|
147
|
-
const {
|
|
148
|
-
width,
|
|
149
|
-
height
|
|
150
|
-
} = _reactNative.Dimensions.get('window');
|
|
151
|
-
const minDimension = Math.min(width, height);
|
|
152
|
-
const deviceType = minDimension >= 600 ? 'tablet' : 'phone';
|
|
153
|
-
return {
|
|
154
|
-
platform,
|
|
155
|
-
osVersion,
|
|
156
|
-
appVersion,
|
|
157
|
-
locale,
|
|
158
|
-
deviceType
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
100
|
}
|
|
162
101
|
|
|
163
102
|
// Export singleton instance
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","_SessionManager","_NetworkClient","_EventQueue","RespectlyticsSDK","isConfigured","constructor","networkClient","NetworkClient","eventQueue","EventQueue","sessionManager","SessionManager","configure","apiKey","trim","console","log","start","track","eventName","
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_SessionManager","_NetworkClient","_EventQueue","RespectlyticsSDK","isConfigured","constructor","networkClient","NetworkClient","eventQueue","EventQueue","sessionManager","SessionManager","platform","Platform","OS","configure","apiKey","trim","console","log","start","track","eventName","length","event","timestamp","Date","toISOString","sessionId","getSessionId","add","flush","exports","Respectlytics","_default","default"],"sourceRoot":"../../src","sources":["Respectlytics.ts"],"mappings":";;;;;;AAQA,IAAAA,YAAA,GAAAC,OAAA;AAEA,IAAAC,eAAA,GAAAD,OAAA;AACA,IAAAE,cAAA,GAAAF,OAAA;AACA,IAAAG,WAAA,GAAAH,OAAA;AAZA;AACA;AACA;AACA;AACA;AACA;AACA;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMI,gBAAgB,CAAC;EACbC,YAAY,GAAG,KAAK;EAM5BC,WAAWA,CAAA,EAAG;IACZ,IAAI,CAACC,aAAa,GAAG,IAAIC,4BAAa,CAAC,CAAC;IACxC,IAAI,CAACC,UAAU,GAAG,IAAIC,sBAAU,CAAC,IAAI,CAACH,aAAa,CAAC;IACpD,IAAI,CAACI,cAAc,GAAG,IAAIC,8BAAc,CAAC,CAAC;IAC1C,IAAI,CAACC,QAAQ,GAAGC,qBAAQ,CAACC,EAAE,KAAK,KAAK,GAAG,KAAK,GAAG,SAAS;EAC3D;;EAEA;AACF;AACA;AACA;AACA;AACA;EACEC,SAASA,CAACC,MAAc,EAAQ;IAC9B,IAAI,CAACA,MAAM,IAAIA,MAAM,CAACC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;MACnCC,OAAO,CAACC,GAAG,CAAC,4CAA4C,CAAC;MACzD;IACF;IAEA,IAAI,CAACb,aAAa,CAACS,SAAS,CAACC,MAAM,CAAC;IACpC,IAAI,CAACR,UAAU,CAACY,KAAK,CAAC,CAAC;IACvB,IAAI,CAAChB,YAAY,GAAG,IAAI;IAExBc,OAAO,CAACC,GAAG,CAAC,2CAA2C,CAAC;EAC1D;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACEE,KAAKA,CAACC,SAAiB,EAAQ;IAC7B,IAAI,CAAC,IAAI,CAAClB,YAAY,EAAE;MACtBc,OAAO,CAACC,GAAG,CAAC,sEAAsE,CAAC;MACnF;IACF;IAEA,IAAI,CAACG,SAAS,IAAIA,SAAS,CAACL,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;MACzCC,OAAO,CAACC,GAAG,CAAC,+CAA+C,CAAC;MAC5D;IACF;IAEA,IAAIG,SAAS,CAACC,MAAM,GAAG,GAAG,EAAE;MAC1BL,OAAO,CAACC,GAAG,CAAC,6DAA6D,CAAC;MAC1E;IACF;IAEA,MAAMK,KAAY,GAAG;MACnBF,SAAS;MACTG,SAAS,EAAE,IAAIC,IAAI,CAAC,CAAC,CAACC,WAAW,CAAC,CAAC;MACnCC,SAAS,EAAE,IAAI,CAAClB,cAAc,CAACmB,YAAY,CAAC,CAAC;MAC7CjB,QAAQ,EAAE,IAAI,CAACA;IACjB,CAAC;IAED,IAAI,CAACJ,UAAU,CAACsB,GAAG,CAACN,KAAK,CAAC;EAC5B;;EAEA;AACF;AACA;AACA;EACE,MAAMO,KAAKA,CAAA,EAAkB;IAC3B,MAAM,IAAI,CAACvB,UAAU,CAACuB,KAAK,CAAC,CAAC;EAC/B;AACF;;AAEA;AAAAC,OAAA,CAAA7B,gBAAA,GAAAA,gBAAA;AACA,MAAM8B,aAAa,GAAG,IAAI9B,gBAAgB,CAAC,CAAC;AAAC,IAAA+B,QAAA,GAAAF,OAAA,CAAAG,OAAA,GAC9BF,aAAa","ignoreList":[]}
|
package/lib/commonjs/types.js
CHANGED
|
@@ -16,18 +16,20 @@ exports.STORAGE_KEYS = void 0;
|
|
|
16
16
|
/**
|
|
17
17
|
* Represents an analytics event - flat structure matching API payload
|
|
18
18
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
19
|
+
* v2.1.0: Only 4 fields are sent (strict API allowlist):
|
|
20
|
+
* - event_name (required)
|
|
21
|
+
* - timestamp
|
|
22
|
+
* - session_id
|
|
23
|
+
* - platform
|
|
24
|
+
*
|
|
25
|
+
* Country is derived server-side from IP (which is immediately discarded).
|
|
24
26
|
*/
|
|
25
27
|
|
|
26
28
|
/**
|
|
27
29
|
* Storage keys used by the SDK
|
|
28
|
-
*
|
|
29
|
-
* Note:
|
|
30
|
-
* Session IDs are RAM-only for
|
|
30
|
+
*
|
|
31
|
+
* Note: Only the event queue is persisted.
|
|
32
|
+
* Session IDs are RAM-only for privacy.
|
|
31
33
|
*/
|
|
32
34
|
const STORAGE_KEYS = exports.STORAGE_KEYS = {
|
|
33
35
|
EVENT_QUEUE: 'com.respectlytics.eventQueue'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["STORAGE_KEYS","exports","EVENT_QUEUE"],"sourceRoot":"../../src","sources":["types.ts"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;
|
|
1
|
+
{"version":3,"names":["STORAGE_KEYS","exports","EVENT_QUEUE"],"sourceRoot":"../../src","sources":["types.ts"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAQA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMA,YAAY,GAAAC,OAAA,CAAAD,YAAA,GAAG;EAC1BE,WAAW,EAAE;AACf,CAAU","ignoreList":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* NetworkClient.ts
|
|
3
3
|
* Respectlytics React Native SDK
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
5
|
* Handles HTTP communication with the Respectlytics API.
|
|
6
6
|
* Copyright (c) 2025 Respectlytics. All rights reserved.
|
|
7
7
|
*/
|
|
@@ -124,19 +124,14 @@ export class NetworkClient {
|
|
|
124
124
|
|
|
125
125
|
/**
|
|
126
126
|
* Convert Event object to API payload format
|
|
127
|
-
*
|
|
127
|
+
* v2.1.0: Only 4 fields are sent
|
|
128
128
|
*/
|
|
129
129
|
eventToPayload(event) {
|
|
130
130
|
return {
|
|
131
131
|
event_name: event.eventName,
|
|
132
132
|
timestamp: event.timestamp,
|
|
133
133
|
session_id: event.sessionId,
|
|
134
|
-
|
|
135
|
-
platform: event.platform,
|
|
136
|
-
os_version: event.osVersion,
|
|
137
|
-
app_version: event.appVersion,
|
|
138
|
-
locale: event.locale,
|
|
139
|
-
device_type: event.deviceType
|
|
134
|
+
platform: event.platform
|
|
140
135
|
};
|
|
141
136
|
}
|
|
142
137
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["API_ENDPOINT","MAX_RETRIES","TIMEOUT_MS","NetworkError","NetworkClient","apiKey","configure","isConfigured","send","events","Error","NotConfigured","event","sendEvent","attempt","controller","AbortController","timeoutId","setTimeout","abort","response","fetch","method","headers","body","JSON","stringify","eventToPayload","signal","clearTimeout","ok","status","Unauthorized","BadRequest","delay","Math","pow","RateLimited","ServerError","InvalidResponse","error","message","name","Timeout","event_name","eventName","timestamp","session_id","sessionId","
|
|
1
|
+
{"version":3,"names":["API_ENDPOINT","MAX_RETRIES","TIMEOUT_MS","NetworkError","NetworkClient","apiKey","configure","isConfigured","send","events","Error","NotConfigured","event","sendEvent","attempt","controller","AbortController","timeoutId","setTimeout","abort","response","fetch","method","headers","body","JSON","stringify","eventToPayload","signal","clearTimeout","ok","status","Unauthorized","BadRequest","delay","Math","pow","RateLimited","ServerError","InvalidResponse","error","message","name","Timeout","event_name","eventName","timestamp","session_id","sessionId","platform","ms","Promise","resolve","networkClient"],"sourceRoot":"../../src","sources":["NetworkClient.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,33 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Respectlytics.ts
|
|
3
3
|
* Respectlytics React Native SDK
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
5
|
* Main entry point for the SDK.
|
|
6
6
|
* Copyright (c) 2025 Respectlytics. All rights reserved.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { Platform
|
|
9
|
+
import { Platform } from 'react-native';
|
|
10
10
|
import { SessionManager } from './SessionManager';
|
|
11
11
|
import { NetworkClient } from './NetworkClient';
|
|
12
12
|
import { EventQueue } from './EventQueue';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Main entry point for the Respectlytics SDK.
|
|
16
|
-
*
|
|
17
|
-
* v2.
|
|
16
|
+
*
|
|
17
|
+
* v2.1.0 uses session-based analytics only:
|
|
18
18
|
* - Session IDs are generated automatically in RAM
|
|
19
19
|
* - Sessions rotate every 2 hours
|
|
20
20
|
* - New session on every app restart
|
|
21
|
-
* -
|
|
22
|
-
*
|
|
21
|
+
* - Only 4 fields sent: event_name, timestamp, session_id, platform
|
|
22
|
+
*
|
|
23
23
|
* Usage:
|
|
24
24
|
* ```typescript
|
|
25
25
|
* // 1. Configure at app launch
|
|
26
26
|
* Respectlytics.configure('your-api-key');
|
|
27
|
-
*
|
|
27
|
+
*
|
|
28
28
|
* // 2. Track events
|
|
29
29
|
* Respectlytics.track('purchase');
|
|
30
|
-
* Respectlytics.track('view_product', 'ProductScreen');
|
|
31
30
|
* ```
|
|
32
31
|
*/
|
|
33
32
|
class RespectlyticsSDK {
|
|
@@ -36,12 +35,13 @@ class RespectlyticsSDK {
|
|
|
36
35
|
this.networkClient = new NetworkClient();
|
|
37
36
|
this.eventQueue = new EventQueue(this.networkClient);
|
|
38
37
|
this.sessionManager = new SessionManager();
|
|
38
|
+
this.platform = Platform.OS === 'ios' ? 'iOS' : 'Android';
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* Initialize the SDK with your API key.
|
|
43
43
|
* Call once at app startup.
|
|
44
|
-
*
|
|
44
|
+
*
|
|
45
45
|
* @param apiKey Your Respectlytics API key from the dashboard
|
|
46
46
|
*/
|
|
47
47
|
configure(apiKey) {
|
|
@@ -52,19 +52,18 @@ class RespectlyticsSDK {
|
|
|
52
52
|
this.networkClient.configure(apiKey);
|
|
53
53
|
this.eventQueue.start();
|
|
54
54
|
this.isConfigured = true;
|
|
55
|
-
console.log('[Respectlytics] ✓ SDK configured');
|
|
55
|
+
console.log('[Respectlytics] ✓ SDK configured (v2.1.0)');
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
|
-
* Track an event
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
59
|
+
* Track an event.
|
|
60
|
+
*
|
|
61
|
+
* Custom properties are NOT supported - this is by design for privacy.
|
|
62
|
+
* The API uses a strict 4-field allowlist.
|
|
63
|
+
*
|
|
64
64
|
* @param eventName Name of the event (e.g., "purchase", "button_clicked")
|
|
65
|
-
* @param screen Optional screen name where the event occurred
|
|
66
65
|
*/
|
|
67
|
-
track(eventName
|
|
66
|
+
track(eventName) {
|
|
68
67
|
if (!this.isConfigured) {
|
|
69
68
|
console.log('[Respectlytics] ⚠️ SDK not configured. Call configure(apiKey) first.');
|
|
70
69
|
return;
|
|
@@ -77,7 +76,12 @@ class RespectlyticsSDK {
|
|
|
77
76
|
console.log('[Respectlytics] ⚠️ Event name too long (max 100 characters)');
|
|
78
77
|
return;
|
|
79
78
|
}
|
|
80
|
-
const event =
|
|
79
|
+
const event = {
|
|
80
|
+
eventName,
|
|
81
|
+
timestamp: new Date().toISOString(),
|
|
82
|
+
sessionId: this.sessionManager.getSessionId(),
|
|
83
|
+
platform: this.platform
|
|
84
|
+
};
|
|
81
85
|
this.eventQueue.add(event);
|
|
82
86
|
}
|
|
83
87
|
|
|
@@ -88,71 +92,6 @@ class RespectlyticsSDK {
|
|
|
88
92
|
async flush() {
|
|
89
93
|
await this.eventQueue.flush();
|
|
90
94
|
}
|
|
91
|
-
|
|
92
|
-
// MARK: - Private Helpers
|
|
93
|
-
|
|
94
|
-
createEvent(eventName, screen) {
|
|
95
|
-
const metadata = this.collectMetadata();
|
|
96
|
-
return {
|
|
97
|
-
eventName,
|
|
98
|
-
timestamp: new Date().toISOString(),
|
|
99
|
-
sessionId: this.sessionManager.getSessionId(),
|
|
100
|
-
screen: screen || null,
|
|
101
|
-
...metadata
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
collectMetadata() {
|
|
105
|
-
// Determine platform
|
|
106
|
-
const platform = Platform.OS === 'ios' ? 'iOS' : 'Android';
|
|
107
|
-
|
|
108
|
-
// Get OS version
|
|
109
|
-
const osVersion = String(Platform.Version);
|
|
110
|
-
|
|
111
|
-
// Get app version - try to get from native modules
|
|
112
|
-
let appVersion = 'unknown';
|
|
113
|
-
try {
|
|
114
|
-
// React Native provides app info through different native modules
|
|
115
|
-
const {
|
|
116
|
-
PlatformConstants
|
|
117
|
-
} = NativeModules;
|
|
118
|
-
if (PlatformConstants?.reactNativeVersion) {
|
|
119
|
-
// This is React Native version, not app version
|
|
120
|
-
// App version should come from the host app
|
|
121
|
-
}
|
|
122
|
-
// For now, use 'unknown' as we can't reliably get app version without additional dependencies
|
|
123
|
-
// In a real app, the developer would configure this
|
|
124
|
-
} catch {
|
|
125
|
-
appVersion = 'unknown';
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Get locale
|
|
129
|
-
let locale = 'en_US';
|
|
130
|
-
try {
|
|
131
|
-
// React Native doesn't expose locale directly, but we can get it from platform
|
|
132
|
-
if (Platform.OS === 'ios') {
|
|
133
|
-
locale = NativeModules.SettingsManager?.settings?.AppleLocale || NativeModules.SettingsManager?.settings?.AppleLanguages?.[0] || 'en_US';
|
|
134
|
-
} else {
|
|
135
|
-
locale = NativeModules.I18nManager?.localeIdentifier || 'en_US';
|
|
136
|
-
}
|
|
137
|
-
} catch {
|
|
138
|
-
locale = 'en_US';
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Determine device type based on screen size
|
|
142
|
-
const {
|
|
143
|
-
width,
|
|
144
|
-
height
|
|
145
|
-
} = Dimensions.get('window');
|
|
146
|
-
const minDimension = Math.min(width, height);
|
|
147
|
-
const deviceType = minDimension >= 600 ? 'tablet' : 'phone';
|
|
148
|
-
return {
|
|
149
|
-
platform,
|
|
150
|
-
osVersion,
|
|
151
|
-
appVersion,
|
|
152
|
-
locale,
|
|
153
|
-
deviceType
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
95
|
}
|
|
157
96
|
|
|
158
97
|
// Export singleton instance
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Platform","
|
|
1
|
+
{"version":3,"names":["Platform","SessionManager","NetworkClient","EventQueue","RespectlyticsSDK","isConfigured","constructor","networkClient","eventQueue","sessionManager","platform","OS","configure","apiKey","trim","console","log","start","track","eventName","length","event","timestamp","Date","toISOString","sessionId","getSessionId","add","flush","Respectlytics"],"sourceRoot":"../../src","sources":["Respectlytics.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,QAAQ,QAAQ,cAAc;AAEvC,SAASC,cAAc,QAAQ,kBAAkB;AACjD,SAASC,aAAa,QAAQ,iBAAiB;AAC/C,SAASC,UAAU,QAAQ,cAAc;;AAEzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,gBAAgB,CAAC;EACbC,YAAY,GAAG,KAAK;EAM5BC,WAAWA,CAAA,EAAG;IACZ,IAAI,CAACC,aAAa,GAAG,IAAIL,aAAa,CAAC,CAAC;IACxC,IAAI,CAACM,UAAU,GAAG,IAAIL,UAAU,CAAC,IAAI,CAACI,aAAa,CAAC;IACpD,IAAI,CAACE,cAAc,GAAG,IAAIR,cAAc,CAAC,CAAC;IAC1C,IAAI,CAACS,QAAQ,GAAGV,QAAQ,CAACW,EAAE,KAAK,KAAK,GAAG,KAAK,GAAG,SAAS;EAC3D;;EAEA;AACF;AACA;AACA;AACA;AACA;EACEC,SAASA,CAACC,MAAc,EAAQ;IAC9B,IAAI,CAACA,MAAM,IAAIA,MAAM,CAACC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;MACnCC,OAAO,CAACC,GAAG,CAAC,4CAA4C,CAAC;MACzD;IACF;IAEA,IAAI,CAACT,aAAa,CAACK,SAAS,CAACC,MAAM,CAAC;IACpC,IAAI,CAACL,UAAU,CAACS,KAAK,CAAC,CAAC;IACvB,IAAI,CAACZ,YAAY,GAAG,IAAI;IAExBU,OAAO,CAACC,GAAG,CAAC,2CAA2C,CAAC;EAC1D;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACEE,KAAKA,CAACC,SAAiB,EAAQ;IAC7B,IAAI,CAAC,IAAI,CAACd,YAAY,EAAE;MACtBU,OAAO,CAACC,GAAG,CAAC,sEAAsE,CAAC;MACnF;IACF;IAEA,IAAI,CAACG,SAAS,IAAIA,SAAS,CAACL,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;MACzCC,OAAO,CAACC,GAAG,CAAC,+CAA+C,CAAC;MAC5D;IACF;IAEA,IAAIG,SAAS,CAACC,MAAM,GAAG,GAAG,EAAE;MAC1BL,OAAO,CAACC,GAAG,CAAC,6DAA6D,CAAC;MAC1E;IACF;IAEA,MAAMK,KAAY,GAAG;MACnBF,SAAS;MACTG,SAAS,EAAE,IAAIC,IAAI,CAAC,CAAC,CAACC,WAAW,CAAC,CAAC;MACnCC,SAAS,EAAE,IAAI,CAAChB,cAAc,CAACiB,YAAY,CAAC,CAAC;MAC7ChB,QAAQ,EAAE,IAAI,CAACA;IACjB,CAAC;IAED,IAAI,CAACF,UAAU,CAACmB,GAAG,CAACN,KAAK,CAAC;EAC5B;;EAEA;AACF;AACA;AACA;EACE,MAAMO,KAAKA,CAAA,EAAkB;IAC3B,MAAM,IAAI,CAACpB,UAAU,CAACoB,KAAK,CAAC,CAAC;EAC/B;AACF;;AAEA;AACA,MAAMC,aAAa,GAAG,IAAIzB,gBAAgB,CAAC,CAAC;AAC5C,eAAeyB,aAAa;AAC5B,SAASzB,gBAAgB","ignoreList":[]}
|
package/lib/module/types.js
CHANGED
|
@@ -10,18 +10,20 @@
|
|
|
10
10
|
/**
|
|
11
11
|
* Represents an analytics event - flat structure matching API payload
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* v2.1.0: Only 4 fields are sent (strict API allowlist):
|
|
14
|
+
* - event_name (required)
|
|
15
|
+
* - timestamp
|
|
16
|
+
* - session_id
|
|
17
|
+
* - platform
|
|
18
|
+
*
|
|
19
|
+
* Country is derived server-side from IP (which is immediately discarded).
|
|
18
20
|
*/
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* Storage keys used by the SDK
|
|
22
|
-
*
|
|
23
|
-
* Note:
|
|
24
|
-
* Session IDs are RAM-only for
|
|
24
|
+
*
|
|
25
|
+
* Note: Only the event queue is persisted.
|
|
26
|
+
* Session IDs are RAM-only for privacy.
|
|
25
27
|
*/
|
|
26
28
|
export const STORAGE_KEYS = {
|
|
27
29
|
EVENT_QUEUE: 'com.respectlytics.eventQueue'
|
package/lib/module/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["STORAGE_KEYS","EVENT_QUEUE"],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;
|
|
1
|
+
{"version":3,"names":["STORAGE_KEYS","EVENT_QUEUE"],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMA,YAAY,GAAG;EAC1BC,WAAW,EAAE;AACf,CAAU","ignoreList":[]}
|
|
@@ -36,7 +36,7 @@ export declare class NetworkClient {
|
|
|
36
36
|
private sendEvent;
|
|
37
37
|
/**
|
|
38
38
|
* Convert Event object to API payload format
|
|
39
|
-
*
|
|
39
|
+
* v2.1.0: Only 4 fields are sent
|
|
40
40
|
*/
|
|
41
41
|
private eventToPayload;
|
|
42
42
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkClient.d.ts","sourceRoot":"","sources":["../../src/NetworkClient.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAMhC,oBAAY,YAAY;IACtB,aAAa,mBAAmB;IAChC,eAAe,qBAAqB;IACpC,YAAY,iBAAiB;IAC7B,UAAU,gBAAgB;IAC1B,WAAW,iBAAiB;IAC5B,WAAW,iBAAiB;IAC5B,YAAY,kBAAkB;IAC9B,OAAO,YAAY;CACpB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAuB;IAErC;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAU1C;;OAEG;YACW,SAAS;IAgFvB;;;OAGG;IACH,OAAO,CAAC,cAAc;
|
|
1
|
+
{"version":3,"file":"NetworkClient.d.ts","sourceRoot":"","sources":["../../src/NetworkClient.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAMhC,oBAAY,YAAY;IACtB,aAAa,mBAAmB;IAChC,eAAe,qBAAqB;IACpC,YAAY,iBAAiB;IAC7B,UAAU,gBAAgB;IAC1B,WAAW,iBAAiB;IAC5B,WAAW,iBAAiB;IAC5B,YAAY,kBAAkB;IAC9B,OAAO,YAAY;CACpB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAuB;IAErC;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAU1C;;OAEG;YACW,SAAS;IAgFvB;;;OAGG;IACH,OAAO,CAAC,cAAc;IAStB;;OAEG;IACH,OAAO,CAAC,KAAK;CAGd;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC"}
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
/**
|
|
9
9
|
* Main entry point for the Respectlytics SDK.
|
|
10
10
|
*
|
|
11
|
-
* v2.
|
|
11
|
+
* v2.1.0 uses session-based analytics only:
|
|
12
12
|
* - Session IDs are generated automatically in RAM
|
|
13
13
|
* - Sessions rotate every 2 hours
|
|
14
14
|
* - New session on every app restart
|
|
15
|
-
* -
|
|
15
|
+
* - Only 4 fields sent: event_name, timestamp, session_id, platform
|
|
16
16
|
*
|
|
17
17
|
* Usage:
|
|
18
18
|
* ```typescript
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
*
|
|
22
22
|
* // 2. Track events
|
|
23
23
|
* Respectlytics.track('purchase');
|
|
24
|
-
* Respectlytics.track('view_product', 'ProductScreen');
|
|
25
24
|
* ```
|
|
26
25
|
*/
|
|
27
26
|
declare class RespectlyticsSDK {
|
|
@@ -29,6 +28,7 @@ declare class RespectlyticsSDK {
|
|
|
29
28
|
private networkClient;
|
|
30
29
|
private eventQueue;
|
|
31
30
|
private sessionManager;
|
|
31
|
+
private platform;
|
|
32
32
|
constructor();
|
|
33
33
|
/**
|
|
34
34
|
* Initialize the SDK with your API key.
|
|
@@ -38,22 +38,19 @@ declare class RespectlyticsSDK {
|
|
|
38
38
|
*/
|
|
39
39
|
configure(apiKey: string): void;
|
|
40
40
|
/**
|
|
41
|
-
* Track an event
|
|
41
|
+
* Track an event.
|
|
42
42
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
43
|
+
* Custom properties are NOT supported - this is by design for privacy.
|
|
44
|
+
* The API uses a strict 4-field allowlist.
|
|
45
45
|
*
|
|
46
46
|
* @param eventName Name of the event (e.g., "purchase", "button_clicked")
|
|
47
|
-
* @param screen Optional screen name where the event occurred
|
|
48
47
|
*/
|
|
49
|
-
track(eventName: string
|
|
48
|
+
track(eventName: string): void;
|
|
50
49
|
/**
|
|
51
50
|
* Force send all queued events immediately.
|
|
52
51
|
* Rarely needed - the SDK auto-flushes every 30 seconds or when the queue reaches 10 events.
|
|
53
52
|
*/
|
|
54
53
|
flush(): Promise<void>;
|
|
55
|
-
private createEvent;
|
|
56
|
-
private collectMetadata;
|
|
57
54
|
}
|
|
58
55
|
declare const Respectlytics: RespectlyticsSDK;
|
|
59
56
|
export default Respectlytics;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Respectlytics.d.ts","sourceRoot":"","sources":["../../src/Respectlytics.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH
|
|
1
|
+
{"version":3,"file":"Respectlytics.d.ts","sourceRoot":"","sources":["../../src/Respectlytics.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH;;;;;;;;;;;;;;;;;GAiBG;AACH,cAAM,gBAAgB;IACpB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAS;;IASzB;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAa/B;;;;;;;OAOG;IACH,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IA0B9B;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B;AAGD,QAAA,MAAM,aAAa,kBAAyB,CAAC;AAC7C,eAAe,aAAa,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -9,28 +9,25 @@
|
|
|
9
9
|
/**
|
|
10
10
|
* Represents an analytics event - flat structure matching API payload
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* v2.1.0: Only 4 fields are sent (strict API allowlist):
|
|
13
|
+
* - event_name (required)
|
|
14
|
+
* - timestamp
|
|
15
|
+
* - session_id
|
|
16
|
+
* - platform
|
|
15
17
|
*
|
|
16
|
-
*
|
|
18
|
+
* Country is derived server-side from IP (which is immediately discarded).
|
|
17
19
|
*/
|
|
18
20
|
export interface Event {
|
|
19
21
|
eventName: string;
|
|
20
22
|
timestamp: string;
|
|
21
23
|
sessionId: string;
|
|
22
|
-
screen: string | null;
|
|
23
24
|
platform: string;
|
|
24
|
-
osVersion: string;
|
|
25
|
-
appVersion: string;
|
|
26
|
-
locale: string;
|
|
27
|
-
deviceType: string;
|
|
28
25
|
}
|
|
29
26
|
/**
|
|
30
27
|
* Storage keys used by the SDK
|
|
31
28
|
*
|
|
32
|
-
* Note:
|
|
33
|
-
* Session IDs are RAM-only for
|
|
29
|
+
* Note: Only the event queue is persisted.
|
|
30
|
+
* Session IDs are RAM-only for privacy.
|
|
34
31
|
*/
|
|
35
32
|
export declare const STORAGE_KEYS: {
|
|
36
33
|
readonly EVENT_QUEUE: "com.respectlytics.eventQueue";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,WAAW,KAAK;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY;;CAEf,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "respectlytics-react-native",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Official Respectlytics SDK for React Native. Privacy-first analytics with automatic session management, offline event queuing, and zero device identifier collection.",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -47,11 +47,14 @@
|
|
|
47
47
|
"registry": "https://registry.npmjs.org/"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
+
"@babel/preset-env": "^7.28.5",
|
|
51
|
+
"@babel/preset-typescript": "^7.28.5",
|
|
50
52
|
"@react-native-async-storage/async-storage": "^2.0.0",
|
|
51
53
|
"@react-native-community/netinfo": "^11.3.0",
|
|
52
54
|
"@types/jest": "^29.5.12",
|
|
53
55
|
"@types/react": "^18.2.0",
|
|
54
56
|
"@types/react-native": "^0.72.0",
|
|
57
|
+
"babel-jest": "^30.2.0",
|
|
55
58
|
"eslint": "^8.56.0",
|
|
56
59
|
"jest": "^29.7.0",
|
|
57
60
|
"react": "^18.2.0",
|
package/src/NetworkClient.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* NetworkClient.ts
|
|
3
3
|
* Respectlytics React Native SDK
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
5
|
* Handles HTTP communication with the Respectlytics API.
|
|
6
6
|
* Copyright (c) 2025 Respectlytics. All rights reserved.
|
|
7
7
|
*/
|
|
@@ -138,19 +138,14 @@ export class NetworkClient {
|
|
|
138
138
|
|
|
139
139
|
/**
|
|
140
140
|
* Convert Event object to API payload format
|
|
141
|
-
*
|
|
141
|
+
* v2.1.0: Only 4 fields are sent
|
|
142
142
|
*/
|
|
143
143
|
private eventToPayload(event: Event): Record<string, unknown> {
|
|
144
144
|
return {
|
|
145
145
|
event_name: event.eventName,
|
|
146
146
|
timestamp: event.timestamp,
|
|
147
147
|
session_id: event.sessionId,
|
|
148
|
-
screen: event.screen || undefined,
|
|
149
148
|
platform: event.platform,
|
|
150
|
-
os_version: event.osVersion,
|
|
151
|
-
app_version: event.appVersion,
|
|
152
|
-
locale: event.locale,
|
|
153
|
-
device_type: event.deviceType,
|
|
154
149
|
};
|
|
155
150
|
}
|
|
156
151
|
|
package/src/Respectlytics.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Respectlytics.ts
|
|
3
3
|
* Respectlytics React Native SDK
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
5
|
* Main entry point for the SDK.
|
|
6
6
|
* Copyright (c) 2025 Respectlytics. All rights reserved.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { Platform
|
|
9
|
+
import { Platform } from 'react-native';
|
|
10
10
|
import { Event } from './types';
|
|
11
11
|
import { SessionManager } from './SessionManager';
|
|
12
12
|
import { NetworkClient } from './NetworkClient';
|
|
@@ -14,21 +14,20 @@ import { EventQueue } from './EventQueue';
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Main entry point for the Respectlytics SDK.
|
|
17
|
-
*
|
|
18
|
-
* v2.
|
|
17
|
+
*
|
|
18
|
+
* v2.1.0 uses session-based analytics only:
|
|
19
19
|
* - Session IDs are generated automatically in RAM
|
|
20
20
|
* - Sessions rotate every 2 hours
|
|
21
21
|
* - New session on every app restart
|
|
22
|
-
* -
|
|
23
|
-
*
|
|
22
|
+
* - Only 4 fields sent: event_name, timestamp, session_id, platform
|
|
23
|
+
*
|
|
24
24
|
* Usage:
|
|
25
25
|
* ```typescript
|
|
26
26
|
* // 1. Configure at app launch
|
|
27
27
|
* Respectlytics.configure('your-api-key');
|
|
28
|
-
*
|
|
28
|
+
*
|
|
29
29
|
* // 2. Track events
|
|
30
30
|
* Respectlytics.track('purchase');
|
|
31
|
-
* Respectlytics.track('view_product', 'ProductScreen');
|
|
32
31
|
* ```
|
|
33
32
|
*/
|
|
34
33
|
class RespectlyticsSDK {
|
|
@@ -36,17 +35,19 @@ class RespectlyticsSDK {
|
|
|
36
35
|
private networkClient: NetworkClient;
|
|
37
36
|
private eventQueue: EventQueue;
|
|
38
37
|
private sessionManager: SessionManager;
|
|
38
|
+
private platform: string;
|
|
39
39
|
|
|
40
40
|
constructor() {
|
|
41
41
|
this.networkClient = new NetworkClient();
|
|
42
42
|
this.eventQueue = new EventQueue(this.networkClient);
|
|
43
43
|
this.sessionManager = new SessionManager();
|
|
44
|
+
this.platform = Platform.OS === 'ios' ? 'iOS' : 'Android';
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
/**
|
|
47
48
|
* Initialize the SDK with your API key.
|
|
48
49
|
* Call once at app startup.
|
|
49
|
-
*
|
|
50
|
+
*
|
|
50
51
|
* @param apiKey Your Respectlytics API key from the dashboard
|
|
51
52
|
*/
|
|
52
53
|
configure(apiKey: string): void {
|
|
@@ -59,19 +60,18 @@ class RespectlyticsSDK {
|
|
|
59
60
|
this.eventQueue.start();
|
|
60
61
|
this.isConfigured = true;
|
|
61
62
|
|
|
62
|
-
console.log('[Respectlytics] ✓ SDK configured');
|
|
63
|
+
console.log('[Respectlytics] ✓ SDK configured (v2.1.0)');
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
/**
|
|
66
|
-
* Track an event
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
67
|
+
* Track an event.
|
|
68
|
+
*
|
|
69
|
+
* Custom properties are NOT supported - this is by design for privacy.
|
|
70
|
+
* The API uses a strict 4-field allowlist.
|
|
71
|
+
*
|
|
71
72
|
* @param eventName Name of the event (e.g., "purchase", "button_clicked")
|
|
72
|
-
* @param screen Optional screen name where the event occurred
|
|
73
73
|
*/
|
|
74
|
-
track(eventName: string
|
|
74
|
+
track(eventName: string): void {
|
|
75
75
|
if (!this.isConfigured) {
|
|
76
76
|
console.log('[Respectlytics] ⚠️ SDK not configured. Call configure(apiKey) first.');
|
|
77
77
|
return;
|
|
@@ -87,7 +87,13 @@ class RespectlyticsSDK {
|
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
const event =
|
|
90
|
+
const event: Event = {
|
|
91
|
+
eventName,
|
|
92
|
+
timestamp: new Date().toISOString(),
|
|
93
|
+
sessionId: this.sessionManager.getSessionId(),
|
|
94
|
+
platform: this.platform,
|
|
95
|
+
};
|
|
96
|
+
|
|
91
97
|
this.eventQueue.add(event);
|
|
92
98
|
}
|
|
93
99
|
|
|
@@ -98,77 +104,6 @@ class RespectlyticsSDK {
|
|
|
98
104
|
async flush(): Promise<void> {
|
|
99
105
|
await this.eventQueue.flush();
|
|
100
106
|
}
|
|
101
|
-
|
|
102
|
-
// MARK: - Private Helpers
|
|
103
|
-
|
|
104
|
-
private createEvent(eventName: string, screen?: string): Event {
|
|
105
|
-
const metadata = this.collectMetadata();
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
eventName,
|
|
109
|
-
timestamp: new Date().toISOString(),
|
|
110
|
-
sessionId: this.sessionManager.getSessionId(),
|
|
111
|
-
screen: screen || null,
|
|
112
|
-
...metadata,
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
private collectMetadata(): {
|
|
117
|
-
platform: string;
|
|
118
|
-
osVersion: string;
|
|
119
|
-
appVersion: string;
|
|
120
|
-
locale: string;
|
|
121
|
-
deviceType: string;
|
|
122
|
-
} {
|
|
123
|
-
// Determine platform
|
|
124
|
-
const platform = Platform.OS === 'ios' ? 'iOS' : 'Android';
|
|
125
|
-
|
|
126
|
-
// Get OS version
|
|
127
|
-
const osVersion = String(Platform.Version);
|
|
128
|
-
|
|
129
|
-
// Get app version - try to get from native modules
|
|
130
|
-
let appVersion = 'unknown';
|
|
131
|
-
try {
|
|
132
|
-
// React Native provides app info through different native modules
|
|
133
|
-
const { PlatformConstants } = NativeModules;
|
|
134
|
-
if (PlatformConstants?.reactNativeVersion) {
|
|
135
|
-
// This is React Native version, not app version
|
|
136
|
-
// App version should come from the host app
|
|
137
|
-
}
|
|
138
|
-
// For now, use 'unknown' as we can't reliably get app version without additional dependencies
|
|
139
|
-
// In a real app, the developer would configure this
|
|
140
|
-
} catch {
|
|
141
|
-
appVersion = 'unknown';
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Get locale
|
|
145
|
-
let locale = 'en_US';
|
|
146
|
-
try {
|
|
147
|
-
// React Native doesn't expose locale directly, but we can get it from platform
|
|
148
|
-
if (Platform.OS === 'ios') {
|
|
149
|
-
locale = NativeModules.SettingsManager?.settings?.AppleLocale ||
|
|
150
|
-
NativeModules.SettingsManager?.settings?.AppleLanguages?.[0] ||
|
|
151
|
-
'en_US';
|
|
152
|
-
} else {
|
|
153
|
-
locale = NativeModules.I18nManager?.localeIdentifier || 'en_US';
|
|
154
|
-
}
|
|
155
|
-
} catch {
|
|
156
|
-
locale = 'en_US';
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Determine device type based on screen size
|
|
160
|
-
const { width, height } = Dimensions.get('window');
|
|
161
|
-
const minDimension = Math.min(width, height);
|
|
162
|
-
const deviceType = minDimension >= 600 ? 'tablet' : 'phone';
|
|
163
|
-
|
|
164
|
-
return {
|
|
165
|
-
platform,
|
|
166
|
-
osVersion,
|
|
167
|
-
appVersion,
|
|
168
|
-
locale,
|
|
169
|
-
deviceType,
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
107
|
}
|
|
173
108
|
|
|
174
109
|
// Export singleton instance
|
package/src/types.ts
CHANGED
|
@@ -10,29 +10,26 @@
|
|
|
10
10
|
/**
|
|
11
11
|
* Represents an analytics event - flat structure matching API payload
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* v2.1.0: Only 4 fields are sent (strict API allowlist):
|
|
14
|
+
* - event_name (required)
|
|
15
|
+
* - timestamp
|
|
16
|
+
* - session_id
|
|
17
|
+
* - platform
|
|
18
|
+
*
|
|
19
|
+
* Country is derived server-side from IP (which is immediately discarded).
|
|
18
20
|
*/
|
|
19
21
|
export interface Event {
|
|
20
22
|
eventName: string;
|
|
21
23
|
timestamp: string;
|
|
22
24
|
sessionId: string;
|
|
23
|
-
screen: string | null;
|
|
24
25
|
platform: string;
|
|
25
|
-
osVersion: string;
|
|
26
|
-
appVersion: string;
|
|
27
|
-
locale: string;
|
|
28
|
-
deviceType: string;
|
|
29
26
|
}
|
|
30
27
|
|
|
31
28
|
/**
|
|
32
29
|
* Storage keys used by the SDK
|
|
33
|
-
*
|
|
34
|
-
* Note:
|
|
35
|
-
* Session IDs are RAM-only for
|
|
30
|
+
*
|
|
31
|
+
* Note: Only the event queue is persisted.
|
|
32
|
+
* Session IDs are RAM-only for privacy.
|
|
36
33
|
*/
|
|
37
34
|
export const STORAGE_KEYS = {
|
|
38
35
|
EVENT_QUEUE: 'com.respectlytics.eventQueue',
|