rn-prodeeplinks 0.0.1 → 0.0.2
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 +42 -15
- package/lib/api.d.ts +2 -2
- package/lib/api.js +11 -5
- package/lib/index.d.ts +4 -2
- package/lib/index.js +47 -2
- package/lib/types.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -130,6 +130,41 @@ const deepLink = new ProDeepLink({
|
|
|
130
130
|
const result = await deepLink.getDeepLinkUrl();
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
+
### Analytics & Tracking
|
|
134
|
+
|
|
135
|
+
This SDK can optionally send deep link analytics events to our tracking service.
|
|
136
|
+
|
|
137
|
+
- When a deep link is opened via React Native `Linking.getInitialURL()`, the SDK:
|
|
138
|
+
- Resolves the URL
|
|
139
|
+
- Collects device fingerprint data
|
|
140
|
+
- Sends an internal tracking event named `pro_track` with the resolved short URL and fingerprint
|
|
141
|
+
- When a deep link is resolved via the fingerprint API, the SDK:
|
|
142
|
+
- Resolves the URL from the server
|
|
143
|
+
- Sends the same `pro_track` event with the short URL and fingerprint
|
|
144
|
+
|
|
145
|
+
You can also send custom tracking events manually:
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
import {
|
|
149
|
+
trackAnalyticsEvent,
|
|
150
|
+
CustomDeepLinkAnalyticsEvent,
|
|
151
|
+
} from 'rn-prodeeplinks';
|
|
152
|
+
|
|
153
|
+
const event: CustomDeepLinkAnalyticsEvent = {
|
|
154
|
+
licenseKey: 'your-license-key',
|
|
155
|
+
eventType: 'deeplink',
|
|
156
|
+
eventName: 'pro_track',
|
|
157
|
+
category: 'custom',
|
|
158
|
+
action: 'open',
|
|
159
|
+
label: 'My custom event',
|
|
160
|
+
properties: {
|
|
161
|
+
shortUrl: 'https://your-short-url',
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
await trackAnalyticsEvent(event);
|
|
166
|
+
```
|
|
167
|
+
|
|
133
168
|
## API Reference
|
|
134
169
|
|
|
135
170
|
### Functions
|
|
@@ -234,24 +269,16 @@ License keys are **NOT FREE**. You must:
|
|
|
234
269
|
- Invalid or expired license keys will result in API errors
|
|
235
270
|
- License keys cannot be shared or reused without authorization
|
|
236
271
|
|
|
237
|
-
### Custom License
|
|
238
|
-
For environments with a custom auth API, the license validate endpoint is:
|
|
239
|
-
|
|
240
|
-
POST {{base_url}}{{api_prefix}}/custom-deep-link/license/validate
|
|
272
|
+
### Custom License Validation (Optional)
|
|
241
273
|
|
|
242
|
-
|
|
274
|
+
In most cases you should rely on the built‑in license validation handled by this SDK.
|
|
275
|
+
If you have your own backend that integrates with our license service, you can:
|
|
243
276
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
--body '{
|
|
248
|
-
"licenseKey": "{{license_key}}",
|
|
249
|
-
"domain": "acme.com",
|
|
250
|
-
"ipAddress": "103.21.149.10"
|
|
251
|
-
}'
|
|
252
|
-
```
|
|
277
|
+
- Call your backend from your app
|
|
278
|
+
- Let your backend talk to our license service
|
|
279
|
+
- Use the result in your own business logic
|
|
253
280
|
|
|
254
|
-
|
|
281
|
+
The exact backend endpoint and payload are specific to your environment and are intentionally not exposed in this README.
|
|
255
282
|
|
|
256
283
|
## Error Handling
|
|
257
284
|
|
package/lib/api.d.ts
CHANGED
|
@@ -20,5 +20,5 @@ export declare function validateLicenseInit(licenseKey: string): Promise<{
|
|
|
20
20
|
status?: number;
|
|
21
21
|
data?: LicenseValidationApiResponse;
|
|
22
22
|
}>;
|
|
23
|
-
export declare function matchFingerprintCustom(payload: FingerprintMatchPayload, baseUrl?: string): Promise<FingerprintMatchResponse>;
|
|
24
|
-
export declare function trackCustomDeepLinkEvent(event: CustomDeepLinkAnalyticsEvent): Promise<any>;
|
|
23
|
+
export declare function matchFingerprintCustom(payload: FingerprintMatchPayload, baseUrl?: string, licenseKey?: string): Promise<FingerprintMatchResponse>;
|
|
24
|
+
export declare function trackCustomDeepLinkEvent(event: CustomDeepLinkAnalyticsEvent, licenseKey?: string): Promise<any>;
|
package/lib/api.js
CHANGED
|
@@ -26,7 +26,7 @@ async function fetchDeepLinkUrl(licenseKey, fingerprint, apiEndpoint, timeout =
|
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
const PACKAGE_NAME = 'react-native-pro-deeplink';
|
|
29
|
-
const PACKAGE_VERSION = '0.0.
|
|
29
|
+
const PACKAGE_VERSION = '0.0.2';
|
|
30
30
|
const payload = {
|
|
31
31
|
licenseKey,
|
|
32
32
|
fingerprint: fingerprint,
|
|
@@ -39,13 +39,14 @@ async function fetchDeepLinkUrl(licenseKey, fingerprint, apiEndpoint, timeout =
|
|
|
39
39
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
40
40
|
try {
|
|
41
41
|
const PACKAGE_NAME = 'react-native-pro-deeplink';
|
|
42
|
-
const PACKAGE_VERSION = '0.0.
|
|
42
|
+
const PACKAGE_VERSION = '0.0.2';
|
|
43
43
|
const response = await fetch(endpoint, {
|
|
44
44
|
method: 'POST',
|
|
45
45
|
headers: {
|
|
46
46
|
'Content-Type': 'application/json',
|
|
47
47
|
'X-Package-Name': PACKAGE_NAME,
|
|
48
48
|
'X-Package-Version': PACKAGE_VERSION,
|
|
49
|
+
'x-license-key': licenseKey,
|
|
49
50
|
},
|
|
50
51
|
body: JSON.stringify(payload),
|
|
51
52
|
signal: controller.signal,
|
|
@@ -129,7 +130,10 @@ async function validateLicenseCustom(licenseKey, opts) {
|
|
|
129
130
|
};
|
|
130
131
|
const res = await fetch(endpoint, {
|
|
131
132
|
method: 'POST',
|
|
132
|
-
headers: {
|
|
133
|
+
headers: {
|
|
134
|
+
'Content-Type': 'application/json',
|
|
135
|
+
'x-license-key': licenseKey,
|
|
136
|
+
},
|
|
133
137
|
body: JSON.stringify(body),
|
|
134
138
|
});
|
|
135
139
|
const json = (await res.json().catch(() => ({})));
|
|
@@ -168,7 +172,7 @@ async function validateLicenseInit(licenseKey) {
|
|
|
168
172
|
};
|
|
169
173
|
}
|
|
170
174
|
}
|
|
171
|
-
async function matchFingerprintCustom(payload, baseUrl) {
|
|
175
|
+
async function matchFingerprintCustom(payload, baseUrl, licenseKey) {
|
|
172
176
|
try {
|
|
173
177
|
const base = (baseUrl || CUSTOM_API_BASE_URL).trim().replace(/\/+$/, '');
|
|
174
178
|
const endpoint = `${base}/custom-deep-link/fingerprint/match`;
|
|
@@ -176,6 +180,7 @@ async function matchFingerprintCustom(payload, baseUrl) {
|
|
|
176
180
|
method: 'POST',
|
|
177
181
|
headers: {
|
|
178
182
|
'Content-Type': 'application/json',
|
|
183
|
+
...(licenseKey ? { 'x-license-key': licenseKey } : {}),
|
|
179
184
|
},
|
|
180
185
|
body: JSON.stringify(payload),
|
|
181
186
|
});
|
|
@@ -190,12 +195,13 @@ async function matchFingerprintCustom(payload, baseUrl) {
|
|
|
190
195
|
};
|
|
191
196
|
}
|
|
192
197
|
}
|
|
193
|
-
async function trackCustomDeepLinkEvent(event) {
|
|
198
|
+
async function trackCustomDeepLinkEvent(event, licenseKey) {
|
|
194
199
|
try {
|
|
195
200
|
const res = await fetch(ANALYTICS_ENDPOINT, {
|
|
196
201
|
method: 'POST',
|
|
197
202
|
headers: {
|
|
198
203
|
'Content-Type': 'application/json',
|
|
204
|
+
...(licenseKey ? { 'x-license-key': licenseKey } : {}),
|
|
199
205
|
},
|
|
200
206
|
body: JSON.stringify(event),
|
|
201
207
|
});
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InitConfig, DeepLinkResponse } from './types';
|
|
1
|
+
import { InitConfig, DeepLinkResponse, CustomDeepLinkAnalyticsEvent } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* Initialize the deep link package with license key
|
|
4
4
|
* This must be called before using getDeepLink()
|
|
@@ -53,7 +53,8 @@ export declare function isReady(): boolean;
|
|
|
53
53
|
* Useful for testing or logout scenarios
|
|
54
54
|
*/
|
|
55
55
|
export declare function reset(): void;
|
|
56
|
-
export
|
|
56
|
+
export declare function trackAnalyticsEvent(event: CustomDeepLinkAnalyticsEvent): Promise<any>;
|
|
57
|
+
export type { InitConfig, DeepLinkResponse, CustomDeepLinkAnalyticsEvent } from './types';
|
|
57
58
|
export declare class ProDeepLink {
|
|
58
59
|
private licenseKey;
|
|
59
60
|
constructor(config: InitConfig);
|
|
@@ -64,5 +65,6 @@ declare const _default: {
|
|
|
64
65
|
getDeepLink: typeof getDeepLink;
|
|
65
66
|
isReady: typeof isReady;
|
|
66
67
|
reset: typeof reset;
|
|
68
|
+
trackAnalyticsEvent: typeof trackAnalyticsEvent;
|
|
67
69
|
};
|
|
68
70
|
export default _default;
|
package/lib/index.js
CHANGED
|
@@ -5,6 +5,7 @@ exports.init = init;
|
|
|
5
5
|
exports.getDeepLink = getDeepLink;
|
|
6
6
|
exports.isReady = isReady;
|
|
7
7
|
exports.reset = reset;
|
|
8
|
+
exports.trackAnalyticsEvent = trackAnalyticsEvent;
|
|
8
9
|
const fingerprint_1 = require("./fingerprint");
|
|
9
10
|
const api_1 = require("./api");
|
|
10
11
|
const license_1 = require("./license");
|
|
@@ -60,6 +61,25 @@ async function init(config) {
|
|
|
60
61
|
};
|
|
61
62
|
}
|
|
62
63
|
}
|
|
64
|
+
async function trackDeepLinkResolved(url, source, fingerprint) {
|
|
65
|
+
const event = {
|
|
66
|
+
eventType: 'deeplink',
|
|
67
|
+
eventName: 'pro_track',
|
|
68
|
+
category: source,
|
|
69
|
+
action: 'open',
|
|
70
|
+
label: url,
|
|
71
|
+
properties: {
|
|
72
|
+
shortUrl: url,
|
|
73
|
+
source,
|
|
74
|
+
fingerprint,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
try {
|
|
78
|
+
await trackAnalyticsEvent(event);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
}
|
|
82
|
+
}
|
|
63
83
|
/**
|
|
64
84
|
* Get deep link URL from server
|
|
65
85
|
* This function automatically handles device fingerprinting internally
|
|
@@ -95,6 +115,12 @@ async function getDeepLink(callback) {
|
|
|
95
115
|
// First: try to read deep link via Linking (if app opened by URL)
|
|
96
116
|
const initialUrl = await react_native_1.Linking.getInitialURL();
|
|
97
117
|
if (initialUrl) {
|
|
118
|
+
try {
|
|
119
|
+
const fingerprint = await (0, fingerprint_1.generateDeviceFingerprint)();
|
|
120
|
+
await trackDeepLinkResolved(initialUrl, 'linking', fingerprint);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
}
|
|
98
124
|
if (callback)
|
|
99
125
|
callback(initialUrl);
|
|
100
126
|
return { success: true, url: initialUrl };
|
|
@@ -104,6 +130,13 @@ async function getDeepLink(callback) {
|
|
|
104
130
|
// Fetch deep link URL from API with retry mechanism
|
|
105
131
|
const result = await (0, api_1.fetchDeepLinkUrlWithRetry)(storedLicenseKey, fingerprint, 3, // retry attempts
|
|
106
132
|
DEFAULT_API_ENDPOINT);
|
|
133
|
+
if (result.success && result.url) {
|
|
134
|
+
try {
|
|
135
|
+
await trackDeepLinkResolved(result.url, 'api', fingerprint);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
}
|
|
139
|
+
}
|
|
107
140
|
// Call callback if provided and result is successful
|
|
108
141
|
if (callback && result.success && result.url) {
|
|
109
142
|
callback(result.url);
|
|
@@ -136,6 +169,10 @@ function reset() {
|
|
|
136
169
|
storedLicenseKey = null;
|
|
137
170
|
isInitialized = false;
|
|
138
171
|
}
|
|
172
|
+
async function trackAnalyticsEvent(event) {
|
|
173
|
+
const licenseKey = storedLicenseKey;
|
|
174
|
+
return (0, api_1.trackCustomDeepLinkEvent)(event, licenseKey || undefined);
|
|
175
|
+
}
|
|
139
176
|
// Keep backward compatibility - export class for advanced users (optional)
|
|
140
177
|
class ProDeepLink {
|
|
141
178
|
constructor(config) {
|
|
@@ -154,9 +191,17 @@ class ProDeepLink {
|
|
|
154
191
|
};
|
|
155
192
|
}
|
|
156
193
|
const fingerprint = await (0, fingerprint_1.generateDeviceFingerprint)();
|
|
157
|
-
|
|
194
|
+
const result = await (0, api_1.fetchDeepLinkUrlWithRetry)(this.licenseKey, fingerprint, 3, DEFAULT_API_ENDPOINT);
|
|
195
|
+
if (result.success && result.url) {
|
|
196
|
+
try {
|
|
197
|
+
await trackDeepLinkResolved(result.url, 'api', fingerprint);
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return result;
|
|
158
203
|
}
|
|
159
204
|
}
|
|
160
205
|
exports.ProDeepLink = ProDeepLink;
|
|
161
206
|
// Export default
|
|
162
|
-
exports.default = { init, getDeepLink, isReady, reset };
|
|
207
|
+
exports.default = { init, getDeepLink, isReady, reset, trackAnalyticsEvent };
|
package/lib/types.d.ts
CHANGED
package/package.json
CHANGED