@analyticscli/sdk 0.1.0-preview.7 → 0.1.0-preview.9
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/browser.cjs +190 -8
- package/dist/browser.d.cts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +1 -1
- package/dist/{chunk-O4FIH647.js → chunk-FRXYHOBX.js} +190 -8
- package/dist/index.cjs +190 -8
- package/dist/index.d.cts +76 -1
- package/dist/index.d.ts +76 -1
- package/dist/index.js +1 -1
- package/dist/react-native.cjs +190 -8
- package/dist/react-native.d.cts +1 -1
- package/dist/react-native.d.ts +1 -1
- package/dist/react-native.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -587,6 +587,49 @@ var sanitizeSurveyResponseInput = (input) => {
|
|
|
587
587
|
|
|
588
588
|
// src/analytics-client.ts
|
|
589
589
|
var DEFAULT_CONSENT_STORAGE_KEY = "analyticscli:consent:v1";
|
|
590
|
+
var AUTH_FAILURE_FLUSH_PAUSE_MS = 6e4;
|
|
591
|
+
var resolveDefaultOsNameFromPlatform = (platform) => {
|
|
592
|
+
if (!platform) {
|
|
593
|
+
return void 0;
|
|
594
|
+
}
|
|
595
|
+
if (platform === "ios") {
|
|
596
|
+
return "iOS";
|
|
597
|
+
}
|
|
598
|
+
if (platform === "android") {
|
|
599
|
+
return "Android";
|
|
600
|
+
}
|
|
601
|
+
if (platform === "web") {
|
|
602
|
+
return "Web";
|
|
603
|
+
}
|
|
604
|
+
if (platform === "mac") {
|
|
605
|
+
return "macOS";
|
|
606
|
+
}
|
|
607
|
+
if (platform === "windows") {
|
|
608
|
+
return "Windows";
|
|
609
|
+
}
|
|
610
|
+
return void 0;
|
|
611
|
+
};
|
|
612
|
+
var IngestSendError = class extends Error {
|
|
613
|
+
retryable;
|
|
614
|
+
attempts;
|
|
615
|
+
status;
|
|
616
|
+
errorCode;
|
|
617
|
+
serverMessage;
|
|
618
|
+
requestId;
|
|
619
|
+
constructor(input) {
|
|
620
|
+
super(input.message);
|
|
621
|
+
this.name = "IngestSendError";
|
|
622
|
+
this.retryable = input.retryable;
|
|
623
|
+
this.attempts = input.attempts;
|
|
624
|
+
this.status = input.status;
|
|
625
|
+
this.errorCode = input.errorCode;
|
|
626
|
+
this.serverMessage = input.serverMessage;
|
|
627
|
+
this.requestId = input.requestId;
|
|
628
|
+
if (input.cause !== void 0) {
|
|
629
|
+
this.cause = input.cause;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
};
|
|
590
633
|
var AnalyticsClient = class {
|
|
591
634
|
apiKey;
|
|
592
635
|
hasIngestConfig;
|
|
@@ -595,6 +638,7 @@ var AnalyticsClient = class {
|
|
|
595
638
|
flushIntervalMs;
|
|
596
639
|
maxRetries;
|
|
597
640
|
debug;
|
|
641
|
+
onIngestError;
|
|
598
642
|
platform;
|
|
599
643
|
projectSurface;
|
|
600
644
|
appVersion;
|
|
@@ -627,6 +671,7 @@ var AnalyticsClient = class {
|
|
|
627
671
|
deferredEventsBeforeHydration = [];
|
|
628
672
|
onboardingStepViewStateSessionId = null;
|
|
629
673
|
onboardingStepViewsSeen = /* @__PURE__ */ new Set();
|
|
674
|
+
flushPausedUntilMs = 0;
|
|
630
675
|
constructor(options) {
|
|
631
676
|
const normalizedOptions = this.normalizeOptions(options);
|
|
632
677
|
this.apiKey = this.readRequiredStringOption(normalizedOptions.apiKey);
|
|
@@ -639,11 +684,17 @@ var AnalyticsClient = class {
|
|
|
639
684
|
this.flushIntervalMs = normalizedOptions.flushIntervalMs ?? 5e3;
|
|
640
685
|
this.maxRetries = normalizedOptions.maxRetries ?? 4;
|
|
641
686
|
this.debug = normalizedOptions.debug ?? false;
|
|
687
|
+
this.onIngestError = typeof normalizedOptions.onIngestError === "function" ? normalizedOptions.onIngestError : null;
|
|
642
688
|
this.platform = this.normalizePlatformOption(normalizedOptions.platform) ?? detectDefaultPlatform();
|
|
643
689
|
this.projectSurface = this.normalizeProjectSurfaceOption(normalizedOptions.projectSurface);
|
|
644
690
|
this.appVersion = this.readRequiredStringOption(normalizedOptions.appVersion) || detectDefaultAppVersion();
|
|
645
691
|
this.identityTrackingMode = this.resolveIdentityTrackingModeOption(normalizedOptions);
|
|
646
|
-
|
|
692
|
+
const initialContext = { ...normalizedOptions.context ?? {} };
|
|
693
|
+
const hasExplicitOsName = this.readRequiredStringOption(initialContext.osName).length > 0;
|
|
694
|
+
this.context = {
|
|
695
|
+
...initialContext,
|
|
696
|
+
osName: hasExplicitOsName ? initialContext.osName : resolveDefaultOsNameFromPlatform(this.platform) ?? initialContext.osName
|
|
697
|
+
};
|
|
647
698
|
this.runtimeEnv = detectRuntimeEnv();
|
|
648
699
|
this.persistConsentState = normalizedOptions.persistConsentState ?? false;
|
|
649
700
|
this.consentStorageKey = this.readRequiredStringOption(normalizedOptions.consentStorageKey) || DEFAULT_CONSENT_STORAGE_KEY;
|
|
@@ -676,6 +727,7 @@ var AnalyticsClient = class {
|
|
|
676
727
|
this.writePersistedConsent(this.configuredStorage, this.fullTrackingConsentGranted);
|
|
677
728
|
}
|
|
678
729
|
this.hydrationPromise = this.hydrateIdentityFromStorage();
|
|
730
|
+
this.enqueueInitialSessionStart();
|
|
679
731
|
this.startAutoFlush();
|
|
680
732
|
}
|
|
681
733
|
/**
|
|
@@ -733,6 +785,32 @@ var AnalyticsClient = class {
|
|
|
733
785
|
...context
|
|
734
786
|
};
|
|
735
787
|
}
|
|
788
|
+
enqueueInitialSessionStart() {
|
|
789
|
+
if (!this.consentGranted) {
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
if (this.shouldDeferEventsUntilHydrated()) {
|
|
793
|
+
this.deferEventUntilHydrated(() => {
|
|
794
|
+
this.enqueueInitialSessionStart();
|
|
795
|
+
});
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
const sessionId = this.getSessionId();
|
|
799
|
+
this.enqueue({
|
|
800
|
+
eventId: randomId(),
|
|
801
|
+
eventName: "session_start",
|
|
802
|
+
ts: nowIso(),
|
|
803
|
+
sessionId,
|
|
804
|
+
anonId: this.anonId,
|
|
805
|
+
userId: this.getEventUserId(),
|
|
806
|
+
properties: this.withRuntimeMetadata({ source: "sdk_mount" }, sessionId),
|
|
807
|
+
platform: this.platform,
|
|
808
|
+
projectSurface: this.projectSurface,
|
|
809
|
+
appVersion: this.appVersion,
|
|
810
|
+
...this.withEventContext(),
|
|
811
|
+
type: "track"
|
|
812
|
+
});
|
|
813
|
+
}
|
|
736
814
|
/**
|
|
737
815
|
* Associates following events with a known user id.
|
|
738
816
|
* Anonymous history remains linked by anonId/sessionId.
|
|
@@ -1102,6 +1180,9 @@ var AnalyticsClient = class {
|
|
|
1102
1180
|
if (this.queue.length === 0 || this.isFlushing || !this.consentGranted) {
|
|
1103
1181
|
return;
|
|
1104
1182
|
}
|
|
1183
|
+
if (Date.now() < this.flushPausedUntilMs) {
|
|
1184
|
+
return;
|
|
1185
|
+
}
|
|
1105
1186
|
this.isFlushing = true;
|
|
1106
1187
|
const batch = this.queue.splice(0, this.batchSize);
|
|
1107
1188
|
const payload = {
|
|
@@ -1116,9 +1197,20 @@ var AnalyticsClient = class {
|
|
|
1116
1197
|
}
|
|
1117
1198
|
try {
|
|
1118
1199
|
await this.sendWithRetry(payload);
|
|
1200
|
+
this.flushPausedUntilMs = 0;
|
|
1119
1201
|
} catch (error) {
|
|
1120
|
-
this.log("Send failed permanently, requeueing batch", error);
|
|
1121
1202
|
this.queue = [...batch, ...this.queue];
|
|
1203
|
+
const ingestError = this.toIngestSendError(error);
|
|
1204
|
+
const diagnostics = this.createIngestDiagnostics(ingestError, batch.length, this.queue.length);
|
|
1205
|
+
if (ingestError.status === 401 || ingestError.status === 403) {
|
|
1206
|
+
this.flushPausedUntilMs = Date.now() + AUTH_FAILURE_FLUSH_PAUSE_MS;
|
|
1207
|
+
this.log("Pausing ingest flush after auth failure", {
|
|
1208
|
+
status: ingestError.status,
|
|
1209
|
+
retryAfterMs: AUTH_FAILURE_FLUSH_PAUSE_MS
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
this.log("Send failed permanently, requeueing batch", diagnostics);
|
|
1213
|
+
this.reportIngestError(diagnostics);
|
|
1122
1214
|
} finally {
|
|
1123
1215
|
this.isFlushing = false;
|
|
1124
1216
|
}
|
|
@@ -1147,9 +1239,8 @@ var AnalyticsClient = class {
|
|
|
1147
1239
|
});
|
|
1148
1240
|
}
|
|
1149
1241
|
async sendWithRetry(payload) {
|
|
1150
|
-
let attempt = 0;
|
|
1151
1242
|
let delay = 250;
|
|
1152
|
-
|
|
1243
|
+
for (let attempt = 1; attempt <= this.maxRetries + 1; attempt += 1) {
|
|
1153
1244
|
try {
|
|
1154
1245
|
const response = await fetch(`${this.endpoint}/v1/collect`, {
|
|
1155
1246
|
method: "POST",
|
|
@@ -1161,19 +1252,110 @@ var AnalyticsClient = class {
|
|
|
1161
1252
|
keepalive: true
|
|
1162
1253
|
});
|
|
1163
1254
|
if (!response.ok) {
|
|
1164
|
-
throw
|
|
1255
|
+
throw await this.createHttpIngestSendError(response, attempt);
|
|
1165
1256
|
}
|
|
1166
1257
|
return;
|
|
1167
1258
|
} catch (error) {
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1259
|
+
const normalized = this.toIngestSendError(error, attempt);
|
|
1260
|
+
const finalAttempt = attempt >= this.maxRetries + 1;
|
|
1261
|
+
this.log("Ingest attempt failed", {
|
|
1262
|
+
attempt: normalized.attempts,
|
|
1263
|
+
maxRetries: this.maxRetries,
|
|
1264
|
+
retryable: normalized.retryable,
|
|
1265
|
+
status: normalized.status,
|
|
1266
|
+
errorCode: normalized.errorCode,
|
|
1267
|
+
requestId: normalized.requestId,
|
|
1268
|
+
nextRetryInMs: !finalAttempt && normalized.retryable ? delay : null
|
|
1269
|
+
});
|
|
1270
|
+
if (finalAttempt || !normalized.retryable) {
|
|
1271
|
+
throw normalized;
|
|
1171
1272
|
}
|
|
1172
1273
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1173
1274
|
delay *= 2;
|
|
1174
1275
|
}
|
|
1175
1276
|
}
|
|
1176
1277
|
}
|
|
1278
|
+
async createHttpIngestSendError(response, attempts) {
|
|
1279
|
+
const requestId = response.headers.get("x-request-id") ?? response.headers.get("cf-ray") ?? void 0;
|
|
1280
|
+
let errorCode;
|
|
1281
|
+
let serverMessage;
|
|
1282
|
+
try {
|
|
1283
|
+
const parsed = await response.json();
|
|
1284
|
+
const errorBody = parsed && typeof parsed === "object" && parsed.error && typeof parsed.error === "object" ? parsed.error : void 0;
|
|
1285
|
+
if (typeof errorBody?.code === "string") {
|
|
1286
|
+
errorCode = errorBody.code;
|
|
1287
|
+
}
|
|
1288
|
+
if (typeof errorBody?.message === "string") {
|
|
1289
|
+
serverMessage = errorBody.message;
|
|
1290
|
+
}
|
|
1291
|
+
} catch {
|
|
1292
|
+
}
|
|
1293
|
+
const retryable = this.shouldRetryHttpStatus(response.status);
|
|
1294
|
+
const statusSuffix = errorCode ? ` ${errorCode}` : "";
|
|
1295
|
+
const message = `ingest status=${response.status}${statusSuffix}`;
|
|
1296
|
+
return new IngestSendError({
|
|
1297
|
+
message,
|
|
1298
|
+
retryable,
|
|
1299
|
+
attempts,
|
|
1300
|
+
status: response.status,
|
|
1301
|
+
errorCode,
|
|
1302
|
+
serverMessage,
|
|
1303
|
+
requestId
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
shouldRetryHttpStatus(status) {
|
|
1307
|
+
return status === 408 || status === 425 || status === 429 || status >= 500;
|
|
1308
|
+
}
|
|
1309
|
+
toIngestSendError(error, attempts) {
|
|
1310
|
+
if (error instanceof IngestSendError) {
|
|
1311
|
+
const resolvedAttempts = attempts ?? error.attempts;
|
|
1312
|
+
return new IngestSendError({
|
|
1313
|
+
message: error.message,
|
|
1314
|
+
retryable: error.retryable,
|
|
1315
|
+
attempts: resolvedAttempts,
|
|
1316
|
+
status: error.status,
|
|
1317
|
+
errorCode: error.errorCode,
|
|
1318
|
+
serverMessage: error.serverMessage,
|
|
1319
|
+
requestId: error.requestId,
|
|
1320
|
+
cause: error.cause
|
|
1321
|
+
});
|
|
1322
|
+
}
|
|
1323
|
+
const fallbackMessage = error instanceof Error ? error.message : "ingest request failed";
|
|
1324
|
+
return new IngestSendError({
|
|
1325
|
+
message: fallbackMessage,
|
|
1326
|
+
retryable: true,
|
|
1327
|
+
attempts: attempts ?? 1,
|
|
1328
|
+
cause: error
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
createIngestDiagnostics(error, batchSize, queueSize) {
|
|
1332
|
+
return {
|
|
1333
|
+
name: "AnalyticsIngestError",
|
|
1334
|
+
message: error.message,
|
|
1335
|
+
endpoint: this.endpoint,
|
|
1336
|
+
path: "/v1/collect",
|
|
1337
|
+
status: error.status,
|
|
1338
|
+
errorCode: error.errorCode,
|
|
1339
|
+
serverMessage: error.serverMessage,
|
|
1340
|
+
requestId: error.requestId,
|
|
1341
|
+
retryable: error.retryable,
|
|
1342
|
+
attempts: error.attempts,
|
|
1343
|
+
maxRetries: this.maxRetries,
|
|
1344
|
+
batchSize,
|
|
1345
|
+
queueSize,
|
|
1346
|
+
timestamp: nowIso()
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1349
|
+
reportIngestError(error) {
|
|
1350
|
+
if (!this.onIngestError) {
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1353
|
+
try {
|
|
1354
|
+
this.onIngestError(error);
|
|
1355
|
+
} catch (callbackError) {
|
|
1356
|
+
this.log("onIngestError callback threw", callbackError);
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1177
1359
|
parsePersistedConsent(raw) {
|
|
1178
1360
|
if (raw === "granted") {
|
|
1179
1361
|
return true;
|
package/dist/index.d.cts
CHANGED
|
@@ -130,6 +130,65 @@ type PaywallTracker = {
|
|
|
130
130
|
};
|
|
131
131
|
type AnalyticsConsentState = 'granted' | 'denied' | 'unknown';
|
|
132
132
|
type IdentityTrackingMode = 'strict' | 'consent_gated' | 'always_on';
|
|
133
|
+
type AnalyticsIngestError = {
|
|
134
|
+
/**
|
|
135
|
+
* Stable error name for host-app monitoring.
|
|
136
|
+
*/
|
|
137
|
+
name: 'AnalyticsIngestError';
|
|
138
|
+
/**
|
|
139
|
+
* Human-readable summary of the ingest failure.
|
|
140
|
+
*/
|
|
141
|
+
message: string;
|
|
142
|
+
/**
|
|
143
|
+
* Collector endpoint base URL configured in the SDK client.
|
|
144
|
+
*/
|
|
145
|
+
endpoint: string;
|
|
146
|
+
/**
|
|
147
|
+
* Collector path that failed.
|
|
148
|
+
*/
|
|
149
|
+
path: '/v1/collect';
|
|
150
|
+
/**
|
|
151
|
+
* HTTP status when available.
|
|
152
|
+
*/
|
|
153
|
+
status?: number;
|
|
154
|
+
/**
|
|
155
|
+
* Structured server error code when available.
|
|
156
|
+
*/
|
|
157
|
+
errorCode?: string;
|
|
158
|
+
/**
|
|
159
|
+
* Structured server message when available.
|
|
160
|
+
*/
|
|
161
|
+
serverMessage?: string;
|
|
162
|
+
/**
|
|
163
|
+
* Request correlation id when exposed by the collector response.
|
|
164
|
+
*/
|
|
165
|
+
requestId?: string;
|
|
166
|
+
/**
|
|
167
|
+
* Whether retrying can help (`true` for network/5xx/429 class failures).
|
|
168
|
+
*/
|
|
169
|
+
retryable: boolean;
|
|
170
|
+
/**
|
|
171
|
+
* Number of attempts that were made for this batch.
|
|
172
|
+
*/
|
|
173
|
+
attempts: number;
|
|
174
|
+
/**
|
|
175
|
+
* SDK max retries configured on the client.
|
|
176
|
+
*/
|
|
177
|
+
maxRetries: number;
|
|
178
|
+
/**
|
|
179
|
+
* Number of events in the failed batch.
|
|
180
|
+
*/
|
|
181
|
+
batchSize: number;
|
|
182
|
+
/**
|
|
183
|
+
* Current queue size after requeue.
|
|
184
|
+
*/
|
|
185
|
+
queueSize: number;
|
|
186
|
+
/**
|
|
187
|
+
* ISO timestamp when the failure was surfaced to host-app callbacks.
|
|
188
|
+
*/
|
|
189
|
+
timestamp: string;
|
|
190
|
+
};
|
|
191
|
+
type AnalyticsIngestErrorHandler = (error: AnalyticsIngestError) => void;
|
|
133
192
|
type SetConsentOptions = {
|
|
134
193
|
/**
|
|
135
194
|
* Whether consent state should be persisted to storage when enabled.
|
|
@@ -158,6 +217,14 @@ type AnalyticsClientOptions = {
|
|
|
158
217
|
* `debug: __DEV__`
|
|
159
218
|
*/
|
|
160
219
|
debug?: boolean | null;
|
|
220
|
+
/**
|
|
221
|
+
* Optional host-app hook for ingest delivery failures.
|
|
222
|
+
* Use this to forward operational diagnostics to your own monitoring stack.
|
|
223
|
+
*
|
|
224
|
+
* GDPR recommendation:
|
|
225
|
+
* forward this structured metadata only and avoid attaching event payloads or raw identifiers.
|
|
226
|
+
*/
|
|
227
|
+
onIngestError?: AnalyticsIngestErrorHandler | null;
|
|
161
228
|
/**
|
|
162
229
|
* Optional platform hint.
|
|
163
230
|
* React Native/Expo: passing `Platform.OS` directly is supported.
|
|
@@ -246,6 +313,7 @@ declare class AnalyticsClient {
|
|
|
246
313
|
private readonly flushIntervalMs;
|
|
247
314
|
private readonly maxRetries;
|
|
248
315
|
private readonly debug;
|
|
316
|
+
private readonly onIngestError;
|
|
249
317
|
private readonly platform;
|
|
250
318
|
private readonly projectSurface;
|
|
251
319
|
private readonly appVersion;
|
|
@@ -278,6 +346,7 @@ declare class AnalyticsClient {
|
|
|
278
346
|
private deferredEventsBeforeHydration;
|
|
279
347
|
private onboardingStepViewStateSessionId;
|
|
280
348
|
private onboardingStepViewsSeen;
|
|
349
|
+
private flushPausedUntilMs;
|
|
281
350
|
constructor(options: AnalyticsClientOptions);
|
|
282
351
|
/**
|
|
283
352
|
* Resolves once client initialization work completes.
|
|
@@ -296,6 +365,7 @@ declare class AnalyticsClient {
|
|
|
296
365
|
* Sets or updates shared event context fields (useful for mobile device/app metadata).
|
|
297
366
|
*/
|
|
298
367
|
setContext(context: EventContext): void;
|
|
368
|
+
private enqueueInitialSessionStart;
|
|
299
369
|
/**
|
|
300
370
|
* Associates following events with a known user id.
|
|
301
371
|
* Anonymous history remains linked by anonId/sessionId.
|
|
@@ -373,6 +443,11 @@ declare class AnalyticsClient {
|
|
|
373
443
|
private enqueue;
|
|
374
444
|
private scheduleFlush;
|
|
375
445
|
private sendWithRetry;
|
|
446
|
+
private createHttpIngestSendError;
|
|
447
|
+
private shouldRetryHttpStatus;
|
|
448
|
+
private toIngestSendError;
|
|
449
|
+
private createIngestDiagnostics;
|
|
450
|
+
private reportIngestError;
|
|
376
451
|
private parsePersistedConsent;
|
|
377
452
|
private readPersistedConsentSync;
|
|
378
453
|
private readPersistedConsentAsync;
|
|
@@ -489,4 +564,4 @@ declare const initConsentFirst: (input?: InitInput) => AnalyticsClient;
|
|
|
489
564
|
declare const initAsync: (input?: InitInput) => Promise<AnalyticsClient>;
|
|
490
565
|
declare const initConsentFirstAsync: (input?: InitInput) => Promise<AnalyticsClient>;
|
|
491
566
|
|
|
492
|
-
export { AnalyticsClient, type AnalyticsClientOptions, type AnalyticsConsentState, type AnalyticsContext, type AnalyticsContextConsentControls, type AnalyticsContextUserControls, type AnalyticsStorageAdapter, type CreateAnalyticsContextOptions, type EventContext, type EventProperties, type IdentityTrackingMode, type InitInput, type InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, type OnboardingEventName, type OnboardingEventProperties, type OnboardingStepTracker, type OnboardingSurveyAnswerType, type OnboardingSurveyEventName, type OnboardingSurveyResponseInput, type OnboardingTracker, type OnboardingTrackerDefaults, type OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, type PaywallEventName, type PaywallEventProperties, type PaywallJourneyEventName, type PaywallTracker, type PaywallTrackerDefaults, type PaywallTrackerProperties, type PurchaseEventName, type SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync };
|
|
567
|
+
export { AnalyticsClient, type AnalyticsClientOptions, type AnalyticsConsentState, type AnalyticsContext, type AnalyticsContextConsentControls, type AnalyticsContextUserControls, type AnalyticsIngestError, type AnalyticsIngestErrorHandler, type AnalyticsStorageAdapter, type CreateAnalyticsContextOptions, type EventContext, type EventProperties, type IdentityTrackingMode, type InitInput, type InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, type OnboardingEventName, type OnboardingEventProperties, type OnboardingStepTracker, type OnboardingSurveyAnswerType, type OnboardingSurveyEventName, type OnboardingSurveyResponseInput, type OnboardingTracker, type OnboardingTrackerDefaults, type OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, type PaywallEventName, type PaywallEventProperties, type PaywallJourneyEventName, type PaywallTracker, type PaywallTrackerDefaults, type PaywallTrackerProperties, type PurchaseEventName, type SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync };
|
package/dist/index.d.ts
CHANGED
|
@@ -130,6 +130,65 @@ type PaywallTracker = {
|
|
|
130
130
|
};
|
|
131
131
|
type AnalyticsConsentState = 'granted' | 'denied' | 'unknown';
|
|
132
132
|
type IdentityTrackingMode = 'strict' | 'consent_gated' | 'always_on';
|
|
133
|
+
type AnalyticsIngestError = {
|
|
134
|
+
/**
|
|
135
|
+
* Stable error name for host-app monitoring.
|
|
136
|
+
*/
|
|
137
|
+
name: 'AnalyticsIngestError';
|
|
138
|
+
/**
|
|
139
|
+
* Human-readable summary of the ingest failure.
|
|
140
|
+
*/
|
|
141
|
+
message: string;
|
|
142
|
+
/**
|
|
143
|
+
* Collector endpoint base URL configured in the SDK client.
|
|
144
|
+
*/
|
|
145
|
+
endpoint: string;
|
|
146
|
+
/**
|
|
147
|
+
* Collector path that failed.
|
|
148
|
+
*/
|
|
149
|
+
path: '/v1/collect';
|
|
150
|
+
/**
|
|
151
|
+
* HTTP status when available.
|
|
152
|
+
*/
|
|
153
|
+
status?: number;
|
|
154
|
+
/**
|
|
155
|
+
* Structured server error code when available.
|
|
156
|
+
*/
|
|
157
|
+
errorCode?: string;
|
|
158
|
+
/**
|
|
159
|
+
* Structured server message when available.
|
|
160
|
+
*/
|
|
161
|
+
serverMessage?: string;
|
|
162
|
+
/**
|
|
163
|
+
* Request correlation id when exposed by the collector response.
|
|
164
|
+
*/
|
|
165
|
+
requestId?: string;
|
|
166
|
+
/**
|
|
167
|
+
* Whether retrying can help (`true` for network/5xx/429 class failures).
|
|
168
|
+
*/
|
|
169
|
+
retryable: boolean;
|
|
170
|
+
/**
|
|
171
|
+
* Number of attempts that were made for this batch.
|
|
172
|
+
*/
|
|
173
|
+
attempts: number;
|
|
174
|
+
/**
|
|
175
|
+
* SDK max retries configured on the client.
|
|
176
|
+
*/
|
|
177
|
+
maxRetries: number;
|
|
178
|
+
/**
|
|
179
|
+
* Number of events in the failed batch.
|
|
180
|
+
*/
|
|
181
|
+
batchSize: number;
|
|
182
|
+
/**
|
|
183
|
+
* Current queue size after requeue.
|
|
184
|
+
*/
|
|
185
|
+
queueSize: number;
|
|
186
|
+
/**
|
|
187
|
+
* ISO timestamp when the failure was surfaced to host-app callbacks.
|
|
188
|
+
*/
|
|
189
|
+
timestamp: string;
|
|
190
|
+
};
|
|
191
|
+
type AnalyticsIngestErrorHandler = (error: AnalyticsIngestError) => void;
|
|
133
192
|
type SetConsentOptions = {
|
|
134
193
|
/**
|
|
135
194
|
* Whether consent state should be persisted to storage when enabled.
|
|
@@ -158,6 +217,14 @@ type AnalyticsClientOptions = {
|
|
|
158
217
|
* `debug: __DEV__`
|
|
159
218
|
*/
|
|
160
219
|
debug?: boolean | null;
|
|
220
|
+
/**
|
|
221
|
+
* Optional host-app hook for ingest delivery failures.
|
|
222
|
+
* Use this to forward operational diagnostics to your own monitoring stack.
|
|
223
|
+
*
|
|
224
|
+
* GDPR recommendation:
|
|
225
|
+
* forward this structured metadata only and avoid attaching event payloads or raw identifiers.
|
|
226
|
+
*/
|
|
227
|
+
onIngestError?: AnalyticsIngestErrorHandler | null;
|
|
161
228
|
/**
|
|
162
229
|
* Optional platform hint.
|
|
163
230
|
* React Native/Expo: passing `Platform.OS` directly is supported.
|
|
@@ -246,6 +313,7 @@ declare class AnalyticsClient {
|
|
|
246
313
|
private readonly flushIntervalMs;
|
|
247
314
|
private readonly maxRetries;
|
|
248
315
|
private readonly debug;
|
|
316
|
+
private readonly onIngestError;
|
|
249
317
|
private readonly platform;
|
|
250
318
|
private readonly projectSurface;
|
|
251
319
|
private readonly appVersion;
|
|
@@ -278,6 +346,7 @@ declare class AnalyticsClient {
|
|
|
278
346
|
private deferredEventsBeforeHydration;
|
|
279
347
|
private onboardingStepViewStateSessionId;
|
|
280
348
|
private onboardingStepViewsSeen;
|
|
349
|
+
private flushPausedUntilMs;
|
|
281
350
|
constructor(options: AnalyticsClientOptions);
|
|
282
351
|
/**
|
|
283
352
|
* Resolves once client initialization work completes.
|
|
@@ -296,6 +365,7 @@ declare class AnalyticsClient {
|
|
|
296
365
|
* Sets or updates shared event context fields (useful for mobile device/app metadata).
|
|
297
366
|
*/
|
|
298
367
|
setContext(context: EventContext): void;
|
|
368
|
+
private enqueueInitialSessionStart;
|
|
299
369
|
/**
|
|
300
370
|
* Associates following events with a known user id.
|
|
301
371
|
* Anonymous history remains linked by anonId/sessionId.
|
|
@@ -373,6 +443,11 @@ declare class AnalyticsClient {
|
|
|
373
443
|
private enqueue;
|
|
374
444
|
private scheduleFlush;
|
|
375
445
|
private sendWithRetry;
|
|
446
|
+
private createHttpIngestSendError;
|
|
447
|
+
private shouldRetryHttpStatus;
|
|
448
|
+
private toIngestSendError;
|
|
449
|
+
private createIngestDiagnostics;
|
|
450
|
+
private reportIngestError;
|
|
376
451
|
private parsePersistedConsent;
|
|
377
452
|
private readPersistedConsentSync;
|
|
378
453
|
private readPersistedConsentAsync;
|
|
@@ -489,4 +564,4 @@ declare const initConsentFirst: (input?: InitInput) => AnalyticsClient;
|
|
|
489
564
|
declare const initAsync: (input?: InitInput) => Promise<AnalyticsClient>;
|
|
490
565
|
declare const initConsentFirstAsync: (input?: InitInput) => Promise<AnalyticsClient>;
|
|
491
566
|
|
|
492
|
-
export { AnalyticsClient, type AnalyticsClientOptions, type AnalyticsConsentState, type AnalyticsContext, type AnalyticsContextConsentControls, type AnalyticsContextUserControls, type AnalyticsStorageAdapter, type CreateAnalyticsContextOptions, type EventContext, type EventProperties, type IdentityTrackingMode, type InitInput, type InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, type OnboardingEventName, type OnboardingEventProperties, type OnboardingStepTracker, type OnboardingSurveyAnswerType, type OnboardingSurveyEventName, type OnboardingSurveyResponseInput, type OnboardingTracker, type OnboardingTrackerDefaults, type OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, type PaywallEventName, type PaywallEventProperties, type PaywallJourneyEventName, type PaywallTracker, type PaywallTrackerDefaults, type PaywallTrackerProperties, type PurchaseEventName, type SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync };
|
|
567
|
+
export { AnalyticsClient, type AnalyticsClientOptions, type AnalyticsConsentState, type AnalyticsContext, type AnalyticsContextConsentControls, type AnalyticsContextUserControls, type AnalyticsIngestError, type AnalyticsIngestErrorHandler, type AnalyticsStorageAdapter, type CreateAnalyticsContextOptions, type EventContext, type EventProperties, type IdentityTrackingMode, type InitInput, type InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, type OnboardingEventName, type OnboardingEventProperties, type OnboardingStepTracker, type OnboardingSurveyAnswerType, type OnboardingSurveyEventName, type OnboardingSurveyResponseInput, type OnboardingTracker, type OnboardingTrackerDefaults, type OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, type PaywallEventName, type PaywallEventProperties, type PaywallJourneyEventName, type PaywallTracker, type PaywallTrackerDefaults, type PaywallTrackerProperties, type PurchaseEventName, type SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync };
|