adsparkle-react-native 0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Viralif
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,286 @@
1
+ # adsparkle-react-native
2
+
3
+ React Native client SDK for the Viralif / AdBird affiliate attribution platform.
4
+ Sends postback events to the tracking API and handles deep link click_id attribution.
5
+
6
+ ---
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install adsparkle-react-native @react-native-async-storage/async-storage
12
+ ```
13
+
14
+ For Expo managed workflow:
15
+
16
+ ```bash
17
+ npx expo install adsparkle-react-native @react-native-async-storage/async-storage
18
+ ```
19
+
20
+ > **Note:** `@react-native-async-storage/async-storage` is a required peer dependency.
21
+ > For bare React Native, follow the [AsyncStorage setup guide](https://react-native-async-storage.github.io/async-storage/docs/install/).
22
+
23
+ ---
24
+
25
+ ## Security note
26
+
27
+ The SDK uses a **publishable company key** (`co_...` prefix).
28
+ This key is **safe to embed in your app binary** — it is not a secret.
29
+ No HMAC secret or private key is ever used or required.
30
+
31
+ ---
32
+
33
+ ## Quick start
34
+
35
+ ### 1. Configure (call once at app startup)
36
+
37
+ ```tsx
38
+ // app/_layout.tsx or App.tsx
39
+ import AdSparkle from 'adsparkle-react-native';
40
+
41
+ AdSparkle.configure({
42
+ companyKey: 'co_your_key_here',
43
+ // baseUrl: 'https://api.viralif.co', // default, no need to set
44
+ debug: __DEV__,
45
+ });
46
+ ```
47
+
48
+ `configure()` is async; it hydrates persisted state and flushes any events that
49
+ failed in the previous session. You can await it if you need to guarantee
50
+ completion before the first screen renders.
51
+
52
+ ### 2. Set user ID (after login/registration)
53
+
54
+ ```ts
55
+ AdSparkle.setUserId('internal-user-id-123');
56
+ ```
57
+
58
+ ### 3. Handle deep links
59
+
60
+ The SDK does **not** attach itself to `Linking` automatically.
61
+ You must call `handleDeepLink` from your own Linking wiring.
62
+
63
+ #### Option A — manual wiring (recommended, full control)
64
+
65
+ ```tsx
66
+ import { useEffect } from 'react';
67
+ import { Linking } from 'react-native';
68
+ import AdSparkle from 'adsparkle-react-native';
69
+
70
+ export default function RootLayout() {
71
+ useEffect(() => {
72
+ // Cold start (app opened via deep link)
73
+ Linking.getInitialURL().then((url) => {
74
+ if (url) AdSparkle.handleDeepLink(url);
75
+ });
76
+
77
+ // Warm start / foreground
78
+ const subscription = Linking.addEventListener('url', ({ url }) => {
79
+ AdSparkle.handleDeepLink(url);
80
+ });
81
+
82
+ return () => subscription.remove();
83
+ }, []);
84
+
85
+ // ...
86
+ }
87
+ ```
88
+
89
+ #### Option B — attachLinking helper
90
+
91
+ ```tsx
92
+ import { Linking } from 'react-native';
93
+ import AdSparkle from 'adsparkle-react-native';
94
+
95
+ // In your root component's useEffect:
96
+ AdSparkle.attachLinking(Linking);
97
+
98
+ // On unmount:
99
+ AdSparkle.detachLinking();
100
+ ```
101
+
102
+ #### Expo Router + expo-linking
103
+
104
+ ```tsx
105
+ import * as Linking from 'expo-linking';
106
+ import { useEffect } from 'react';
107
+ import AdSparkle from 'adsparkle-react-native';
108
+
109
+ export default function RootLayout() {
110
+ const url = Linking.useURL();
111
+
112
+ useEffect(() => {
113
+ if (url) AdSparkle.handleDeepLink(url);
114
+ }, [url]);
115
+
116
+ // ...
117
+ }
118
+ ```
119
+
120
+ The SDK looks for the `click_id` query parameter in the URL:
121
+
122
+ ```
123
+ myapp://open?click_id=abc-123-uuid
124
+ https://example.com/promo?click_id=abc-123-uuid&utm_source=viralif
125
+ ```
126
+
127
+ Up to **10** unique click IDs are stored in a chain; duplicates are silently ignored.
128
+
129
+ ---
130
+
131
+ ## Tracking events
132
+
133
+ ### Generic track()
134
+
135
+ ```ts
136
+ await AdSparkle.track('purchase', {
137
+ transactionId: 'txn_abc',
138
+ amount: 49.99,
139
+ currency: 'USD',
140
+ productIds: ['prod_1', 'prod_2'],
141
+ customParams: { plan: 'premium' },
142
+ });
143
+ ```
144
+
145
+ ### Convenience methods
146
+
147
+ ```ts
148
+ await AdSparkle.trackInstall();
149
+ await AdSparkle.trackSignUp();
150
+ await AdSparkle.trackLogin();
151
+ await AdSparkle.trackDownload();
152
+
153
+ await AdSparkle.trackPurchase({
154
+ transactionId: 'txn_abc', // required
155
+ amount: 49.99,
156
+ currency: 'USD',
157
+ });
158
+
159
+ await AdSparkle.trackSubscription({
160
+ transactionId: 'sub_xyz', // required
161
+ amount: 9.99,
162
+ currency: 'EUR',
163
+ });
164
+
165
+ await AdSparkle.trackRefund({
166
+ transactionId: 'txn_abc', // required
167
+ });
168
+ ```
169
+
170
+ ### Supported event types
171
+
172
+ | Event type | transactionId | amount / currency | Notes |
173
+ |----------------|:-------------:|:-----------------:|------------------------------|
174
+ | `install` | | | Fire on first app launch |
175
+ | `sign_up` | | | After successful registration|
176
+ | `login` | | | After successful login |
177
+ | `download` | | | In-app content download |
178
+ | `purchase` | required | recommended | One-time purchase |
179
+ | `subscription` | required | recommended | Recurring subscription start |
180
+ | `refund` | required | | Order / subscription refund |
181
+
182
+ Only the event types listed above are accepted.
183
+ Derived or custom event type strings are rejected (no-op with a warning in debug mode).
184
+
185
+ ---
186
+
187
+ ## No-op behaviour
188
+
189
+ `track()` is **always safe to call** — it never throws.
190
+
191
+ - If `configure()` has not been called: warning logged, no network call.
192
+ - If `userId` is not set: warning logged, no network call.
193
+ - If `clickId` is not set: warning logged, no network call.
194
+
195
+ Set `debug: true` in `configure()` to see all warnings in the console.
196
+
197
+ ---
198
+
199
+ ## Retry and offline queue
200
+
201
+ - On **5xx** or **network error**: the SDK retries up to **3 times** with exponential
202
+ backoff starting at 500 ms.
203
+ - If all retries fail, the event is persisted to an **AsyncStorage queue**.
204
+ - The queue is flushed automatically on the next `configure()` call and before
205
+ every subsequent `track()` call.
206
+ - **4xx** responses (bad request, auth failure) are **not** retried.
207
+
208
+ ---
209
+
210
+ ## API reference
211
+
212
+ ```ts
213
+ // Setup
214
+ AdSparkle.configure(config: AdSparkleConfig): Promise<void>
215
+
216
+ // Identity
217
+ AdSparkle.setUserId(userId: string): Promise<void>
218
+
219
+ // Attribution
220
+ AdSparkle.handleDeepLink(url: string): Promise<void>
221
+ AdSparkle.setClickId(clickId: string): Promise<void>
222
+ AdSparkle.getClickId(): string | null
223
+
224
+ // Tracking
225
+ AdSparkle.track(eventType: EventType, params?: TrackParams): Promise<void>
226
+ AdSparkle.trackInstall(params?: TrackParams): Promise<void>
227
+ AdSparkle.trackSignUp(params?: TrackParams): Promise<void>
228
+ AdSparkle.trackLogin(params?: TrackParams): Promise<void>
229
+ AdSparkle.trackDownload(params?: TrackParams): Promise<void>
230
+ AdSparkle.trackPurchase(params: TrackParams & { transactionId: string }): Promise<void>
231
+ AdSparkle.trackSubscription(params: TrackParams & { transactionId: string }): Promise<void>
232
+ AdSparkle.trackRefund(params: TrackParams & { transactionId: string }): Promise<void>
233
+
234
+ // Linking helpers (optional)
235
+ AdSparkle.attachLinking(Linking: LinkingModule): Promise<void>
236
+ AdSparkle.detachLinking(): void
237
+ ```
238
+
239
+ ### AdSparkleConfig
240
+
241
+ | Property | Type | Required | Default |
242
+ |--------------|-----------|:--------:|------------------------------|
243
+ | `companyKey` | `string` | yes | — |
244
+ | `baseUrl` | `string` | no | `https://api.viralif.co` |
245
+ | `debug` | `boolean` | no | `false` |
246
+
247
+ ### TrackParams
248
+
249
+ | Property | Type | Notes |
250
+ |----------------|--------------------------|---------------------------------------|
251
+ | `transactionId`| `string` | Required for purchase/subscription/refund |
252
+ | `amount` | `number` | Monetary amount |
253
+ | `currency` | `string` | ISO 4217 (e.g. `"USD"`) |
254
+ | `productIds` | `string[]` | Product identifiers |
255
+ | `customParams` | `Record<string, string>` | Arbitrary metadata |
256
+
257
+ ---
258
+
259
+ ## Postback endpoint (reference)
260
+
261
+ ```
262
+ POST {baseUrl}/api/tracking/postback
263
+ Headers:
264
+ Content-Type: application/json
265
+ X-Company-Key: co_...
266
+ Body:
267
+ click_id string (required)
268
+ click_ids string[] (optional, stored chain)
269
+ event_type string (required, see table above)
270
+ user_id string (required)
271
+ transaction_id string (required for purchase/subscription/refund)
272
+ amount number (optional)
273
+ currency string (optional)
274
+ product_ids string[] (optional)
275
+ custom_params object (optional)
276
+ ```
277
+
278
+ HTTP 200 = received (processing is asynchronous on the server).
279
+ HTTP 5xx = retry.
280
+ HTTP 4xx = permanent failure, do not retry.
281
+
282
+ ---
283
+
284
+ ## License
285
+
286
+ MIT
@@ -0,0 +1,31 @@
1
+ import type { PostbackPayload } from './types';
2
+ export interface ClientConfig {
3
+ companyKey: string;
4
+ baseUrl?: string;
5
+ debug?: boolean;
6
+ }
7
+ export interface SendResult {
8
+ success: boolean;
9
+ queued: boolean;
10
+ }
11
+ export declare function setDebug(enabled: boolean): void;
12
+ /**
13
+ * Attempts to POST a payload to the postback endpoint up to MAX_RETRIES times
14
+ * with exponential backoff. Returns true on success, false after all retries fail.
15
+ */
16
+ export declare function sendWithRetry(payload: PostbackPayload, config: ClientConfig): Promise<boolean>;
17
+ /**
18
+ * Sends a postback event. If all retries fail, the event is persisted to the
19
+ * pending queue so it can be flushed on the next SDK activity.
20
+ *
21
+ * This function is designed to be fire-and-forget from the caller's perspective:
22
+ * it resolves quickly and does retry work in the background, but still returns
23
+ * a Promise so callers can await it if they care about the final outcome.
24
+ */
25
+ export declare function sendEvent(payload: PostbackPayload, config: ClientConfig): Promise<SendResult>;
26
+ /**
27
+ * Drains the persisted pending queue. Called automatically on configure()
28
+ * and before each new track() call.
29
+ */
30
+ export declare function flushPendingQueue(config: ClientConfig): Promise<void>;
31
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,SAAS,CAAC;AAgB7D,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;AAQD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAE/C;AAkBD;;;GAGG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,OAAO,CAAC,CA8ClB;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,UAAU,CAAC,CAWrB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB3E"}
package/dist/client.js ADDED
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setDebug = setDebug;
4
+ exports.sendWithRetry = sendWithRetry;
5
+ exports.sendEvent = sendEvent;
6
+ exports.flushPendingQueue = flushPendingQueue;
7
+ const storage_1 = require("./storage");
8
+ // ---------------------------------------------------------------------------
9
+ // Constants
10
+ // ---------------------------------------------------------------------------
11
+ const DEFAULT_BASE_URL = 'https://api.viralif.co';
12
+ const POSTBACK_PATH = '/api/tracking/postback';
13
+ const MAX_RETRIES = 3;
14
+ const INITIAL_BACKOFF_MS = 500;
15
+ // ---------------------------------------------------------------------------
16
+ // Logging
17
+ // ---------------------------------------------------------------------------
18
+ let _debug = false;
19
+ function setDebug(enabled) {
20
+ _debug = enabled;
21
+ }
22
+ function log(...args) {
23
+ if (_debug)
24
+ console.log('[AdSparkle]', ...args);
25
+ }
26
+ function warn(...args) {
27
+ if (_debug)
28
+ console.warn('[AdSparkle]', ...args);
29
+ }
30
+ // ---------------------------------------------------------------------------
31
+ // Core send with retry
32
+ // ---------------------------------------------------------------------------
33
+ async function sleep(ms) {
34
+ return new Promise((resolve) => setTimeout(resolve, ms));
35
+ }
36
+ /**
37
+ * Attempts to POST a payload to the postback endpoint up to MAX_RETRIES times
38
+ * with exponential backoff. Returns true on success, false after all retries fail.
39
+ */
40
+ async function sendWithRetry(payload, config) {
41
+ var _a;
42
+ const url = `${(_a = config.baseUrl) !== null && _a !== void 0 ? _a : DEFAULT_BASE_URL}${POSTBACK_PATH}`;
43
+ const headers = {
44
+ 'Content-Type': 'application/json',
45
+ 'X-Company-Key': config.companyKey,
46
+ };
47
+ for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
48
+ try {
49
+ log(`Sending event "${payload.event_type}" (attempt ${attempt}/${MAX_RETRIES})`);
50
+ const response = await fetch(url, {
51
+ method: 'POST',
52
+ headers,
53
+ body: JSON.stringify(payload),
54
+ });
55
+ if (response.ok) {
56
+ log(`Event "${payload.event_type}" accepted (HTTP ${response.status})`);
57
+ return true;
58
+ }
59
+ // 4xx errors are not retryable (bad request, auth failure, etc.)
60
+ if (response.status >= 400 && response.status < 500) {
61
+ warn(`Event "${payload.event_type}" rejected with HTTP ${response.status} — not retrying`);
62
+ return false;
63
+ }
64
+ // 5xx — retryable
65
+ warn(`HTTP ${response.status} on attempt ${attempt}, will retry if attempts remain`);
66
+ }
67
+ catch (err) {
68
+ // Network error — retryable
69
+ warn(`Network error on attempt ${attempt}:`, err);
70
+ }
71
+ if (attempt < MAX_RETRIES) {
72
+ const backoff = INITIAL_BACKOFF_MS * Math.pow(2, attempt - 1);
73
+ log(`Backing off ${backoff}ms before retry`);
74
+ await sleep(backoff);
75
+ }
76
+ }
77
+ warn(`All ${MAX_RETRIES} attempts failed for event "${payload.event_type}"`);
78
+ return false;
79
+ }
80
+ /**
81
+ * Sends a postback event. If all retries fail, the event is persisted to the
82
+ * pending queue so it can be flushed on the next SDK activity.
83
+ *
84
+ * This function is designed to be fire-and-forget from the caller's perspective:
85
+ * it resolves quickly and does retry work in the background, but still returns
86
+ * a Promise so callers can await it if they care about the final outcome.
87
+ */
88
+ async function sendEvent(payload, config) {
89
+ const success = await sendWithRetry(payload, config);
90
+ if (!success) {
91
+ const pending = { payload, enqueuedAt: Date.now() };
92
+ await (0, storage_1.appendToPendingQueue)(pending);
93
+ log(`Event "${payload.event_type}" queued for later retry`);
94
+ return { success: false, queued: true };
95
+ }
96
+ return { success: true, queued: false };
97
+ }
98
+ /**
99
+ * Drains the persisted pending queue. Called automatically on configure()
100
+ * and before each new track() call.
101
+ */
102
+ async function flushPendingQueue(config) {
103
+ let queue = await (0, storage_1.loadPendingQueue)();
104
+ if (queue.length === 0)
105
+ return;
106
+ log(`Flushing ${queue.length} pending event(s)`);
107
+ const remaining = [];
108
+ for (const item of queue) {
109
+ const success = await sendWithRetry(item.payload, config);
110
+ if (!success) {
111
+ remaining.push(item);
112
+ }
113
+ }
114
+ await (0, storage_1.savePendingQueue)(remaining);
115
+ if (remaining.length > 0) {
116
+ warn(`${remaining.length} event(s) still pending after flush`);
117
+ }
118
+ else {
119
+ log('Pending queue fully flushed');
120
+ }
121
+ }
122
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Deep link utilities for extracting click_id from inbound URLs.
3
+ *
4
+ * The SDK does NOT automatically attach itself to React Native's Linking module.
5
+ * The host app is responsible for calling AdSparkle.handleDeepLink(url) from
6
+ * both Linking.getInitialURL() and the Linking 'url' event listener.
7
+ * See README for a ready-to-paste integration example.
8
+ */
9
+ /**
10
+ * Extracts the `click_id` query parameter from a URL string.
11
+ * Returns null if the URL is invalid or the parameter is missing/empty.
12
+ *
13
+ * Handles all common RN deep link schemes:
14
+ * myapp://launch?click_id=abc123
15
+ * https://example.com/promo?click_id=abc123&utm_source=viralif
16
+ */
17
+ export declare function extractClickId(url: string): string | null;
18
+ //# sourceMappingURL=deeplink.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deeplink.d.ts","sourceRoot":"","sources":["../src/deeplink.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA4BzD"}
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ /**
3
+ * Deep link utilities for extracting click_id from inbound URLs.
4
+ *
5
+ * The SDK does NOT automatically attach itself to React Native's Linking module.
6
+ * The host app is responsible for calling AdSparkle.handleDeepLink(url) from
7
+ * both Linking.getInitialURL() and the Linking 'url' event listener.
8
+ * See README for a ready-to-paste integration example.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.extractClickId = extractClickId;
12
+ const CLICK_ID_PARAM = 'click_id';
13
+ /**
14
+ * Canonical UUID v4-ish format (case-insensitive), matching adsparkle.js UUID_RE.
15
+ * click_ids that don't match are treated as invalid and ignored.
16
+ */
17
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
18
+ /**
19
+ * Extracts the `click_id` query parameter from a URL string.
20
+ * Returns null if the URL is invalid or the parameter is missing/empty.
21
+ *
22
+ * Handles all common RN deep link schemes:
23
+ * myapp://launch?click_id=abc123
24
+ * https://example.com/promo?click_id=abc123&utm_source=viralif
25
+ */
26
+ function extractClickId(url) {
27
+ if (!url || typeof url !== 'string')
28
+ return null;
29
+ try {
30
+ // URL() is available in React Native >= 0.63 (Hermes / JSC both support it).
31
+ // For older RN, we fall back to a manual query-string parser.
32
+ let searchString;
33
+ try {
34
+ const parsed = new URL(url);
35
+ searchString = parsed.search;
36
+ }
37
+ catch (_a) {
38
+ // Manual fallback: grab everything after '?'
39
+ const qIdx = url.indexOf('?');
40
+ if (qIdx === -1)
41
+ return null;
42
+ searchString = url.slice(qIdx);
43
+ }
44
+ const params = parseQueryString(searchString);
45
+ const value = params[CLICK_ID_PARAM];
46
+ const trimmed = value && value.trim() !== '' ? value.trim() : null;
47
+ // Reject anything that isn't a well-formed UUID (parity with adsparkle.js).
48
+ if (!trimmed || !UUID_RE.test(trimmed))
49
+ return null;
50
+ return trimmed;
51
+ }
52
+ catch (_b) {
53
+ // Any unexpected error — silently return null.
54
+ return null;
55
+ }
56
+ }
57
+ /**
58
+ * Minimal query-string parser that does NOT rely on URLSearchParams
59
+ * (not universally available in all RN environments).
60
+ */
61
+ function parseQueryString(search) {
62
+ const result = {};
63
+ const qs = search.startsWith('?') ? search.slice(1) : search;
64
+ if (!qs)
65
+ return result;
66
+ for (const pair of qs.split('&')) {
67
+ const eqIdx = pair.indexOf('=');
68
+ if (eqIdx === -1)
69
+ continue;
70
+ const key = safeDecodeURIComponent(pair.slice(0, eqIdx));
71
+ const val = safeDecodeURIComponent(pair.slice(eqIdx + 1));
72
+ if (key)
73
+ result[key] = val;
74
+ }
75
+ return result;
76
+ }
77
+ function safeDecodeURIComponent(str) {
78
+ try {
79
+ return decodeURIComponent(str.replace(/\+/g, ' '));
80
+ }
81
+ catch (_a) {
82
+ return str;
83
+ }
84
+ }
85
+ //# sourceMappingURL=deeplink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deeplink.js","sourceRoot":"","sources":["../src/deeplink.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AAkBH,wCA4BC;AA5CD,MAAM,cAAc,GAAG,UAAU,CAAC;AAElC;;;GAGG;AACH,MAAM,OAAO,GAAG,iEAAiE,CAAC;AAElF;;;;;;;GAOG;AACH,SAAgB,cAAc,CAAC,GAAW;IACxC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAEjD,IAAI,CAAC;QACH,6EAA6E;QAC7E,8DAA8D;QAC9D,IAAI,YAAoB,CAAC;QAEzB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;YAC5B,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC;QAC/B,CAAC;QAAC,WAAM,CAAC;YACP,6CAA6C;YAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,IAAI,KAAK,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC7B,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;QAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACnE,4EAA4E;QAC5E,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC;QACpD,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,WAAM,CAAC;QACP,+CAA+C;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,MAAc;IACtC,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC7D,IAAI,CAAC,EAAE;QAAE,OAAO,MAAM,CAAC;IAEvB,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE,SAAS;QAC3B,MAAM,GAAG,GAAG,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QACzD,MAAM,GAAG,GAAG,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;QAC1D,IAAI,GAAG;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IAC7B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,sBAAsB,CAAC,GAAW;IACzC,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IACrD,CAAC;IAAC,WAAM,CAAC;QACP,OAAO,GAAG,CAAC;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * adsparkle-react-native
3
+ * Viralif / AdBird affiliate attribution SDK for React Native.
4
+ *
5
+ * Usage:
6
+ * import AdSparkle from 'adsparkle-react-native';
7
+ * AdSparkle.configure({ companyKey: 'co_...' });
8
+ */
9
+ import type { AdSparkleConfig, EventType, TrackParams, PendingEvent } from './types';
10
+ export type { AdSparkleConfig, EventType, TrackParams, PendingEvent };
11
+ /**
12
+ * Initialises the SDK. Must be called before any tracking.
13
+ * Hydrates state from AsyncStorage and flushes any pending events.
14
+ */
15
+ declare function configure(config: AdSparkleConfig): Promise<void>;
16
+ /**
17
+ * Sets the merchant's internal user identifier.
18
+ * Persists to storage so it survives app restarts.
19
+ */
20
+ declare function setUserId(userId: string): Promise<void>;
21
+ /**
22
+ * Parses a deep link URL, extracts the click_id query parameter, and
23
+ * adds it to the persisted chain (max 10, no duplicates).
24
+ *
25
+ * Call this from both Linking.getInitialURL() and the Linking event listener.
26
+ * The SDK does NOT attach itself to Linking automatically.
27
+ */
28
+ declare function handleDeepLink(url: string): Promise<void>;
29
+ /**
30
+ * Manually sets a click_id (e.g. when received via a custom channel).
31
+ * Adds to the chain with the same deduplication/cap logic as handleDeepLink.
32
+ */
33
+ declare function setClickId(clickId: string): Promise<void>;
34
+ /**
35
+ * Returns the most recently captured click_id, or null if none is set.
36
+ */
37
+ declare function getClickId(): string | null;
38
+ /**
39
+ * Core tracking method. Sends an event to the postback endpoint.
40
+ *
41
+ * - No-op (with optional debug warning) if clickId or userId is not set.
42
+ * - Retries on 5xx / network failure (up to 3 times with exponential backoff).
43
+ * - Falls back to persisted queue if all retries fail.
44
+ * - Automatically flushes previously queued events before sending.
45
+ *
46
+ * @returns A Promise that resolves once the send attempt (or queue) is complete.
47
+ */
48
+ declare function track(eventType: EventType, params?: TrackParams): Promise<void>;
49
+ declare function trackInstall(params?: TrackParams): Promise<void>;
50
+ declare function trackSignUp(params?: TrackParams): Promise<void>;
51
+ declare function trackLogin(params?: TrackParams): Promise<void>;
52
+ declare function trackDownload(params?: TrackParams): Promise<void>;
53
+ declare function trackPurchase(params?: Omit<TrackParams, 'transactionId'> & {
54
+ transactionId: string;
55
+ }): Promise<void>;
56
+ declare function trackSubscription(params?: Omit<TrackParams, 'transactionId'> & {
57
+ transactionId: string;
58
+ }): Promise<void>;
59
+ declare function trackRefund(params?: Omit<TrackParams, 'transactionId'> & {
60
+ transactionId: string;
61
+ }): Promise<void>;
62
+ /**
63
+ * Bir store satın alma objesinden otomatik `purchase` event'i gönderir.
64
+ * `productIds` ve `transactionId` store objesinden KENDİLİĞİNDEN çıkarılır;
65
+ * merchant SKU'yu elle yazmak zorunda kalmaz. Adjust'ın StoreKit/Play Billing'den
66
+ * ürün okumasının React Native karşılığıdır. `amount`/`currency` store objesinde
67
+ * bulunmadığı için yüzde komisyonlu event'lerde params ile geçilmelidir.
68
+ */
69
+ declare function trackPurchaseFromStore(purchase: unknown, params?: Omit<TrackParams, 'productIds'>): Promise<void>;
70
+ interface LinkingModule {
71
+ getInitialURL(): Promise<string | null>;
72
+ addEventListener(event: string, handler: (event: {
73
+ url: string;
74
+ }) => void): {
75
+ remove(): void;
76
+ };
77
+ }
78
+ /**
79
+ * Optional convenience helper that automatically wires the SDK to React Native's
80
+ * Linking module. Call once at app startup (e.g. in your root _layout.tsx).
81
+ *
82
+ * You must pass the Linking module explicitly to keep this package free of a
83
+ * hard dependency on react-native:
84
+ *
85
+ * import { Linking } from 'react-native';
86
+ * AdSparkle.attachLinking(Linking);
87
+ *
88
+ * Call AdSparkle.detachLinking() to remove the listener (e.g. on unmount).
89
+ */
90
+ declare function attachLinking(Linking: LinkingModule): Promise<void>;
91
+ declare function detachLinking(): void;
92
+ declare const AdSparkle: {
93
+ readonly configure: typeof configure;
94
+ readonly setUserId: typeof setUserId;
95
+ readonly handleDeepLink: typeof handleDeepLink;
96
+ readonly setClickId: typeof setClickId;
97
+ readonly getClickId: typeof getClickId;
98
+ readonly track: typeof track;
99
+ readonly trackInstall: typeof trackInstall;
100
+ readonly trackSignUp: typeof trackSignUp;
101
+ readonly trackLogin: typeof trackLogin;
102
+ readonly trackDownload: typeof trackDownload;
103
+ readonly trackPurchase: typeof trackPurchase;
104
+ readonly trackSubscription: typeof trackSubscription;
105
+ readonly trackRefund: typeof trackRefund;
106
+ readonly trackPurchaseFromStore: typeof trackPurchaseFromStore;
107
+ readonly attachLinking: typeof attachLinking;
108
+ readonly detachLinking: typeof detachLinking;
109
+ };
110
+ export default AdSparkle;
111
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EACV,eAAe,EACf,SAAS,EAET,WAAW,EACX,YAAY,EACb,MAAM,SAAS,CAAC;AAIjB,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;AAsHtE;;;GAGG;AACH,iBAAe,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA8B/D;AAED;;;GAGG;AACH,iBAAe,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKtD;AAWD;;;;;;GAMG;AACH,iBAAe,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOxD;AAED;;;GAGG;AACH,iBAAe,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMxD;AAED;;GAEG;AACH,iBAAS,UAAU,IAAI,MAAM,GAAG,IAAI,CAEnC;AAED;;;;;;;;;GASG;AACH,iBAAe,KAAK,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6ClF;AAMD,iBAAe,YAAY,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/D;AAED,iBAAe,WAAW,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D;AAED,iBAAe,UAAU,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7D;AAED,iBAAe,aAAa,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhE;AAED,iBAAe,aAAa,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,GAAG;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAEnH;AAED,iBAAe,iBAAiB,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,GAAG;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvH;AAED,iBAAe,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,GAAG;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjH;AAwBD;;;;;;GAMG;AACH,iBAAe,sBAAsB,CACnC,QAAQ,EAAE,OAAO,EACjB,MAAM,GAAE,IAAI,CAAC,WAAW,EAAE,YAAY,CAAM,GAC3C,OAAO,CAAC,IAAI,CAAC,CAQf;AAMD,UAAU,aAAa;IACrB,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxC,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG;QAAE,MAAM,IAAI,IAAI,CAAA;KAAE,CAAC;CAChG;AAID;;;;;;;;;;;GAWG;AACH,iBAAe,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAalE;AAED,iBAAS,aAAa,IAAI,IAAI,CAM7B;AAMD,QAAA,MAAM,SAAS;;;;;;;;;;;;;;;;;CAiBL,CAAC;AAEX,eAAe,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,327 @@
1
+ "use strict";
2
+ /**
3
+ * adsparkle-react-native
4
+ * Viralif / AdBird affiliate attribution SDK for React Native.
5
+ *
6
+ * Usage:
7
+ * import AdSparkle from 'adsparkle-react-native';
8
+ * AdSparkle.configure({ companyKey: 'co_...' });
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ const deeplink_1 = require("./deeplink");
12
+ const client_1 = require("./client");
13
+ const storage_1 = require("./storage");
14
+ const types_1 = require("./types");
15
+ const DEFAULT_BASE_URL = 'https://api.viralif.co';
16
+ // Parity with adsparkle.js (MAX_CHAIN_SIZE = 50).
17
+ const MAX_CLICK_ID_CHAIN = 50;
18
+ // 7-day sliding attribution window (ATTRIBUTION_WINDOW_DAYS) in milliseconds.
19
+ const CHAIN_TTL_MS = 7 * 24 * 60 * 60 * 1000;
20
+ // Canonical UUID format (case-insensitive), matching adsparkle.js UUID_RE.
21
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
22
+ const state = {
23
+ companyKey: null,
24
+ baseUrl: DEFAULT_BASE_URL,
25
+ debug: false,
26
+ userId: null,
27
+ clickId: null,
28
+ clickIds: [],
29
+ clickIdsUpdatedAt: 0,
30
+ };
31
+ // ---------------------------------------------------------------------------
32
+ // Internal helpers
33
+ // ---------------------------------------------------------------------------
34
+ function isConfigured() {
35
+ return state.companyKey !== null;
36
+ }
37
+ function clientConfig() {
38
+ return {
39
+ companyKey: state.companyKey,
40
+ baseUrl: state.baseUrl,
41
+ debug: state.debug,
42
+ };
43
+ }
44
+ function log(...args) {
45
+ if (state.debug)
46
+ console.log('[AdSparkle]', ...args);
47
+ }
48
+ function warn(...args) {
49
+ if (state.debug)
50
+ console.warn('[AdSparkle]', ...args);
51
+ }
52
+ /**
53
+ * Enforces the 7-day sliding window on the in-memory chain. If the chain has not
54
+ * been updated within CHAIN_TTL_MS, it is considered expired: clickIds/clickId
55
+ * are cleared and the cleared state is persisted. Returns true if it expired.
56
+ */
57
+ async function expireChainIfStale() {
58
+ if (state.clickIds.length === 0)
59
+ return false;
60
+ if (Date.now() - state.clickIdsUpdatedAt <= CHAIN_TTL_MS)
61
+ return false;
62
+ log('click_id chain expired (>7d since last update) — clearing');
63
+ state.clickIds = [];
64
+ state.clickId = null;
65
+ const current = await (0, storage_1.loadState)();
66
+ await (0, storage_1.saveState)(Object.assign(Object.assign({}, current), { clickId: undefined, clickIds: [] }));
67
+ return true;
68
+ }
69
+ /**
70
+ * Adds a click_id to the chain. Mirrors adsparkle.js addClickId:
71
+ * - validates UUID format (silently ignores invalid values)
72
+ * - move-to-front recency: if already present, removes the old position and
73
+ * re-appends so it becomes the most-recent entry
74
+ * - caps at MAX_CLICK_ID_CHAIN (keep the most recent 50)
75
+ * - refreshes the sliding-window timestamp on every add
76
+ * Persists the updated chain to storage.
77
+ */
78
+ async function addToClickIdChain(clickId) {
79
+ if (!UUID_RE.test(clickId)) {
80
+ log(`click_id "${clickId}" is not a valid UUID, ignoring`);
81
+ return;
82
+ }
83
+ // Move-to-front (recency): drop any existing occurrence, then append.
84
+ const next = state.clickIds.filter((id) => id !== clickId);
85
+ next.push(clickId);
86
+ state.clickId = clickId;
87
+ state.clickIds = next.slice(-MAX_CLICK_ID_CHAIN);
88
+ state.clickIdsUpdatedAt = Date.now();
89
+ const current = await (0, storage_1.loadState)();
90
+ await (0, storage_1.saveState)(Object.assign(Object.assign({}, current), { clickId: state.clickId, clickIds: state.clickIds, clickIdsUpdatedAt: state.clickIdsUpdatedAt }));
91
+ log(`click_id set to "${clickId}" (chain length: ${state.clickIds.length})`);
92
+ }
93
+ // ---------------------------------------------------------------------------
94
+ // Public API
95
+ // ---------------------------------------------------------------------------
96
+ /**
97
+ * Initialises the SDK. Must be called before any tracking.
98
+ * Hydrates state from AsyncStorage and flushes any pending events.
99
+ */
100
+ async function configure(config) {
101
+ var _a, _b, _c;
102
+ state.companyKey = config.companyKey;
103
+ state.baseUrl = (_a = config.baseUrl) !== null && _a !== void 0 ? _a : DEFAULT_BASE_URL;
104
+ state.debug = (_b = config.debug) !== null && _b !== void 0 ? _b : false;
105
+ (0, client_1.setDebug)(state.debug);
106
+ log('Configuring SDK', { companyKey: config.companyKey, baseUrl: state.baseUrl });
107
+ // Hydrate from storage
108
+ const persisted = await (0, storage_1.loadState)();
109
+ if (persisted.userId && !state.userId)
110
+ state.userId = persisted.userId;
111
+ if (persisted.clickId)
112
+ state.clickId = persisted.clickId;
113
+ if (persisted.clickIds)
114
+ state.clickIds = persisted.clickIds;
115
+ if (persisted.clickIdsUpdatedAt)
116
+ state.clickIdsUpdatedAt = persisted.clickIdsUpdatedAt;
117
+ // Enforce the 7-day sliding window on the hydrated chain.
118
+ await expireChainIfStale();
119
+ // Persist latest config values
120
+ await (0, storage_1.saveState)(Object.assign(Object.assign({}, persisted), { companyKey: state.companyKey, baseUrl: state.baseUrl, clickId: (_c = state.clickId) !== null && _c !== void 0 ? _c : undefined, clickIds: state.clickIds }));
121
+ // Flush any events that failed in a previous session
122
+ await (0, client_1.flushPendingQueue)(clientConfig());
123
+ }
124
+ /**
125
+ * Sets the merchant's internal user identifier.
126
+ * Persists to storage so it survives app restarts.
127
+ */
128
+ async function setUserId(userId) {
129
+ state.userId = userId;
130
+ const current = await (0, storage_1.loadState)();
131
+ await (0, storage_1.saveState)(Object.assign(Object.assign({}, current), { userId }));
132
+ log(`userId set to "${userId}"`);
133
+ }
134
+ /**
135
+ * Browser SDK (adsparkle.js) paritesi: merchant userId vermediğinde kalıcı bir
136
+ * anonim oturum kimliği üretir. Böylece aynı cihazdaki tekrar conversion'lar
137
+ * yine de tek bir kullanıcıya eşlenebilir ve userId çağrısı opsiyonel kalır.
138
+ */
139
+ function generateAnonId() {
140
+ return `anon_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;
141
+ }
142
+ /**
143
+ * Parses a deep link URL, extracts the click_id query parameter, and
144
+ * adds it to the persisted chain (max 10, no duplicates).
145
+ *
146
+ * Call this from both Linking.getInitialURL() and the Linking event listener.
147
+ * The SDK does NOT attach itself to Linking automatically.
148
+ */
149
+ async function handleDeepLink(url) {
150
+ const clickId = (0, deeplink_1.extractClickId)(url);
151
+ if (!clickId) {
152
+ log(`No click_id found in URL: ${url}`);
153
+ return;
154
+ }
155
+ await addToClickIdChain(clickId);
156
+ }
157
+ /**
158
+ * Manually sets a click_id (e.g. when received via a custom channel).
159
+ * Adds to the chain with the same deduplication/cap logic as handleDeepLink.
160
+ */
161
+ async function setClickId(clickId) {
162
+ if (!clickId || typeof clickId !== 'string' || clickId.trim() === '') {
163
+ warn('setClickId called with empty value — ignoring');
164
+ return;
165
+ }
166
+ await addToClickIdChain(clickId.trim());
167
+ }
168
+ /**
169
+ * Returns the most recently captured click_id, or null if none is set.
170
+ */
171
+ function getClickId() {
172
+ return state.clickId;
173
+ }
174
+ /**
175
+ * Core tracking method. Sends an event to the postback endpoint.
176
+ *
177
+ * - No-op (with optional debug warning) if clickId or userId is not set.
178
+ * - Retries on 5xx / network failure (up to 3 times with exponential backoff).
179
+ * - Falls back to persisted queue if all retries fail.
180
+ * - Automatically flushes previously queued events before sending.
181
+ *
182
+ * @returns A Promise that resolves once the send attempt (or queue) is complete.
183
+ */
184
+ async function track(eventType, params = {}) {
185
+ if (!isConfigured()) {
186
+ warn('track() called before configure() — ignoring');
187
+ return;
188
+ }
189
+ if (!types_1.VALID_EVENT_TYPES.includes(eventType)) {
190
+ warn(`Unknown event type "${eventType}" — ignoring. Valid types: ${types_1.VALID_EVENT_TYPES.join(', ')}`);
191
+ return;
192
+ }
193
+ // Drop the chain if the 7-day sliding window has elapsed since the last update.
194
+ await expireChainIfStale();
195
+ if (!state.clickId) {
196
+ warn(`track("${eventType}") called without a click_id — ignoring (no-op)`);
197
+ return;
198
+ }
199
+ // Browser SDK paritesi: userId verilmediyse kalıcı bir anonim kimlik üret
200
+ // ve sakla — conversion düşürülmez (eski davranış no-op idi).
201
+ let userId = state.userId;
202
+ if (!userId) {
203
+ userId = generateAnonId();
204
+ await setUserId(userId);
205
+ }
206
+ // Flush leftover queue before sending new event
207
+ await (0, client_1.flushPendingQueue)(clientConfig());
208
+ const payload = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ click_id: state.clickId, click_ids: state.clickIds.length > 0 ? state.clickIds : undefined, event_type: eventType, user_id: userId }, (params.transactionId !== undefined && { transaction_id: params.transactionId })), (params.amount !== undefined && { amount: params.amount })), (params.currency !== undefined && { currency: params.currency })), (params.productIds !== undefined && { product_ids: params.productIds })), (params.customParams !== undefined && { custom_params: params.customParams }));
209
+ log(`Tracking event "${eventType}"`, payload);
210
+ await (0, client_1.sendEvent)(payload, clientConfig());
211
+ }
212
+ // ---------------------------------------------------------------------------
213
+ // Convenience wrappers
214
+ // ---------------------------------------------------------------------------
215
+ async function trackInstall(params) {
216
+ return track('install', params);
217
+ }
218
+ async function trackSignUp(params) {
219
+ return track('sign_up', params);
220
+ }
221
+ async function trackLogin(params) {
222
+ return track('login', params);
223
+ }
224
+ async function trackDownload(params) {
225
+ return track('download', params);
226
+ }
227
+ async function trackPurchase(params) {
228
+ return track('purchase', params);
229
+ }
230
+ async function trackSubscription(params) {
231
+ return track('subscription', params);
232
+ }
233
+ async function trackRefund(params) {
234
+ return track('refund', params);
235
+ }
236
+ // ---------------------------------------------------------------------------
237
+ // Adjust-style otomatik ürün yakalama (store satın alma objesinden)
238
+ // ---------------------------------------------------------------------------
239
+ /**
240
+ * react-native-iap / expo-in-app-purchases gibi kütüphanelerin döndürdüğü satın
241
+ * alma objesinden ürün kimliklerini çıkarır. Hiçbir kütüphaneye bağımlılık yok:
242
+ * alanlar duck-typing ile okunur (iOS: `productId`, Android: `productIds`/`skus`).
243
+ */
244
+ function extractStoreProductIds(purchase) {
245
+ if (!purchase || typeof purchase !== 'object')
246
+ return [];
247
+ if (Array.isArray(purchase.productIds))
248
+ return purchase.productIds.map(String);
249
+ if (Array.isArray(purchase.skus))
250
+ return purchase.skus.map(String);
251
+ if (purchase.productId != null)
252
+ return [String(purchase.productId)];
253
+ return [];
254
+ }
255
+ function extractStoreTransactionId(purchase) {
256
+ var _a, _b;
257
+ const id = (_b = (_a = purchase === null || purchase === void 0 ? void 0 : purchase.transactionId) !== null && _a !== void 0 ? _a : purchase === null || purchase === void 0 ? void 0 : purchase.orderId) !== null && _b !== void 0 ? _b : purchase === null || purchase === void 0 ? void 0 : purchase.purchaseToken;
258
+ return id != null ? String(id) : undefined;
259
+ }
260
+ /**
261
+ * Bir store satın alma objesinden otomatik `purchase` event'i gönderir.
262
+ * `productIds` ve `transactionId` store objesinden KENDİLİĞİNDEN çıkarılır;
263
+ * merchant SKU'yu elle yazmak zorunda kalmaz. Adjust'ın StoreKit/Play Billing'den
264
+ * ürün okumasının React Native karşılığıdır. `amount`/`currency` store objesinde
265
+ * bulunmadığı için yüzde komisyonlu event'lerde params ile geçilmelidir.
266
+ */
267
+ async function trackPurchaseFromStore(purchase, params = {}) {
268
+ var _a;
269
+ const productIds = extractStoreProductIds(purchase);
270
+ const transactionId = (_a = params.transactionId) !== null && _a !== void 0 ? _a : extractStoreTransactionId(purchase);
271
+ return track('purchase', Object.assign(Object.assign(Object.assign({}, params), (transactionId !== undefined && { transactionId })), (productIds.length > 0 && { productIds })));
272
+ }
273
+ let linkingSubscription = null;
274
+ /**
275
+ * Optional convenience helper that automatically wires the SDK to React Native's
276
+ * Linking module. Call once at app startup (e.g. in your root _layout.tsx).
277
+ *
278
+ * You must pass the Linking module explicitly to keep this package free of a
279
+ * hard dependency on react-native:
280
+ *
281
+ * import { Linking } from 'react-native';
282
+ * AdSparkle.attachLinking(Linking);
283
+ *
284
+ * Call AdSparkle.detachLinking() to remove the listener (e.g. on unmount).
285
+ */
286
+ async function attachLinking(Linking) {
287
+ // Handle cold-start deep link
288
+ const initialUrl = await Linking.getInitialURL();
289
+ if (initialUrl) {
290
+ await handleDeepLink(initialUrl);
291
+ }
292
+ // Handle warm-start / foreground deep links
293
+ linkingSubscription = Linking.addEventListener('url', async (event) => {
294
+ await handleDeepLink(event.url);
295
+ });
296
+ log('Linking attached');
297
+ }
298
+ function detachLinking() {
299
+ if (linkingSubscription) {
300
+ linkingSubscription.remove();
301
+ linkingSubscription = null;
302
+ log('Linking detached');
303
+ }
304
+ }
305
+ // ---------------------------------------------------------------------------
306
+ // Default export — singleton object
307
+ // ---------------------------------------------------------------------------
308
+ const AdSparkle = {
309
+ configure,
310
+ setUserId,
311
+ handleDeepLink,
312
+ setClickId,
313
+ getClickId,
314
+ track,
315
+ trackInstall,
316
+ trackSignUp,
317
+ trackLogin,
318
+ trackDownload,
319
+ trackPurchase,
320
+ trackSubscription,
321
+ trackRefund,
322
+ trackPurchaseFromStore,
323
+ attachLinking,
324
+ detachLinking,
325
+ };
326
+ exports.default = AdSparkle;
327
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { PersistedState, PendingEvent } from './types';
2
+ export declare function loadState(): Promise<PersistedState>;
3
+ export declare function saveState(state: PersistedState): Promise<void>;
4
+ export declare function loadPendingQueue(): Promise<PendingEvent[]>;
5
+ export declare function savePendingQueue(queue: PendingEvent[]): Promise<void>;
6
+ export declare function appendToPendingQueue(event: PendingEvent): Promise<void>;
7
+ export declare function clearPendingQueue(): Promise<void>;
8
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AA+C5D,wBAAsB,SAAS,IAAI,OAAO,CAAC,cAAc,CAAC,CAQzD;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAMpE;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAGhE;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAG3E;AAED,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAM7E;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAGvD"}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadState = loadState;
4
+ exports.saveState = saveState;
5
+ exports.loadPendingQueue = loadPendingQueue;
6
+ exports.savePendingQueue = savePendingQueue;
7
+ exports.appendToPendingQueue = appendToPendingQueue;
8
+ exports.clearPendingQueue = clearPendingQueue;
9
+ const STORAGE_KEY = '@adsparkle/state';
10
+ // Max number of events kept in the offline retry queue. When the queue exceeds
11
+ // this, the oldest event is dropped (FIFO) — mirrors adsparkle.js MAX_QUEUE_SIZE.
12
+ const MAX_QUEUE_SIZE = 100;
13
+ function resolveAsyncStorage() {
14
+ var _a, _b;
15
+ try {
16
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
17
+ const mod = require('@react-native-async-storage/async-storage');
18
+ return (_b = (_a = mod === null || mod === void 0 ? void 0 : mod.default) !== null && _a !== void 0 ? _a : mod) !== null && _b !== void 0 ? _b : null;
19
+ }
20
+ catch (_c) {
21
+ return null;
22
+ }
23
+ }
24
+ // In-memory fallback (used when AsyncStorage is unavailable, e.g. in Jest).
25
+ const memoryStore = {};
26
+ const inMemoryStorage = {
27
+ getItem: (key) => { var _a; return Promise.resolve((_a = memoryStore[key]) !== null && _a !== void 0 ? _a : null); },
28
+ setItem: (key, value) => {
29
+ memoryStore[key] = value;
30
+ return Promise.resolve();
31
+ },
32
+ };
33
+ function getStorage() {
34
+ var _a;
35
+ return (_a = resolveAsyncStorage()) !== null && _a !== void 0 ? _a : inMemoryStorage;
36
+ }
37
+ // ---------------------------------------------------------------------------
38
+ // Public helpers
39
+ // ---------------------------------------------------------------------------
40
+ async function loadState() {
41
+ try {
42
+ const raw = await getStorage().getItem(STORAGE_KEY);
43
+ if (!raw)
44
+ return {};
45
+ return JSON.parse(raw);
46
+ }
47
+ catch (_a) {
48
+ return {};
49
+ }
50
+ }
51
+ async function saveState(state) {
52
+ try {
53
+ await getStorage().setItem(STORAGE_KEY, JSON.stringify(state));
54
+ }
55
+ catch (_a) {
56
+ // Silently ignore persistence failures — tracking should not crash the app.
57
+ }
58
+ }
59
+ async function loadPendingQueue() {
60
+ var _a;
61
+ const state = await loadState();
62
+ return (_a = state.pendingQueue) !== null && _a !== void 0 ? _a : [];
63
+ }
64
+ async function savePendingQueue(queue) {
65
+ const state = await loadState();
66
+ await saveState(Object.assign(Object.assign({}, state), { pendingQueue: queue }));
67
+ }
68
+ async function appendToPendingQueue(event) {
69
+ const queue = await loadPendingQueue();
70
+ queue.push(event);
71
+ // Cap the queue: drop the oldest event(s) when over the limit.
72
+ while (queue.length > MAX_QUEUE_SIZE)
73
+ queue.shift();
74
+ await savePendingQueue(queue);
75
+ }
76
+ async function clearPendingQueue() {
77
+ const state = await loadState();
78
+ await saveState(Object.assign(Object.assign({}, state), { pendingQueue: [] }));
79
+ }
80
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":";;AA+CA,8BAQC;AAED,8BAMC;AAED,4CAGC;AAED,4CAGC;AAED,oDAMC;AAED,8CAGC;AApFD,MAAM,WAAW,GAAG,kBAAkB,CAAC;AAEvC,+EAA+E;AAC/E,kFAAkF;AAClF,MAAM,cAAc,GAAG,GAAG,CAAC;AAa3B,SAAS,mBAAmB;;IAC1B,IAAI,CAAC;QACH,8DAA8D;QAC9D,MAAM,GAAG,GAAG,OAAO,CAAC,2CAA2C,CAAC,CAAC;QACjE,OAAO,MAAA,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,OAAO,mCAAI,GAAG,mCAAI,IAAI,CAAC;IACrC,CAAC;IAAC,WAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,4EAA4E;AAC5E,MAAM,WAAW,GAA2B,EAAE,CAAC;AAC/C,MAAM,eAAe,GAAqB;IACxC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,WAAC,OAAA,OAAO,CAAC,OAAO,CAAC,MAAA,WAAW,CAAC,GAAG,CAAC,mCAAI,IAAI,CAAC,CAAA,EAAA;IAC3D,OAAO,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QACtB,WAAW,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACzB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;CACF,CAAC;AAEF,SAAS,UAAU;;IACjB,OAAO,MAAA,mBAAmB,EAAE,mCAAI,eAAe,CAAC;AAClD,CAAC;AAED,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAEvE,KAAK,UAAU,SAAS;IAC7B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACpD,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmB,CAAC;IAC3C,CAAC;IAAC,WAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,SAAS,CAAC,KAAqB;IACnD,IAAI,CAAC;QACH,MAAM,UAAU,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACjE,CAAC;IAAC,WAAM,CAAC;QACP,4EAA4E;IAC9E,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,gBAAgB;;IACpC,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAChC,OAAO,MAAA,KAAK,CAAC,YAAY,mCAAI,EAAE,CAAC;AAClC,CAAC;AAEM,KAAK,UAAU,gBAAgB,CAAC,KAAqB;IAC1D,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAChC,MAAM,SAAS,iCAAM,KAAK,KAAE,YAAY,EAAE,KAAK,IAAG,CAAC;AACrD,CAAC;AAEM,KAAK,UAAU,oBAAoB,CAAC,KAAmB;IAC5D,MAAM,KAAK,GAAG,MAAM,gBAAgB,EAAE,CAAC;IACvC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,+DAA+D;IAC/D,OAAO,KAAK,CAAC,MAAM,GAAG,cAAc;QAAE,KAAK,CAAC,KAAK,EAAE,CAAC;IACpD,MAAM,gBAAgB,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAEM,KAAK,UAAU,iBAAiB;IACrC,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAChC,MAAM,SAAS,iCAAM,KAAK,KAAE,YAAY,EAAE,EAAE,IAAG,CAAC;AAClD,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Supported event types. Only these values may be sent to the postback endpoint.
3
+ * Derived or custom event types are NOT permitted.
4
+ */
5
+ export type EventType = 'install' | 'sign_up' | 'login' | 'download' | 'purchase' | 'subscription' | 'refund';
6
+ export declare const VALID_EVENT_TYPES: readonly EventType[];
7
+ /**
8
+ * SDK configuration object passed to AdSparkle.configure().
9
+ */
10
+ export interface AdSparkleConfig {
11
+ /**
12
+ * Your publishable company key (starts with "co_").
13
+ * This is a public key and safe to embed in client apps.
14
+ * Never use an HMAC secret or private key here.
15
+ */
16
+ companyKey: string;
17
+ /**
18
+ * Base URL for the tracking API.
19
+ * @default "https://api.viralif.co"
20
+ */
21
+ baseUrl?: string;
22
+ /**
23
+ * Enable verbose console logging.
24
+ * @default false
25
+ */
26
+ debug?: boolean;
27
+ }
28
+ /**
29
+ * Optional parameters for track() calls.
30
+ */
31
+ export interface TrackParams {
32
+ /** Required for purchase, subscription, and refund events. */
33
+ transactionId?: string;
34
+ /** Monetary amount (purchase / subscription). */
35
+ amount?: number;
36
+ /** ISO 4217 currency code (e.g. "USD", "EUR"). */
37
+ currency?: string;
38
+ /** List of product identifiers involved in the event. */
39
+ productIds?: string[];
40
+ /** Arbitrary key-value metadata. Values must be strings. */
41
+ customParams?: Record<string, string>;
42
+ }
43
+ /**
44
+ * The JSON body sent to POST {baseUrl}/api/tracking/postback.
45
+ * Internal type — not part of the public API surface.
46
+ */
47
+ export interface PostbackPayload {
48
+ click_id: string;
49
+ click_ids?: string[];
50
+ event_type: EventType;
51
+ user_id: string;
52
+ transaction_id?: string;
53
+ amount?: number;
54
+ currency?: string;
55
+ product_ids?: string[];
56
+ custom_params?: Record<string, string>;
57
+ }
58
+ /**
59
+ * An event that failed all retry attempts and is sitting in the persisted queue.
60
+ */
61
+ export interface PendingEvent {
62
+ payload: PostbackPayload;
63
+ enqueuedAt: number;
64
+ }
65
+ /**
66
+ * Shape of data persisted to AsyncStorage.
67
+ */
68
+ export interface PersistedState {
69
+ companyKey?: string;
70
+ baseUrl?: string;
71
+ userId?: string;
72
+ clickId?: string;
73
+ clickIds?: string[];
74
+ /**
75
+ * Epoch ms of the last time the click_id chain was updated. Used to enforce
76
+ * the 7-day sliding attribution window: if (now - clickIdsUpdatedAt) exceeds
77
+ * the window, the chain is considered expired and cleared.
78
+ */
79
+ clickIdsUpdatedAt?: number;
80
+ pendingQueue?: PendingEvent[];
81
+ }
82
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,SAAS,GACT,OAAO,GACP,UAAU,GACV,UAAU,GACV,cAAc,GACd,QAAQ,CAAC;AAEb,eAAO,MAAM,iBAAiB,EAAE,SAAS,SAAS,EAQjD,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,SAAS,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,eAAe,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,YAAY,EAAE,CAAC;CAC/B"}
package/dist/types.js ADDED
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VALID_EVENT_TYPES = void 0;
4
+ exports.VALID_EVENT_TYPES = [
5
+ 'install',
6
+ 'sign_up',
7
+ 'login',
8
+ 'download',
9
+ 'purchase',
10
+ 'subscription',
11
+ 'refund',
12
+ ];
13
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAaa,QAAA,iBAAiB,GAAyB;IACrD,SAAS;IACT,SAAS;IACT,OAAO;IACP,UAAU;IACV,UAAU;IACV,cAAc;IACd,QAAQ;CACT,CAAC"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "adsparkle-react-native",
3
+ "version": "0.1.0",
4
+ "description": "Viralif / AdBird affiliate attribution SDK for React Native",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "typecheck": "tsc --noEmit",
13
+ "clean": "rm -rf dist"
14
+ },
15
+ "peerDependencies": {
16
+ "@react-native-async-storage/async-storage": ">=1.18.0",
17
+ "react-native": ">=0.70.0"
18
+ },
19
+ "peerDependenciesMeta": {
20
+ "@react-native-async-storage/async-storage": {
21
+ "optional": false
22
+ }
23
+ },
24
+ "devDependencies": {
25
+ "typescript": "^5.9.3"
26
+ },
27
+ "keywords": [
28
+ "react-native",
29
+ "affiliate",
30
+ "tracking",
31
+ "attribution",
32
+ "viralif",
33
+ "adbird",
34
+ "sdk"
35
+ ],
36
+ "license": "MIT",
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "https://github.com/viralif/adsparkle-react-native"
40
+ }
41
+ }