sitepong 0.2.0 → 0.2.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/dist/cdn/sitepong.min.js +5 -5
- package/dist/cdn/sitepong.min.js.map +1 -1
- package/dist/entries/node.d.mts +2 -2
- package/dist/entries/node.d.ts +2 -2
- package/dist/entries/rn.d.ts +995 -0
- package/dist/entries/rn.js +240 -29
- package/dist/entries/rn.js.map +1 -1
- package/dist/entries/web.d.mts +2 -2
- package/dist/entries/web.d.ts +2 -2
- package/dist/entries/web.js +2094 -1235
- package/dist/entries/web.js.map +1 -1
- package/dist/entries/web.mjs +2093 -1236
- package/dist/entries/web.mjs.map +1 -1
- package/dist/index.d.mts +162 -3
- package/dist/index.d.ts +162 -3
- package/dist/index.js +158 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +157 -18
- package/dist/index.mjs.map +1 -1
- package/dist/nextjs/index.d.mts +2 -2
- package/dist/nextjs/index.d.ts +2 -2
- package/dist/react/index.d.mts +4 -4
- package/dist/react/index.d.ts +4 -4
- package/dist/react/index.js +158 -16
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +157 -17
- package/dist/react/index.mjs.map +1 -1
- package/dist/server/index.d.mts +3 -3
- package/dist/server/index.d.ts +3 -3
- package/dist/{types-DQSv7JAE.d.ts → types-BTA43eyz.d.ts} +1 -1
- package/dist/{types-Cms9VXx9.d.mts → types-CphqOTfm.d.mts} +1 -1
- package/dist/{types-BEqbz0tw.d.mts → types-DPINdOQW.d.mts} +2 -0
- package/dist/{types-BEqbz0tw.d.ts → types-DPINdOQW.d.ts} +2 -0
- package/package.json +8 -3
|
@@ -0,0 +1,995 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Platform-agnostic storage interface.
|
|
5
|
+
* Concrete implementations live under src/platforms/{web,rn,node}.
|
|
6
|
+
*/
|
|
7
|
+
interface StorageAdapter {
|
|
8
|
+
getItem(key: string): Promise<string | null>;
|
|
9
|
+
setItem(key: string, value: string): Promise<void>;
|
|
10
|
+
removeItem(key: string): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface RecaptchaV3 {
|
|
14
|
+
ready: (cb: () => void) => void;
|
|
15
|
+
execute: (siteKey: string, options: {
|
|
16
|
+
action: string;
|
|
17
|
+
}) => Promise<string>;
|
|
18
|
+
}
|
|
19
|
+
interface HCaptcha {
|
|
20
|
+
execute: (siteKey: string, options?: {
|
|
21
|
+
async: boolean;
|
|
22
|
+
}) => Promise<{
|
|
23
|
+
response: string;
|
|
24
|
+
}>;
|
|
25
|
+
render: (container: string | HTMLElement, options: object) => string;
|
|
26
|
+
}
|
|
27
|
+
declare global {
|
|
28
|
+
interface Window {
|
|
29
|
+
grecaptcha?: RecaptchaV3;
|
|
30
|
+
hcaptcha?: HCaptcha;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface TrackProperties {
|
|
35
|
+
[key: string]: unknown;
|
|
36
|
+
}
|
|
37
|
+
interface UserTraits {
|
|
38
|
+
email?: string;
|
|
39
|
+
name?: string;
|
|
40
|
+
firstName?: string;
|
|
41
|
+
lastName?: string;
|
|
42
|
+
phone?: string;
|
|
43
|
+
avatar?: string;
|
|
44
|
+
createdAt?: string;
|
|
45
|
+
[key: string]: unknown;
|
|
46
|
+
}
|
|
47
|
+
interface GroupTraits {
|
|
48
|
+
name?: string;
|
|
49
|
+
industry?: string;
|
|
50
|
+
employees?: number;
|
|
51
|
+
plan?: string;
|
|
52
|
+
[key: string]: unknown;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Remote Config Types
|
|
57
|
+
*
|
|
58
|
+
* Configuration fetched from SitePong servers to control SDK behavior
|
|
59
|
+
* without requiring npm updates.
|
|
60
|
+
*/
|
|
61
|
+
interface RemoteConfigFeatures {
|
|
62
|
+
/** Per-feature on/off toggles */
|
|
63
|
+
[key: string]: boolean;
|
|
64
|
+
}
|
|
65
|
+
interface RemoteConfigSampling {
|
|
66
|
+
/** Error sampling rate (0-1) */
|
|
67
|
+
errors?: number;
|
|
68
|
+
/** Analytics sampling rate (0-1) */
|
|
69
|
+
analytics?: number;
|
|
70
|
+
/** Replay sampling rate (0-1) */
|
|
71
|
+
replay?: number;
|
|
72
|
+
/** Performance sampling rate (0-1) */
|
|
73
|
+
performance?: number;
|
|
74
|
+
}
|
|
75
|
+
interface RemoteConfigTransport {
|
|
76
|
+
/** Flush interval in ms */
|
|
77
|
+
flushInterval?: number;
|
|
78
|
+
/** Max batch size */
|
|
79
|
+
maxBatchSize?: number;
|
|
80
|
+
/** Max retry attempts */
|
|
81
|
+
maxRetries?: number;
|
|
82
|
+
}
|
|
83
|
+
interface RemoteConfigAutocapture {
|
|
84
|
+
/** Enable click autocapture */
|
|
85
|
+
clicks?: boolean;
|
|
86
|
+
/** Enable form autocapture */
|
|
87
|
+
forms?: boolean;
|
|
88
|
+
/** Enable pageview autocapture */
|
|
89
|
+
pageviews?: boolean;
|
|
90
|
+
/** Enable RN app state tracking */
|
|
91
|
+
appState?: boolean;
|
|
92
|
+
/** Enable RN screen view tracking */
|
|
93
|
+
screenViews?: boolean;
|
|
94
|
+
}
|
|
95
|
+
interface RemoteConfig {
|
|
96
|
+
/** Feature toggles */
|
|
97
|
+
features: RemoteConfigFeatures;
|
|
98
|
+
/** Sampling rates */
|
|
99
|
+
sampling: RemoteConfigSampling;
|
|
100
|
+
/** Transport settings */
|
|
101
|
+
transport: RemoteConfigTransport;
|
|
102
|
+
/** Autocapture rules per platform */
|
|
103
|
+
autocapture: RemoteConfigAutocapture;
|
|
104
|
+
/** TTL in seconds before refetch */
|
|
105
|
+
ttl: number;
|
|
106
|
+
/** Minimum SDK version required (semver) */
|
|
107
|
+
minSdkVersion?: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Anonymous ID Management
|
|
112
|
+
* Generates and persists a unique ID for consistent flag evaluation
|
|
113
|
+
*/
|
|
114
|
+
declare function getAnonymousId(): string;
|
|
115
|
+
/**
|
|
116
|
+
* Clear the anonymous ID
|
|
117
|
+
* Useful for testing or when user wants to reset their identity
|
|
118
|
+
*/
|
|
119
|
+
declare function clearAnonymousId(): void;
|
|
120
|
+
/**
|
|
121
|
+
* Set a custom anonymous ID
|
|
122
|
+
* Useful when you want to use your own user identifier
|
|
123
|
+
*/
|
|
124
|
+
declare function setAnonymousId(id: string): void;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* SuperLink — deferred deep linking / smart links (OneLink/Branch-style).
|
|
128
|
+
*
|
|
129
|
+
* These types are platform-agnostic and shared between the web capture path
|
|
130
|
+
* and the React Native deferred-attribution path. They mirror the database
|
|
131
|
+
* schema (see supabase/migrations/*_superlink.sql): the redirect engine logs
|
|
132
|
+
* clicks + device fingerprints, and the mobile SDK matches on first launch to
|
|
133
|
+
* deliver the original deep link across the install gap.
|
|
134
|
+
*/
|
|
135
|
+
/**
|
|
136
|
+
* UTM parameters carried on a SuperLink. Keyed without the `utm_` prefix —
|
|
137
|
+
* the redirect URL's `utm_source`/`utm_medium`/… map to `source`/`medium`/…
|
|
138
|
+
* (self-contained so the SuperLink module has no cross-module dependencies).
|
|
139
|
+
*/
|
|
140
|
+
interface UtmParams {
|
|
141
|
+
source?: string;
|
|
142
|
+
medium?: string;
|
|
143
|
+
campaign?: string;
|
|
144
|
+
term?: string;
|
|
145
|
+
content?: string;
|
|
146
|
+
}
|
|
147
|
+
/** Platforms recognised by the redirect engine (matches superlink_platform). */
|
|
148
|
+
type SuperLinkPlatform = 'ios' | 'android' | 'desktop' | 'other';
|
|
149
|
+
/** How a deferred click was matched to an install (matches superlink_match_type). */
|
|
150
|
+
type SuperLinkMatchType = 'referrer' | 'clipboard' | 'qr' | 'identity' | 'fingerprint' | 'none';
|
|
151
|
+
/** Lifecycle event types (matches superlink_event_type). */
|
|
152
|
+
type SuperLinkEventType = 'clicked' | 'installed' | 'opened' | 'converted';
|
|
153
|
+
/**
|
|
154
|
+
* Configuration for the SuperLink client.
|
|
155
|
+
*/
|
|
156
|
+
interface SuperLinkConfig {
|
|
157
|
+
/** Redirect engine base URL. Defaults to the shared short domain. */
|
|
158
|
+
endpoint?: string;
|
|
159
|
+
/** Optional SuperLink app id (superlink_apps.id) for store-URL / AASA context. */
|
|
160
|
+
appId?: string;
|
|
161
|
+
/** Stable per-install id reported at match time (superlink_clicks.install_id). */
|
|
162
|
+
installId?: string;
|
|
163
|
+
/** Emit verbose diagnostics to the console. */
|
|
164
|
+
debug?: boolean;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Resolved deep link payload delivered to the app, whether captured directly
|
|
168
|
+
* on the web (inbound params), via a Universal Link / App Link open, or matched
|
|
169
|
+
* deferentially on first launch after an install.
|
|
170
|
+
*/
|
|
171
|
+
interface SuperLinkDeepLink {
|
|
172
|
+
/** In-app route, e.g. "/products/42" (superlink_links.deep_link_path). */
|
|
173
|
+
deep_link_path: string | null;
|
|
174
|
+
/** Arbitrary payload delivered on open (superlink_links.deep_link_data). */
|
|
175
|
+
deep_link_data: Record<string, unknown>;
|
|
176
|
+
/** Campaign params carried from the click URL. */
|
|
177
|
+
utm: UtmParams;
|
|
178
|
+
/** Affiliate / referral params carried from the click URL. */
|
|
179
|
+
referral: Record<string, unknown>;
|
|
180
|
+
/** Opaque click token, when known (superlink_clicks.click_id). */
|
|
181
|
+
click_id?: string | null;
|
|
182
|
+
/** How this link was resolved. */
|
|
183
|
+
match_type: SuperLinkMatchType;
|
|
184
|
+
/** 0..1 confidence — deterministic matches are 1, fingerprint matches lower. */
|
|
185
|
+
confidence: number;
|
|
186
|
+
}
|
|
187
|
+
/** Handler invoked with a resolved deferred deep link. */
|
|
188
|
+
type DeferredDeepLinkHandler = (link: SuperLinkDeepLink) => void;
|
|
189
|
+
/**
|
|
190
|
+
* Device fingerprint signals POSTed to /match. Mirrors the fingerprint columns
|
|
191
|
+
* on superlink_clicks. All fields are best-effort and optional.
|
|
192
|
+
*/
|
|
193
|
+
interface SuperLinkFingerprint {
|
|
194
|
+
platform: SuperLinkPlatform;
|
|
195
|
+
os?: string;
|
|
196
|
+
os_version?: string;
|
|
197
|
+
device_model?: string;
|
|
198
|
+
/** Browser name/UA, when known (web/desktop). */
|
|
199
|
+
browser?: string;
|
|
200
|
+
/** Coarse device class reported to the engine. */
|
|
201
|
+
device_type?: string;
|
|
202
|
+
/** Client IP, when the caller knows it (engine usually fills this in). */
|
|
203
|
+
ip?: string;
|
|
204
|
+
/** Raw user-agent string (web/desktop). */
|
|
205
|
+
user_agent?: string;
|
|
206
|
+
/** BCP-47 locale tag. */
|
|
207
|
+
language?: string;
|
|
208
|
+
}
|
|
209
|
+
/** Identity metadata for high-confidence matching against a click's metadata jsonb. */
|
|
210
|
+
interface SuperLinkIdentityMetadata {
|
|
211
|
+
/** User-supplied email for matching. */
|
|
212
|
+
email?: string;
|
|
213
|
+
/** User-supplied phone number for matching. */
|
|
214
|
+
phone?: string;
|
|
215
|
+
/** App-level user id for matching. */
|
|
216
|
+
user_id?: string;
|
|
217
|
+
/** Generic id for matching. */
|
|
218
|
+
id?: string;
|
|
219
|
+
/** Arbitrary user-provided attributes for custom matching. */
|
|
220
|
+
custom?: Record<string, unknown>;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* SuperLink deferred-deep-link registry — platform-agnostic.
|
|
225
|
+
*
|
|
226
|
+
* Holds the shared onDeferredDeepLink handler set, the cached last match, and
|
|
227
|
+
* the SuperLinkMatchResponse → SuperLinkDeepLink normaliser. Both the web/node
|
|
228
|
+
* recovery path (identify / completeFromScan) and the React Native first-launch
|
|
229
|
+
* attribution path emit through here so a single handler set sees every match.
|
|
230
|
+
*/
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Register a handler fired when a deferred deep link is matched (first-launch
|
|
234
|
+
* attribution, identify(), or completeFromScan()). If a match already happened
|
|
235
|
+
* before registration, the handler is invoked immediately with the cached
|
|
236
|
+
* payload. Returns an unsubscribe fn.
|
|
237
|
+
*/
|
|
238
|
+
declare function onDeferredDeepLink(handler: DeferredDeepLinkHandler): () => void;
|
|
239
|
+
/** The deferred deep link matched so far this process, if any. */
|
|
240
|
+
declare function getMatchedDeepLink(): SuperLinkDeepLink | null;
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* SuperLink URL parsing — platform-agnostic.
|
|
244
|
+
*
|
|
245
|
+
* Extracts the deep link payload encoded in a SuperLink URL: the path, any
|
|
246
|
+
* `~`-prefixed deep link data, UTM params, and `r_`-prefixed referral params.
|
|
247
|
+
* Works on both inbound web URLs and Universal Link / App Link opens. Uses the
|
|
248
|
+
* WHATWG `URL`, which is available on browser, RN (Hermes), and Node.
|
|
249
|
+
*/
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Parse a SuperLink (or Universal/App Link) URL into a deep link payload.
|
|
253
|
+
* Returns null if the URL can't be parsed.
|
|
254
|
+
*
|
|
255
|
+
* Conventions carried in the query string:
|
|
256
|
+
* - utm_* → utm
|
|
257
|
+
* - r_<key> → referral (affiliate params)
|
|
258
|
+
* - ~<key> → deep_link_data (Branch-style)
|
|
259
|
+
* - click_id → click token
|
|
260
|
+
* - $deep_link_path / dlp → explicit in-app route override
|
|
261
|
+
*/
|
|
262
|
+
declare function parseUniversalLink(url: string): SuperLinkDeepLink | null;
|
|
263
|
+
|
|
264
|
+
interface SitePongConfig {
|
|
265
|
+
apiKey: string;
|
|
266
|
+
endpoint?: string;
|
|
267
|
+
environment?: string;
|
|
268
|
+
release?: string;
|
|
269
|
+
autoCapture?: boolean;
|
|
270
|
+
maxBatchSize?: number;
|
|
271
|
+
flushInterval?: number;
|
|
272
|
+
debug?: boolean;
|
|
273
|
+
}
|
|
274
|
+
interface ErrorContext {
|
|
275
|
+
user?: {
|
|
276
|
+
id?: string;
|
|
277
|
+
email?: string;
|
|
278
|
+
[key: string]: unknown;
|
|
279
|
+
};
|
|
280
|
+
tags?: Record<string, string>;
|
|
281
|
+
extra?: Record<string, unknown>;
|
|
282
|
+
}
|
|
283
|
+
interface SitePongInitConfig extends SitePongConfig {
|
|
284
|
+
/** Enable feature flags (default: false) */
|
|
285
|
+
enableFlags?: boolean;
|
|
286
|
+
/** Custom endpoint for flags API (default: uses main endpoint) */
|
|
287
|
+
flagsEndpoint?: string;
|
|
288
|
+
/** Analytics configuration */
|
|
289
|
+
analytics?: {
|
|
290
|
+
enabled?: boolean;
|
|
291
|
+
autocapturePageviews?: boolean;
|
|
292
|
+
autocaptureClicks?: boolean;
|
|
293
|
+
autocaptureForms?: boolean;
|
|
294
|
+
/** Full autocapture configuration (overrides individual autocapture flags) */
|
|
295
|
+
autocapture?: {
|
|
296
|
+
clicks?: boolean;
|
|
297
|
+
forms?: boolean;
|
|
298
|
+
pageviews?: boolean;
|
|
299
|
+
blockSelectors?: string[];
|
|
300
|
+
allowSelectors?: string[];
|
|
301
|
+
} | boolean;
|
|
302
|
+
maxBatchSize?: number;
|
|
303
|
+
flushInterval?: number;
|
|
304
|
+
eventsEndpoint?: string;
|
|
305
|
+
};
|
|
306
|
+
/** Fingerprint / device intelligence configuration */
|
|
307
|
+
fingerprint?: {
|
|
308
|
+
enabled?: boolean;
|
|
309
|
+
extendedSignals?: boolean;
|
|
310
|
+
visitorEndpoint?: string;
|
|
311
|
+
};
|
|
312
|
+
/** Performance monitoring configuration */
|
|
313
|
+
performance?: {
|
|
314
|
+
enabled?: boolean;
|
|
315
|
+
webVitals?: boolean;
|
|
316
|
+
navigationTiming?: boolean;
|
|
317
|
+
resourceTiming?: boolean;
|
|
318
|
+
capturePageLoadTimings?: boolean;
|
|
319
|
+
capturePageRenderTimings?: boolean;
|
|
320
|
+
excludedResourceUrls?: string[];
|
|
321
|
+
resourceNameSanitizer?: (url: string) => string;
|
|
322
|
+
sampleRate?: number;
|
|
323
|
+
flushInterval?: number;
|
|
324
|
+
performanceEndpoint?: string;
|
|
325
|
+
};
|
|
326
|
+
/** Session replay configuration — records a rolling buffer and only sends on error */
|
|
327
|
+
replay?: {
|
|
328
|
+
enabled?: boolean;
|
|
329
|
+
maskInputs?: boolean;
|
|
330
|
+
blockSelector?: string;
|
|
331
|
+
maskSelector?: string;
|
|
332
|
+
sampleRate?: number;
|
|
333
|
+
maxSessionDuration?: number;
|
|
334
|
+
flushInterval?: number;
|
|
335
|
+
replayEndpoint?: string;
|
|
336
|
+
/** Record network requests (XHR/fetch) in the replay timeline */
|
|
337
|
+
recordNetwork?: boolean;
|
|
338
|
+
/** Include request/response headers in network recording */
|
|
339
|
+
captureNetworkHeaders?: boolean;
|
|
340
|
+
/** Record console logs in the replay timeline */
|
|
341
|
+
recordConsole?: boolean;
|
|
342
|
+
/** Which console levels to record (default: all) */
|
|
343
|
+
consoleLevels?: Array<'log' | 'info' | 'warn' | 'error' | 'debug'>;
|
|
344
|
+
/** Rolling buffer duration in ms — how many seconds of replay to keep before an error (default: 20000) */
|
|
345
|
+
bufferDuration?: number;
|
|
346
|
+
};
|
|
347
|
+
/** Watchtower tap capture (web) — tap timeline events + masked screen templates */
|
|
348
|
+
watchtower?: {
|
|
349
|
+
enabled?: boolean;
|
|
350
|
+
/** Project ID sent as X-Project-ID on /api/taps requests (required) */
|
|
351
|
+
projectId?: string;
|
|
352
|
+
/** Override base endpoint for /api/taps + /api/taps/template (default: main endpoint) */
|
|
353
|
+
endpoint?: string;
|
|
354
|
+
/** Flush at this many buffered events (default: 50) */
|
|
355
|
+
maxBatchSize?: number;
|
|
356
|
+
/** Flush interval in ms (default: 10000) */
|
|
357
|
+
flushInterval?: number;
|
|
358
|
+
/** Extra CSS selector blocked out of the masked screen template */
|
|
359
|
+
blockSelector?: string;
|
|
360
|
+
/** CSS selector whose text is masked in the screen template */
|
|
361
|
+
maskSelector?: string;
|
|
362
|
+
};
|
|
363
|
+
/** Cron monitoring configuration */
|
|
364
|
+
crons?: {
|
|
365
|
+
enabled?: boolean;
|
|
366
|
+
};
|
|
367
|
+
/** Custom metrics configuration */
|
|
368
|
+
metrics?: {
|
|
369
|
+
enabled?: boolean;
|
|
370
|
+
flushInterval?: number;
|
|
371
|
+
maxBatchSize?: number;
|
|
372
|
+
};
|
|
373
|
+
/** Database query tracking configuration */
|
|
374
|
+
database?: {
|
|
375
|
+
enabled?: boolean;
|
|
376
|
+
slowQueryThreshold?: number;
|
|
377
|
+
redactParams?: boolean;
|
|
378
|
+
};
|
|
379
|
+
/** Production profiling configuration */
|
|
380
|
+
profiling?: {
|
|
381
|
+
enabled?: boolean;
|
|
382
|
+
sampleRate?: number;
|
|
383
|
+
maxDuration?: number;
|
|
384
|
+
flushInterval?: number;
|
|
385
|
+
};
|
|
386
|
+
/** Remote config options */
|
|
387
|
+
remoteConfig?: {
|
|
388
|
+
enabled?: boolean;
|
|
389
|
+
};
|
|
390
|
+
/** Storage adapter for caching (auto-detected if not provided) */
|
|
391
|
+
_storageAdapter?: StorageAdapter;
|
|
392
|
+
}
|
|
393
|
+
declare const initRN: (config: SitePongInitConfig) => void;
|
|
394
|
+
declare const captureError: (error: Error | string, additionalContext?: ErrorContext) => void;
|
|
395
|
+
declare const captureMessage: (message: string, level?: "info" | "warning" | "error", additionalContext?: ErrorContext) => void;
|
|
396
|
+
declare const setContext: (context: ErrorContext) => void;
|
|
397
|
+
declare const setUser: (user: ErrorContext["user"]) => void;
|
|
398
|
+
declare const setTags: (tags: Record<string, string>) => void;
|
|
399
|
+
declare const flush: () => Promise<void>;
|
|
400
|
+
declare const isInitialized: () => boolean;
|
|
401
|
+
declare const clearUser: () => void;
|
|
402
|
+
declare const addBreadcrumb: (breadcrumb: {
|
|
403
|
+
type?: "default" | "http" | "navigation" | "ui" | "console" | "error";
|
|
404
|
+
category?: string;
|
|
405
|
+
message?: string;
|
|
406
|
+
level?: "fatal" | "error" | "warning" | "info" | "debug";
|
|
407
|
+
data?: Record<string, unknown>;
|
|
408
|
+
}) => void;
|
|
409
|
+
declare const setCurrentScreen: (name: string | undefined) => void;
|
|
410
|
+
|
|
411
|
+
declare const getFlag: (key: string, defaultValue?: boolean) => boolean;
|
|
412
|
+
declare const getAllFlags: () => Record<string, boolean>;
|
|
413
|
+
declare const getVariant: (key: string, defaultValue?: string | null) => string | null;
|
|
414
|
+
declare const getVariantPayload: <T = unknown>(key: string, defaultValue?: T | null) => T | null;
|
|
415
|
+
declare const waitForFlags: () => Promise<void>;
|
|
416
|
+
declare const areFlagsReady: () => boolean;
|
|
417
|
+
declare const refreshFlags: () => Promise<void>;
|
|
418
|
+
declare const track: (eventName: string, properties?: TrackProperties) => void;
|
|
419
|
+
declare const identify$1: (userId: string, traits?: UserTraits) => void;
|
|
420
|
+
declare const group: (groupId: string, traits?: GroupTraits) => void;
|
|
421
|
+
declare const resetAnalytics: () => void;
|
|
422
|
+
declare const getRemoteConfig: () => RemoteConfig | null;
|
|
423
|
+
declare const isRemoteConfigFeatureEnabled: (key: string, defaultValue?: boolean) => boolean;
|
|
424
|
+
declare const onRemoteConfigChange: (listener: (config: RemoteConfig) => void) => () => void;
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* React Native Storage Adapter
|
|
428
|
+
*
|
|
429
|
+
* Wraps any AsyncStorage-compatible instance into the SDK's StorageAdapter interface.
|
|
430
|
+
*/
|
|
431
|
+
|
|
432
|
+
interface AsyncStorageLike {
|
|
433
|
+
getItem(key: string): Promise<string | null>;
|
|
434
|
+
setItem(key: string, value: string): Promise<void>;
|
|
435
|
+
removeItem(key: string): Promise<void>;
|
|
436
|
+
}
|
|
437
|
+
declare function createAsyncStorageAdapter(asyncStorage: AsyncStorageLike): StorageAdapter;
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* React Navigation Tracker
|
|
441
|
+
*
|
|
442
|
+
* Integrates with React Navigation's navigationRef to track
|
|
443
|
+
* $screen_view events and navigation breadcrumbs.
|
|
444
|
+
*/
|
|
445
|
+
interface NavigationRef {
|
|
446
|
+
addListener: (event: string, callback: (...args: unknown[]) => void) => () => void;
|
|
447
|
+
getCurrentRoute: () => {
|
|
448
|
+
name: string;
|
|
449
|
+
params?: Record<string, unknown>;
|
|
450
|
+
} | undefined;
|
|
451
|
+
}
|
|
452
|
+
interface NavigationTrackerOptions {
|
|
453
|
+
/** Track screen view events (default: true) */
|
|
454
|
+
trackScreenViews?: boolean;
|
|
455
|
+
/** Add navigation breadcrumbs (default: true) */
|
|
456
|
+
addBreadcrumbs?: boolean;
|
|
457
|
+
/** Screen name filter — return null to skip tracking */
|
|
458
|
+
screenNameFilter?: (name: string) => string | null;
|
|
459
|
+
}
|
|
460
|
+
declare function createNavigationTracker(navigationRef: NavigationRef, options?: NavigationTrackerOptions): () => void;
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* React Native Performance Manager
|
|
464
|
+
*
|
|
465
|
+
* Cold start timing and screen render tracking for RN apps.
|
|
466
|
+
*/
|
|
467
|
+
/**
|
|
468
|
+
* Call at the very top of your app entry point to capture cold start.
|
|
469
|
+
* Must be called before any async work.
|
|
470
|
+
*/
|
|
471
|
+
declare function markColdStart(): void;
|
|
472
|
+
declare class RNPerformanceManager {
|
|
473
|
+
private screenRenderStarts;
|
|
474
|
+
/**
|
|
475
|
+
* Track cold start time from markColdStart() to now.
|
|
476
|
+
* Should be called once the app is interactive (e.g., in the root component's useEffect).
|
|
477
|
+
*/
|
|
478
|
+
trackColdStart(): void;
|
|
479
|
+
/**
|
|
480
|
+
* Start tracking a screen render. Call before rendering starts.
|
|
481
|
+
*/
|
|
482
|
+
startScreenRender(screenName: string): void;
|
|
483
|
+
/**
|
|
484
|
+
* End tracking a screen render. Call after rendering completes.
|
|
485
|
+
*/
|
|
486
|
+
endScreenRender(screenName: string): number | null;
|
|
487
|
+
/**
|
|
488
|
+
* Track a screen render using a useEffect-friendly pattern.
|
|
489
|
+
* Returns a cleanup function.
|
|
490
|
+
*/
|
|
491
|
+
trackScreenRender(screenName: string): () => void;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* React Native Screen Recorder SDK Integration
|
|
496
|
+
*
|
|
497
|
+
* Two modes:
|
|
498
|
+
* 1. **On error (via provider)**: Recording starts automatically, keeps a 10s
|
|
499
|
+
* rolling buffer. On error the buffer is flushed and attached to the error.
|
|
500
|
+
* 2. **Manual**: Call startScreenRecording / stopScreenRecording / flushScreenRecording
|
|
501
|
+
* yourself. Keeps a 60s rolling buffer by default.
|
|
502
|
+
*/
|
|
503
|
+
interface ScreenRecordingConfig {
|
|
504
|
+
/** Enable screen recording (default: false) */
|
|
505
|
+
enabled?: boolean;
|
|
506
|
+
/** Frames per second (default: 1) */
|
|
507
|
+
fps?: number;
|
|
508
|
+
/** Video quality preset */
|
|
509
|
+
quality?: 'low' | 'standard' | 'high';
|
|
510
|
+
/** Sample rate 0-1: what fraction of sessions to record (default: 1.0) */
|
|
511
|
+
sampleRate?: number;
|
|
512
|
+
/** Max recording duration in ms (default: 60 min) */
|
|
513
|
+
maxDuration?: number;
|
|
514
|
+
/**
|
|
515
|
+
* Rolling buffer duration in ms — how much video to keep.
|
|
516
|
+
* - On-error mode (via provider): default 10_000 (10 seconds)
|
|
517
|
+
* - Manual mode: default 60_000 (60 seconds)
|
|
518
|
+
*/
|
|
519
|
+
bufferDuration?: number;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Start screen recording manually.
|
|
523
|
+
* Recording runs in a 60s rolling buffer. Call flushScreenRecording() to upload.
|
|
524
|
+
*/
|
|
525
|
+
declare function startScreenRecording(apiKey: string, endpoint: string, sessionId: string, config?: Omit<ScreenRecordingConfig, 'enabled'>): boolean;
|
|
526
|
+
/**
|
|
527
|
+
* Stop screen recording and discard the buffer.
|
|
528
|
+
*/
|
|
529
|
+
declare function stopScreenRecording(): void;
|
|
530
|
+
/**
|
|
531
|
+
* Flush the rolling buffer to the server.
|
|
532
|
+
* In on-error mode this is called automatically by the error handler.
|
|
533
|
+
* In manual mode, call this yourself to upload the buffer.
|
|
534
|
+
*/
|
|
535
|
+
declare function flushScreenRecording(): Promise<void>;
|
|
536
|
+
/**
|
|
537
|
+
* @deprecated Use flushScreenRecording() instead.
|
|
538
|
+
*/
|
|
539
|
+
declare const flushScreenRecordingOnError: typeof flushScreenRecording;
|
|
540
|
+
/**
|
|
541
|
+
* Check if screen recording is currently active.
|
|
542
|
+
*/
|
|
543
|
+
declare function isScreenRecording(): boolean;
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* SitePong React Native Provider
|
|
547
|
+
*
|
|
548
|
+
* Mirrors the react/provider.tsx pattern with RN-specific setup.
|
|
549
|
+
*/
|
|
550
|
+
|
|
551
|
+
interface SitePongRNContextValue {
|
|
552
|
+
isInitialized: boolean;
|
|
553
|
+
performanceManager: RNPerformanceManager | null;
|
|
554
|
+
}
|
|
555
|
+
interface SitePongRNProviderProps {
|
|
556
|
+
/** API key in format: sp_live_xxx or sp_test_xxx */
|
|
557
|
+
apiKey: string;
|
|
558
|
+
/** Additional configuration options */
|
|
559
|
+
config?: Omit<SitePongInitConfig, 'apiKey'>;
|
|
560
|
+
/** AsyncStorage instance for persistence */
|
|
561
|
+
asyncStorage?: AsyncStorageLike;
|
|
562
|
+
/** React Navigation ref for screen tracking */
|
|
563
|
+
navigationRef?: NavigationRef;
|
|
564
|
+
/** Enable network request interception (default: true) */
|
|
565
|
+
trackNetwork?: boolean;
|
|
566
|
+
/** Enable app state tracking (default: true) */
|
|
567
|
+
trackAppState?: boolean;
|
|
568
|
+
/** Enable error handler setup (default: true) */
|
|
569
|
+
captureErrors?: boolean;
|
|
570
|
+
/** Screen recording configuration — records rolling buffer, only sends on error */
|
|
571
|
+
screenRecording?: ScreenRecordingConfig;
|
|
572
|
+
/** Native device token (APNs hex string or FCM registration token) for direct push delivery */
|
|
573
|
+
devicePushToken?: string;
|
|
574
|
+
/** Device platform — required when using devicePushToken */
|
|
575
|
+
devicePlatform?: 'ios' | 'android';
|
|
576
|
+
/** APNs environment for push notifications */
|
|
577
|
+
pushEnvironment?: 'sandbox' | 'production';
|
|
578
|
+
/**
|
|
579
|
+
* @deprecated Ignored. Associate via `POST /api/push/tokens/associate`
|
|
580
|
+
* from your backend using a `sp_push_xxx` key — see the SDK README.
|
|
581
|
+
*/
|
|
582
|
+
pushUserId?: string;
|
|
583
|
+
children: React.ReactNode;
|
|
584
|
+
}
|
|
585
|
+
declare function SitePongRNProvider({ apiKey, config, asyncStorage, navigationRef, trackNetwork, trackAppState, captureErrors, screenRecording, devicePushToken, devicePlatform, pushEnvironment, pushUserId, children, }: SitePongRNProviderProps): React.ReactElement;
|
|
586
|
+
declare function useSitePongRNContext(): SitePongRNContextValue;
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* React Native Hooks
|
|
590
|
+
*
|
|
591
|
+
* RN-specific hooks + re-exported base hooks.
|
|
592
|
+
*/
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Track a screen render automatically via useEffect.
|
|
596
|
+
*/
|
|
597
|
+
declare function useScreenTrack(screenName: string): void;
|
|
598
|
+
/**
|
|
599
|
+
* Track app state with a reactive hook.
|
|
600
|
+
*/
|
|
601
|
+
declare function useAppState(): string;
|
|
602
|
+
/**
|
|
603
|
+
* Access remote config with reactive updates.
|
|
604
|
+
*/
|
|
605
|
+
declare function useRemoteConfig(): RemoteConfig | null;
|
|
606
|
+
/**
|
|
607
|
+
* Track screen render performance. Returns duration when render completes.
|
|
608
|
+
*/
|
|
609
|
+
declare function useRNPerformance(screenName: string): {
|
|
610
|
+
duration: number | null;
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* React Native Device Info
|
|
615
|
+
*
|
|
616
|
+
* Collects device information using only RN built-in APIs.
|
|
617
|
+
* Zero external dependencies — uses only Platform and Dimensions.
|
|
618
|
+
*/
|
|
619
|
+
interface RNDeviceInfo {
|
|
620
|
+
platform: 'ios' | 'android';
|
|
621
|
+
osVersion?: string;
|
|
622
|
+
deviceName?: string;
|
|
623
|
+
deviceBrand?: string;
|
|
624
|
+
deviceModel?: string;
|
|
625
|
+
appVersion?: string;
|
|
626
|
+
appBuildNumber?: string;
|
|
627
|
+
screenWidth?: number;
|
|
628
|
+
screenHeight?: number;
|
|
629
|
+
screenScale?: number;
|
|
630
|
+
isEmulator?: boolean;
|
|
631
|
+
deviceId?: string;
|
|
632
|
+
}
|
|
633
|
+
declare function collectDeviceInfo(): RNDeviceInfo;
|
|
634
|
+
/** @deprecated No-op, returns null. Kept for API compatibility. */
|
|
635
|
+
declare function fetchPersistentDeviceId(): Promise<string | null>;
|
|
636
|
+
/** @deprecated No-op, returns null. Kept for API compatibility. */
|
|
637
|
+
declare function fetchNativeDeviceSignals(): Promise<null>;
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* React Native Error Handler
|
|
641
|
+
*
|
|
642
|
+
* Enhanced ErrorUtils.setGlobalHandler() + Promise rejection tracking.
|
|
643
|
+
* Returns a teardown function.
|
|
644
|
+
*/
|
|
645
|
+
interface RNErrorHandlerOptions {
|
|
646
|
+
/** Capture fatal errors (default: true) */
|
|
647
|
+
captureFatal?: boolean;
|
|
648
|
+
/** Capture non-fatal errors (default: true) */
|
|
649
|
+
captureNonFatal?: boolean;
|
|
650
|
+
/** Capture unhandled promise rejections (default: true) */
|
|
651
|
+
capturePromiseRejections?: boolean;
|
|
652
|
+
}
|
|
653
|
+
declare function setupRNErrorHandler(options?: RNErrorHandlerOptions): () => void;
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Watchtower tap autocapture — React Native JS layer (spec §4.2).
|
|
657
|
+
*
|
|
658
|
+
* This file is intentionally MINIMAL. The hot path — capturing taps, taking
|
|
659
|
+
* screenshots, perceptual hashing, redaction, and upload — all happens in the
|
|
660
|
+
* shared native engine `WatchtowerCore` (spec §3), reached through the thin
|
|
661
|
+
* Expo bridge in `@sitepong/screen-recorder`. capture-core's JS dHash is NOT on
|
|
662
|
+
* the RN runtime path; the engine hashes natively.
|
|
663
|
+
*
|
|
664
|
+
* JS's only jobs here:
|
|
665
|
+
* (a) start the native engine with apiKey/projectId/endpoint + platform
|
|
666
|
+
* "react-native-ios",
|
|
667
|
+
* (b) feed it React-Navigation route names by subscribing to the existing
|
|
668
|
+
* navigation tracker (navigation.ts) and calling native setScreen on each
|
|
669
|
+
* $screen_view.
|
|
670
|
+
*
|
|
671
|
+
* Element identity comes for free: RN maps a component's `testID` to the iOS
|
|
672
|
+
* view's `accessibilityIdentifier`, which the §3.1 swizzle reads natively.
|
|
673
|
+
*/
|
|
674
|
+
|
|
675
|
+
interface WatchtowerConfig {
|
|
676
|
+
/** API key (demo uses key_demo). */
|
|
677
|
+
apiKey: string;
|
|
678
|
+
/** Project id (demo uses proj_demo). */
|
|
679
|
+
projectId: string;
|
|
680
|
+
/** Ingest endpoint, e.g. http://localhost:8787. */
|
|
681
|
+
endpoint: string;
|
|
682
|
+
/** Screenshot sample rate (passed through to the engine; default 0.1). */
|
|
683
|
+
sampleRate?: number;
|
|
684
|
+
/**
|
|
685
|
+
* Platform stamped on every tap event. Defaults to "react-native-ios" and
|
|
686
|
+
* should not normally be overridden — it is what proves "one engine, two
|
|
687
|
+
* apps" at the wire level.
|
|
688
|
+
*/
|
|
689
|
+
platform?: string;
|
|
690
|
+
/**
|
|
691
|
+
* Initial user identity, stamped as distinct_id on every event. Update it
|
|
692
|
+
* later (e.g. after login) with setWatchtowerUser(). Pass the same value
|
|
693
|
+
* you give the SDK's identify() so users line up across pipelines.
|
|
694
|
+
*/
|
|
695
|
+
distinctId?: string;
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Start the shared native capture engine for React Native. Idempotent.
|
|
699
|
+
* Forwards directly to `Watchtower.start(...)` in WatchtowerCore (§3) via the
|
|
700
|
+
* native bridge — no capture logic in JS.
|
|
701
|
+
*/
|
|
702
|
+
declare function startWatchtower(config: WatchtowerConfig): void;
|
|
703
|
+
/**
|
|
704
|
+
* Set user identity — stamped as distinct_id on every subsequent event. Call
|
|
705
|
+
* this wherever you call the SDK's identify(), with the same id.
|
|
706
|
+
*/
|
|
707
|
+
declare function setWatchtowerUser(distinctId: string | null): void;
|
|
708
|
+
/**
|
|
709
|
+
* The engine's current capture session id (null when not running). Attach it
|
|
710
|
+
* to error reports/analytics — it is the key that joins an error to its
|
|
711
|
+
* Watchtower session for replay.
|
|
712
|
+
*/
|
|
713
|
+
declare function getWatchtowerSessionId(): string | null;
|
|
714
|
+
/** Stop the engine; native side flushes pending taps. */
|
|
715
|
+
declare function stopWatchtower(): void;
|
|
716
|
+
/**
|
|
717
|
+
* Subscribe to React-Navigation screen changes and feed each route name to the
|
|
718
|
+
* native engine via setScreen. Built on the EXISTING navigation tracker
|
|
719
|
+
* (navigation.ts): we hook its per-screen-change callback (`screenNameFilter`)
|
|
720
|
+
* to forward the resolved screen name to native, then return it unchanged so
|
|
721
|
+
* the normal $screen_view tracking still fires. Returns an unsubscribe fn.
|
|
722
|
+
*/
|
|
723
|
+
declare function subscribeNavigationToWatchtower(navigationRef: NavigationRef): () => void;
|
|
724
|
+
interface WatchtowerProviderProps {
|
|
725
|
+
config: WatchtowerConfig;
|
|
726
|
+
/** React Navigation ref — required to feed route names to the engine. */
|
|
727
|
+
navigationRef: NavigationRef;
|
|
728
|
+
children?: React.ReactNode;
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Provider that starts the native engine on mount and wires React-Navigation
|
|
732
|
+
* screen views to native setScreen. Renders children unchanged.
|
|
733
|
+
*/
|
|
734
|
+
declare function WatchtowerProvider(props: WatchtowerProviderProps): React.ReactElement;
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* React Native Network Interception
|
|
738
|
+
*
|
|
739
|
+
* XHR monkey-patch for request tracking + breadcrumbs.
|
|
740
|
+
* RN fetch is XHR internally, so intercepting XMLHttpRequest captures all network.
|
|
741
|
+
*/
|
|
742
|
+
interface NetworkInterceptionOptions {
|
|
743
|
+
/** Track request/response as breadcrumbs (default: true) */
|
|
744
|
+
addBreadcrumbs?: boolean;
|
|
745
|
+
/** URL patterns to ignore (e.g., SitePong's own endpoints) */
|
|
746
|
+
ignoreUrls?: (string | RegExp)[];
|
|
747
|
+
/** Max breadcrumb data size in bytes (default: 1024) */
|
|
748
|
+
maxDataSize?: number;
|
|
749
|
+
}
|
|
750
|
+
declare function setupNetworkInterception(options?: NetworkInterceptionOptions): () => void;
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* React Native Autocapture Module
|
|
754
|
+
*
|
|
755
|
+
* Tracks AppState changes (foreground/background/inactive) automatically.
|
|
756
|
+
*/
|
|
757
|
+
interface RNAutocaptureOptions {
|
|
758
|
+
/** Track app state changes (default: true) */
|
|
759
|
+
trackAppState?: boolean;
|
|
760
|
+
}
|
|
761
|
+
declare class RNAutocaptureModule {
|
|
762
|
+
private options;
|
|
763
|
+
private appStateSubscription;
|
|
764
|
+
private currentAppState;
|
|
765
|
+
constructor(options?: RNAutocaptureOptions);
|
|
766
|
+
start(): void;
|
|
767
|
+
stop(): void;
|
|
768
|
+
private setupAppStateTracking;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/**
|
|
772
|
+
* SQLite Query Tracker for expo-sqlite
|
|
773
|
+
*
|
|
774
|
+
* Wraps an expo-sqlite database handle to intercept and time all queries.
|
|
775
|
+
* Slow queries are reported as analytics events and breadcrumbs.
|
|
776
|
+
*/
|
|
777
|
+
interface TrackedDatabaseOptions {
|
|
778
|
+
/** Threshold in ms — queries slower than this are tracked (default: 100) */
|
|
779
|
+
slowQueryThreshold?: number;
|
|
780
|
+
/** If true, track every query regardless of duration (default: false) */
|
|
781
|
+
trackAll?: boolean;
|
|
782
|
+
}
|
|
783
|
+
/** Minimal interface matching expo-sqlite's SQLiteDatabase */
|
|
784
|
+
interface SQLiteDatabase {
|
|
785
|
+
execAsync(sql: string): Promise<void>;
|
|
786
|
+
runAsync(sql: string, ...params: unknown[]): Promise<{
|
|
787
|
+
changes: number;
|
|
788
|
+
lastInsertRowId: number;
|
|
789
|
+
}>;
|
|
790
|
+
getAllAsync(sql: string, ...params: unknown[]): Promise<unknown[]>;
|
|
791
|
+
getFirstAsync(sql: string, ...params: unknown[]): Promise<unknown | null>;
|
|
792
|
+
execSync(sql: string): void;
|
|
793
|
+
runSync(sql: string, ...params: unknown[]): {
|
|
794
|
+
changes: number;
|
|
795
|
+
lastInsertRowId: number;
|
|
796
|
+
};
|
|
797
|
+
getAllSync(sql: string, ...params: unknown[]): unknown[];
|
|
798
|
+
getFirstSync(sql: string, ...params: unknown[]): unknown | null;
|
|
799
|
+
[key: string]: unknown;
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Wrap an expo-sqlite database with query timing and tracking.
|
|
803
|
+
*
|
|
804
|
+
* Returns a proxy that intercepts all query methods. Use it exactly like the
|
|
805
|
+
* original database — same API, same return values.
|
|
806
|
+
*
|
|
807
|
+
* @example
|
|
808
|
+
* ```ts
|
|
809
|
+
* import { createTrackedDatabase } from 'sitepong/react-native';
|
|
810
|
+
* import * as SQLite from 'expo-sqlite';
|
|
811
|
+
*
|
|
812
|
+
* const db = SQLite.openDatabaseSync('myapp.db');
|
|
813
|
+
* const trackedDb = createTrackedDatabase(db, { slowQueryThreshold: 100 });
|
|
814
|
+
* const users = trackedDb.getAllSync('SELECT * FROM users WHERE active = 1');
|
|
815
|
+
* ```
|
|
816
|
+
*/
|
|
817
|
+
declare function createTrackedDatabase<T extends SQLiteDatabase>(db: T, options?: TrackedDatabaseOptions): T;
|
|
818
|
+
|
|
819
|
+
/**
|
|
820
|
+
* Push Notification & Live Activity token registration for React Native.
|
|
821
|
+
*
|
|
822
|
+
* Registers Expo push tokens and APNs Live Activity tokens with the
|
|
823
|
+
* SitePong ingest server for remote push notification delivery.
|
|
824
|
+
*
|
|
825
|
+
* For Live Activities, prefer the turnkey `@sitepong/expo-live-activity`
|
|
826
|
+
* package — it ships a built-in SwiftUI widget template (SF Symbols,
|
|
827
|
+
* custom progress bar with sliding icon, visibility-driven slots) and
|
|
828
|
+
* forwards push tokens to the registration functions in this file
|
|
829
|
+
* automatically. Use the lower-level `registerLiveActivityToken` and
|
|
830
|
+
* `registerPushToStartToken` exports below only if you author your own
|
|
831
|
+
* iOS Widget Extension and `ActivityAttributes` struct in Swift.
|
|
832
|
+
*
|
|
833
|
+
* ## User attribution (two-step)
|
|
834
|
+
*
|
|
835
|
+
* These register* functions only store (project_id, token, device_id). They
|
|
836
|
+
* deliberately do not accept or send a user_id — publishable SDK keys are
|
|
837
|
+
* extractable from compiled apps, so letting the client attach arbitrary
|
|
838
|
+
* user_ids would let a leaked key shadow-subscribe to another user's pushes.
|
|
839
|
+
*
|
|
840
|
+
* After the user authenticates with your backend, have your backend call
|
|
841
|
+
* `POST /api/push/tokens/associate` (authenticated with your `sp_push_xxx`
|
|
842
|
+
* server key) to bind the token to the user_id.
|
|
843
|
+
*
|
|
844
|
+
* @since 0.1.0
|
|
845
|
+
*/
|
|
846
|
+
interface PushEnvironmentOptions {
|
|
847
|
+
environment: 'sandbox' | 'production';
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* Register an Expo push token for receiving regular push notifications.
|
|
851
|
+
*
|
|
852
|
+
* To attach this token to an authenticated user, have your backend call
|
|
853
|
+
* `POST https://api.sitepong.com/api/push/tokens/associate` with
|
|
854
|
+
* `Authorization: Bearer sp_push_xxx` and body `{ token, user_id }`.
|
|
855
|
+
*/
|
|
856
|
+
declare function registerPushToken(token: string, options: PushEnvironmentOptions): void;
|
|
857
|
+
/**
|
|
858
|
+
* Register a native device token (APNs or FCM) for direct push delivery.
|
|
859
|
+
* This bypasses Expo and sends directly to Apple/Google.
|
|
860
|
+
*
|
|
861
|
+
* @param token - The raw device token (hex string for APNs, FCM registration token for Android)
|
|
862
|
+
* @param options - Platform and environment. `userId` is accepted but ignored
|
|
863
|
+
* — see the two-step attribution note at the top of this file.
|
|
864
|
+
*/
|
|
865
|
+
declare function registerDeviceToken(token: string, options: {
|
|
866
|
+
platform: 'ios' | 'android';
|
|
867
|
+
environment: 'sandbox' | 'production';
|
|
868
|
+
/** @deprecated Ignored. Associate via POST /api/push/tokens/associate from your backend. */
|
|
869
|
+
userId?: string;
|
|
870
|
+
}): void;
|
|
871
|
+
/**
|
|
872
|
+
* Register a running Live Activity's push token for remote updates.
|
|
873
|
+
*/
|
|
874
|
+
declare function registerLiveActivityToken(activityType: string, activityId: string, pushToken: string, options: PushEnvironmentOptions): void;
|
|
875
|
+
/**
|
|
876
|
+
* Register a push-to-start token for remotely launching Live Activities (iOS 17.2+).
|
|
877
|
+
*/
|
|
878
|
+
declare function registerPushToStartToken(activityType: string, pushToStartToken: string, options: PushEnvironmentOptions): void;
|
|
879
|
+
/**
|
|
880
|
+
* Mark a Live Activity as ended (deactivates its token).
|
|
881
|
+
*/
|
|
882
|
+
declare function endLiveActivity(activityType: string, activityId: string): void;
|
|
883
|
+
|
|
884
|
+
interface WidgetSyncOptions {
|
|
885
|
+
refreshInterval?: number;
|
|
886
|
+
}
|
|
887
|
+
declare function syncWidgets(options?: WidgetSyncOptions): Promise<void>;
|
|
888
|
+
declare function updateWidgetData(data: Record<string, unknown>): Promise<void>;
|
|
889
|
+
declare function triggerWidgetRefresh(): void;
|
|
890
|
+
declare function stopWidgetSync(): void;
|
|
891
|
+
|
|
892
|
+
/**
|
|
893
|
+
* SuperLink — React Native deferred deep linking / attribution.
|
|
894
|
+
*
|
|
895
|
+
* On first launch, the SDK resolves the deep link the user originally clicked
|
|
896
|
+
* before the app was installed ("deferred deep link"), bridging the install
|
|
897
|
+
* gap that ordinary Universal Links / App Links can't cross:
|
|
898
|
+
*
|
|
899
|
+
* - Android: read the Play Install Referrer to recover the deterministic
|
|
900
|
+
* `click_id` the redirect engine stamped on the Play Store URL.
|
|
901
|
+
* - iOS: attempt a clipboard read for a click token handed off by the
|
|
902
|
+
* interstitial (Safari → App Store → app).
|
|
903
|
+
* - Both: gather a minimal device fingerprint (UA/model/os/os_version/locale)
|
|
904
|
+
* as a probabilistic fallback.
|
|
905
|
+
*
|
|
906
|
+
* It then POSTs /match and, on a hit, invokes any registered
|
|
907
|
+
* onDeferredDeepLink handler with the resolved payload.
|
|
908
|
+
*
|
|
909
|
+
* For apps that are ALREADY installed, use parseUniversalLink() +
|
|
910
|
+
* createSuperLinkListener() to handle direct opens and report `opened` events.
|
|
911
|
+
*
|
|
912
|
+
* Every native dependency is loaded through guarded optional requires, exactly
|
|
913
|
+
* like the rest of the RN SDK — so an app that hasn't installed
|
|
914
|
+
* `react-native-play-install-referrer` / `expo-clipboard` still builds and the
|
|
915
|
+
* SDK degrades to fingerprint-only matching.
|
|
916
|
+
*/
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Configure SuperLink and run deferred-attribution on first launch.
|
|
920
|
+
*
|
|
921
|
+
* Idempotent: the /match round-trip runs at most once per process. Safe to
|
|
922
|
+
* call from app bootstrap. Returns the matched deep link, or null.
|
|
923
|
+
*
|
|
924
|
+
* Supports identity metadata extraction from the clipboard or from passed options,
|
|
925
|
+
* enabling deterministic matching when the user has provided email/phone/custom
|
|
926
|
+
* attributes on the source link.
|
|
927
|
+
*/
|
|
928
|
+
declare function initSuperLinkRN(config?: SuperLinkConfig, identityOverride?: SuperLinkIdentityMetadata): Promise<SuperLinkDeepLink | null>;
|
|
929
|
+
/**
|
|
930
|
+
* Recover a deferred deep link AFTER the user provides an email/phone (or other
|
|
931
|
+
* identity) at signup. POSTs /match with { identity, install_id, fingerprint }
|
|
932
|
+
* so the engine matches the identity against an unmatched click's metadata.
|
|
933
|
+
* Fires onDeferredDeepLink on a hit. Returns the resolved deep link, or null.
|
|
934
|
+
*/
|
|
935
|
+
declare function identify(identity: SuperLinkIdentityMetadata): Promise<SuperLinkDeepLink | null>;
|
|
936
|
+
/**
|
|
937
|
+
* Complete attribution from a scanned QR payload. POSTs /match with
|
|
938
|
+
* { qr_token: scanned, install_id } — the raw scanned string is passed straight
|
|
939
|
+
* through, and the engine parses a click-token URL (/c/<id>), a raw click_id, a
|
|
940
|
+
* link URL (pongl.ink/<slug>), or a bare <slug>. Fires onDeferredDeepLink on a
|
|
941
|
+
* hit. Returns the resolved deep link, or null.
|
|
942
|
+
*/
|
|
943
|
+
declare function completeFromScan(scanned: string): Promise<SuperLinkDeepLink | null>;
|
|
944
|
+
/**
|
|
945
|
+
* Handle a direct open of an already-installed app via a Universal Link /
|
|
946
|
+
* App Link URL: parse the payload and report an `opened` event. Returns the
|
|
947
|
+
* parsed deep link (does NOT fire onDeferredDeepLink handlers — that channel is
|
|
948
|
+
* reserved for deferred first-launch matches).
|
|
949
|
+
*/
|
|
950
|
+
declare function handleUniversalLink(url: string): SuperLinkDeepLink | null;
|
|
951
|
+
interface LinkingLike {
|
|
952
|
+
getInitialURL(): Promise<string | null>;
|
|
953
|
+
addEventListener(type: 'url', handler: (event: {
|
|
954
|
+
url: string;
|
|
955
|
+
}) => void): {
|
|
956
|
+
remove(): void;
|
|
957
|
+
} | void;
|
|
958
|
+
removeEventListener?(type: 'url', handler: (event: {
|
|
959
|
+
url: string;
|
|
960
|
+
}) => void): void;
|
|
961
|
+
}
|
|
962
|
+
/**
|
|
963
|
+
* Wire RN Linking to handle already-installed opens. Processes the cold-start
|
|
964
|
+
* URL (getInitialURL) and subsequent warm opens, calling `onLink` with the
|
|
965
|
+
* parsed payload and reporting `opened` events. Returns an unsubscribe fn.
|
|
966
|
+
*
|
|
967
|
+
* Pass your app's `Linking` module from 'react-native' (kept as a param so this
|
|
968
|
+
* file has no hard dependency on the Linking native module at import time).
|
|
969
|
+
*/
|
|
970
|
+
declare function createSuperLinkListener(Linking: LinkingLike, onLink: DeferredDeepLinkHandler): () => void;
|
|
971
|
+
/**
|
|
972
|
+
* Report a downstream conversion (signup, purchase, ...) back to the redirect
|
|
973
|
+
* engine, attributed to the matched click when available.
|
|
974
|
+
*/
|
|
975
|
+
declare function reportConversion(props?: Record<string, unknown>): Promise<boolean>;
|
|
976
|
+
|
|
977
|
+
/**
|
|
978
|
+
* React Native entry point for SitePong SDK.
|
|
979
|
+
*
|
|
980
|
+
* Installs the RN EnvironmentAdapter first, then re-exports the RN public
|
|
981
|
+
* API (SitePongRNProvider + RN-safe SDK functions). Consumers should use
|
|
982
|
+
* `initRN()` (not `init()`), which does not touch DOM APIs.
|
|
983
|
+
*
|
|
984
|
+
* Because this module installs the env adapter at import time, simply
|
|
985
|
+
* importing `sitepong/react-native` is enough to make shared SDK modules
|
|
986
|
+
* route all environment access through the RN adapter.
|
|
987
|
+
*/
|
|
988
|
+
|
|
989
|
+
/**
|
|
990
|
+
* Advanced: inject a StorageAdapter (e.g. AsyncStorage/MMKV-backed) after app boot.
|
|
991
|
+
* Typically called by SitePongRNProvider.
|
|
992
|
+
*/
|
|
993
|
+
declare function setRNStorage(storage: StorageAdapter | null): void;
|
|
994
|
+
|
|
995
|
+
export { type AsyncStorageLike, type DeferredDeepLinkHandler, type ErrorContext, type GroupTraits, type NavigationRef, type NavigationTrackerOptions, type NetworkInterceptionOptions, RNAutocaptureModule, type RNAutocaptureOptions, type RNDeviceInfo, type RNErrorHandlerOptions, RNPerformanceManager, type RemoteConfig, type ScreenRecordingConfig, type SitePongConfig, type SitePongInitConfig, SitePongRNProvider, type SitePongRNProviderProps, type SuperLinkConfig, type SuperLinkDeepLink, type SuperLinkEventType, type SuperLinkFingerprint, type SuperLinkIdentityMetadata, type SuperLinkMatchType, type SuperLinkPlatform, type TrackProperties, type TrackedDatabaseOptions, type UserTraits, type WatchtowerConfig, WatchtowerProvider, type WatchtowerProviderProps, type WidgetSyncOptions, addBreadcrumb, areFlagsReady, captureError, captureMessage, clearAnonymousId, clearUser, collectDeviceInfo, completeFromScan, createAsyncStorageAdapter, createNavigationTracker, createSuperLinkListener, createTrackedDatabase, endLiveActivity, fetchNativeDeviceSignals, fetchPersistentDeviceId, flush, flushScreenRecording, flushScreenRecordingOnError, getAllFlags, getAnonymousId, getFlag, getMatchedDeepLink, getRemoteConfig, getVariant, getVariantPayload, getWatchtowerSessionId, group, handleUniversalLink, identify$1 as identify, initRN, initSuperLinkRN, isInitialized, isRemoteConfigFeatureEnabled, isScreenRecording, markColdStart, onDeferredDeepLink, onRemoteConfigChange, parseUniversalLink, refreshFlags, registerDeviceToken, registerLiveActivityToken, registerPushToStartToken, registerPushToken, reportConversion, resetAnalytics, setAnonymousId, setContext, setCurrentScreen, setRNStorage, setTags, setUser, setWatchtowerUser, setupNetworkInterception, setupRNErrorHandler, startScreenRecording, startWatchtower, stopScreenRecording, stopWatchtower, stopWidgetSync, subscribeNavigationToWatchtower, identify as superlinkIdentify, syncWidgets, track, triggerWidgetRefresh, updateWidgetData, useAppState, useRNPerformance, useRemoteConfig, useScreenTrack, useSitePongRNContext, waitForFlags };
|