@analyticscli/sdk 0.1.0-preview.4 → 0.1.0-preview.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +181 -63
- package/dist/browser.cjs +321 -133
- package/dist/browser.d.cts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +7 -13
- package/dist/{chunk-UILQQPVJ.js → chunk-RGEYDN6A.js} +318 -127
- package/dist/index.cjs +321 -133
- package/dist/index.d.cts +182 -92
- package/dist/index.d.ts +182 -92
- package/dist/index.js +7 -13
- package/dist/react-native.cjs +321 -133
- package/dist/react-native.d.cts +1 -1
- package/dist/react-native.d.ts +1 -1
- package/dist/react-native.js +7 -13
- package/package.json +1 -1
- package/dist/chunk-CY4KHPLT.js +0 -1455
- package/dist/chunk-NC6ANZ4H.js +0 -1455
- package/dist/chunk-W4RJPJLF.js +0 -1426
- package/dist/chunk-ZIOGPQNP.js +0 -1478
|
@@ -93,6 +93,9 @@ var validateEvent = (event, index) => {
|
|
|
93
93
|
if (!isOptionalStringMax(event.platform, 64)) {
|
|
94
94
|
return { success: false, reason: `events[${index}].platform is invalid` };
|
|
95
95
|
}
|
|
96
|
+
if (!isOptionalStringMax(event.projectSurface, 64)) {
|
|
97
|
+
return { success: false, reason: `events[${index}].projectSurface is invalid` };
|
|
98
|
+
}
|
|
96
99
|
if (!isOptionalStringMax(event.appVersion, 64)) {
|
|
97
100
|
return { success: false, reason: `events[${index}].appVersion is invalid` };
|
|
98
101
|
}
|
|
@@ -521,6 +524,7 @@ var sanitizeSurveyResponseInput = (input) => {
|
|
|
521
524
|
};
|
|
522
525
|
|
|
523
526
|
// src/analytics-client.ts
|
|
527
|
+
var DEFAULT_CONSENT_STORAGE_KEY = "analyticscli:consent:v1";
|
|
524
528
|
var AnalyticsClient = class {
|
|
525
529
|
apiKey;
|
|
526
530
|
hasIngestConfig;
|
|
@@ -530,10 +534,17 @@ var AnalyticsClient = class {
|
|
|
530
534
|
maxRetries;
|
|
531
535
|
debug;
|
|
532
536
|
platform;
|
|
537
|
+
projectSurface;
|
|
533
538
|
appVersion;
|
|
539
|
+
identityTrackingMode;
|
|
534
540
|
context;
|
|
541
|
+
configuredStorage;
|
|
535
542
|
storage;
|
|
536
543
|
storageReadsAreAsync;
|
|
544
|
+
persistConsentState;
|
|
545
|
+
consentStorageKey;
|
|
546
|
+
hasExplicitInitialConsent;
|
|
547
|
+
hasExplicitInitialFullTrackingConsent;
|
|
537
548
|
sessionTimeoutMs;
|
|
538
549
|
dedupeOnboardingStepViewsPerSession;
|
|
539
550
|
runtimeEnv;
|
|
@@ -544,6 +555,7 @@ var AnalyticsClient = class {
|
|
|
544
555
|
flushTimer = null;
|
|
545
556
|
isFlushing = false;
|
|
546
557
|
consentGranted = true;
|
|
558
|
+
fullTrackingConsentGranted = false;
|
|
547
559
|
userId = null;
|
|
548
560
|
anonId;
|
|
549
561
|
sessionId;
|
|
@@ -566,34 +578,46 @@ var AnalyticsClient = class {
|
|
|
566
578
|
this.maxRetries = normalizedOptions.maxRetries ?? 4;
|
|
567
579
|
this.debug = normalizedOptions.debug ?? false;
|
|
568
580
|
this.platform = this.normalizePlatformOption(normalizedOptions.platform) ?? detectDefaultPlatform();
|
|
581
|
+
this.projectSurface = this.normalizeProjectSurfaceOption(normalizedOptions.projectSurface);
|
|
569
582
|
this.appVersion = this.readRequiredStringOption(normalizedOptions.appVersion) || detectDefaultAppVersion();
|
|
583
|
+
this.identityTrackingMode = this.resolveIdentityTrackingModeOption(normalizedOptions);
|
|
570
584
|
this.context = { ...normalizedOptions.context ?? {} };
|
|
571
585
|
this.runtimeEnv = detectRuntimeEnv();
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
normalizedOptions.cookieMaxAgeSeconds ?? DEFAULT_COOKIE_MAX_AGE_SECONDS
|
|
577
|
-
);
|
|
578
|
-
const browserStorage = resolveBrowserStorageAdapter();
|
|
579
|
-
this.storage = normalizedOptions.storage ?? (cookieStorage && browserStorage ? combineStorageAdapters(cookieStorage, browserStorage) : cookieStorage ?? browserStorage);
|
|
580
|
-
this.storageReadsAreAsync = this.detectAsyncStorageReads();
|
|
586
|
+
this.persistConsentState = normalizedOptions.persistConsentState ?? false;
|
|
587
|
+
this.consentStorageKey = this.readRequiredStringOption(normalizedOptions.consentStorageKey) || DEFAULT_CONSENT_STORAGE_KEY;
|
|
588
|
+
this.hasExplicitInitialConsent = typeof normalizedOptions.initialConsentGranted === "boolean";
|
|
589
|
+
this.hasExplicitInitialFullTrackingConsent = typeof normalizedOptions.initialFullTrackingConsentGranted === "boolean";
|
|
581
590
|
this.sessionTimeoutMs = normalizedOptions.sessionTimeoutMs ?? DEFAULT_SESSION_TIMEOUT_MS;
|
|
582
|
-
this.dedupeOnboardingStepViewsPerSession = normalizedOptions.dedupeOnboardingStepViewsPerSession ??
|
|
583
|
-
|
|
584
|
-
const
|
|
591
|
+
this.dedupeOnboardingStepViewsPerSession = normalizedOptions.dedupeOnboardingStepViewsPerSession ?? true;
|
|
592
|
+
this.configuredStorage = this.resolveConfiguredStorage(normalizedOptions);
|
|
593
|
+
const persistedFullTrackingConsent = this.readPersistedConsentSync(this.configuredStorage);
|
|
594
|
+
const configuredFullTrackingConsent = normalizedOptions.initialFullTrackingConsentGranted;
|
|
595
|
+
const initialFullTrackingConsentGranted = typeof configuredFullTrackingConsent === "boolean" ? configuredFullTrackingConsent : persistedFullTrackingConsent ?? false;
|
|
596
|
+
this.fullTrackingConsentGranted = this.identityTrackingMode === "always_on" || initialFullTrackingConsentGranted;
|
|
597
|
+
this.storage = this.isFullTrackingActive() ? this.configuredStorage : null;
|
|
598
|
+
this.storageReadsAreAsync = this.detectAsyncStorageReads();
|
|
599
|
+
const providedAnonId = this.isFullTrackingActive() ? this.readRequiredStringOption(normalizedOptions.anonId) : "";
|
|
600
|
+
const providedSessionId = this.isFullTrackingActive() ? this.readRequiredStringOption(normalizedOptions.sessionId) : "";
|
|
585
601
|
this.hasExplicitAnonId = Boolean(providedAnonId);
|
|
586
602
|
this.hasExplicitSessionId = Boolean(providedSessionId);
|
|
587
603
|
this.anonId = providedAnonId || this.ensureDeviceId();
|
|
588
604
|
this.sessionId = providedSessionId || this.ensureSessionId();
|
|
589
605
|
this.sessionEventSeq = this.readSessionEventSeq(this.sessionId);
|
|
590
|
-
|
|
606
|
+
const persistedConsent = this.readPersistedConsentSync(this.storage);
|
|
607
|
+
const configuredConsent = normalizedOptions.initialConsentGranted;
|
|
608
|
+
const initialConsentGranted = typeof configuredConsent === "boolean" ? configuredConsent : persistedConsent ?? this.hasIngestConfig;
|
|
609
|
+
this.consentGranted = this.hasIngestConfig && initialConsentGranted;
|
|
610
|
+
if (this.hasExplicitInitialConsent && this.persistConsentState) {
|
|
611
|
+
this.writePersistedConsent(this.storage, this.consentGranted);
|
|
612
|
+
}
|
|
613
|
+
if (this.hasExplicitInitialFullTrackingConsent && this.persistConsentState) {
|
|
614
|
+
this.writePersistedConsent(this.configuredStorage, this.fullTrackingConsentGranted);
|
|
615
|
+
}
|
|
591
616
|
this.hydrationPromise = this.hydrateIdentityFromStorage();
|
|
592
617
|
this.startAutoFlush();
|
|
593
618
|
}
|
|
594
619
|
/**
|
|
595
|
-
* Resolves once
|
|
596
|
-
* Useful in React Native when using async persistence (for example AsyncStorage).
|
|
620
|
+
* Resolves once client initialization work completes.
|
|
597
621
|
*/
|
|
598
622
|
async ready() {
|
|
599
623
|
await this.hydrationPromise;
|
|
@@ -602,22 +626,41 @@ var AnalyticsClient = class {
|
|
|
602
626
|
* Enables or disables event collection.
|
|
603
627
|
* When disabled, queued events are dropped immediately.
|
|
604
628
|
*/
|
|
605
|
-
setConsent(granted) {
|
|
629
|
+
setConsent(granted, options = {}) {
|
|
606
630
|
if (granted && !this.hasIngestConfig) {
|
|
607
631
|
this.log("Ignoring consent opt-in because `apiKey` is missing");
|
|
608
632
|
return;
|
|
609
633
|
}
|
|
610
634
|
this.consentGranted = granted;
|
|
635
|
+
if ((options.persist ?? true) && this.persistConsentState) {
|
|
636
|
+
this.writePersistedConsent(this.storage, granted);
|
|
637
|
+
}
|
|
638
|
+
if (this.identityTrackingMode === "consent_gated") {
|
|
639
|
+
this.setFullTrackingConsent(granted, options);
|
|
640
|
+
}
|
|
611
641
|
if (!granted) {
|
|
612
642
|
this.queue = [];
|
|
613
643
|
this.deferredEventsBeforeHydration = [];
|
|
614
644
|
}
|
|
615
645
|
}
|
|
616
|
-
optIn() {
|
|
617
|
-
this.setConsent(true);
|
|
646
|
+
optIn(options) {
|
|
647
|
+
this.setConsent(true, options);
|
|
648
|
+
}
|
|
649
|
+
optOut(options) {
|
|
650
|
+
this.setConsent(false, options);
|
|
618
651
|
}
|
|
619
|
-
|
|
620
|
-
this.
|
|
652
|
+
getConsent() {
|
|
653
|
+
return this.consentGranted;
|
|
654
|
+
}
|
|
655
|
+
getConsentState() {
|
|
656
|
+
const persisted = this.readPersistedConsentSync(this.storage);
|
|
657
|
+
if (persisted === true) {
|
|
658
|
+
return "granted";
|
|
659
|
+
}
|
|
660
|
+
if (persisted === false) {
|
|
661
|
+
return "denied";
|
|
662
|
+
}
|
|
663
|
+
return this.consentGranted ? "granted" : "unknown";
|
|
621
664
|
}
|
|
622
665
|
/**
|
|
623
666
|
* Sets or updates shared event context fields (useful for mobile device/app metadata).
|
|
@@ -633,22 +676,25 @@ var AnalyticsClient = class {
|
|
|
633
676
|
* Anonymous history remains linked by anonId/sessionId.
|
|
634
677
|
*/
|
|
635
678
|
identify(userId, traits) {
|
|
636
|
-
if (!this.consentGranted) {
|
|
637
|
-
return;
|
|
638
|
-
}
|
|
639
679
|
const normalizedUserId = this.readRequiredStringOption(userId);
|
|
640
680
|
if (!normalizedUserId) {
|
|
641
|
-
this.log("Dropping identify call without required `userId`");
|
|
642
681
|
return;
|
|
643
682
|
}
|
|
683
|
+
if (!this.isFullTrackingActive()) {
|
|
684
|
+
this.log("Ignoring identify() because identity persistence is not enabled");
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
this.userId = normalizedUserId;
|
|
688
|
+
if (!this.consentGranted) {
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
const normalizedTraits = this.cloneProperties(traits);
|
|
644
692
|
if (this.shouldDeferEventsUntilHydrated()) {
|
|
645
|
-
const deferredTraits = this.cloneProperties(traits);
|
|
646
693
|
this.deferEventUntilHydrated(() => {
|
|
647
|
-
this.identify(normalizedUserId,
|
|
694
|
+
this.identify(normalizedUserId, normalizedTraits);
|
|
648
695
|
});
|
|
649
696
|
return;
|
|
650
697
|
}
|
|
651
|
-
this.userId = normalizedUserId;
|
|
652
698
|
const sessionId = this.getSessionId();
|
|
653
699
|
this.enqueue({
|
|
654
700
|
eventId: randomId(),
|
|
@@ -657,8 +703,9 @@ var AnalyticsClient = class {
|
|
|
657
703
|
sessionId,
|
|
658
704
|
anonId: this.anonId,
|
|
659
705
|
userId: normalizedUserId,
|
|
660
|
-
properties: this.withRuntimeMetadata(
|
|
706
|
+
properties: this.withRuntimeMetadata(normalizedTraits, sessionId),
|
|
661
707
|
platform: this.platform,
|
|
708
|
+
projectSurface: this.projectSurface,
|
|
662
709
|
appVersion: this.appVersion,
|
|
663
710
|
...this.withEventContext(),
|
|
664
711
|
type: "identify"
|
|
@@ -670,13 +717,39 @@ var AnalyticsClient = class {
|
|
|
670
717
|
* - pass null/undefined/empty string to clear user linkage
|
|
671
718
|
*/
|
|
672
719
|
setUser(userId, traits) {
|
|
673
|
-
const normalizedUserId =
|
|
720
|
+
const normalizedUserId = this.readRequiredStringOption(userId);
|
|
674
721
|
if (!normalizedUserId) {
|
|
675
722
|
this.clearUser();
|
|
676
723
|
return;
|
|
677
724
|
}
|
|
678
725
|
this.identify(normalizedUserId, traits);
|
|
679
726
|
}
|
|
727
|
+
/**
|
|
728
|
+
* Sets consent specifically for persistent identity tracking.
|
|
729
|
+
* In `consent_gated` mode this toggles strict-vs-full identity behavior while generic event tracking can stay enabled.
|
|
730
|
+
*/
|
|
731
|
+
setFullTrackingConsent(granted, options = {}) {
|
|
732
|
+
if (this.identityTrackingMode === "strict") {
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
if (this.identityTrackingMode === "always_on") {
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
this.fullTrackingConsentGranted = granted;
|
|
739
|
+
if ((options.persist ?? true) && this.persistConsentState) {
|
|
740
|
+
this.writePersistedConsent(this.configuredStorage, granted);
|
|
741
|
+
}
|
|
742
|
+
this.applyIdentityTrackingState();
|
|
743
|
+
}
|
|
744
|
+
optInFullTracking(options) {
|
|
745
|
+
this.setFullTrackingConsent(true, options);
|
|
746
|
+
}
|
|
747
|
+
optOutFullTracking(options) {
|
|
748
|
+
this.setFullTrackingConsent(false, options);
|
|
749
|
+
}
|
|
750
|
+
isFullTrackingEnabled() {
|
|
751
|
+
return this.isFullTrackingActive();
|
|
752
|
+
}
|
|
680
753
|
/**
|
|
681
754
|
* Clears the current identified user from in-memory SDK state.
|
|
682
755
|
*/
|
|
@@ -707,9 +780,10 @@ var AnalyticsClient = class {
|
|
|
707
780
|
ts: nowIso(),
|
|
708
781
|
sessionId,
|
|
709
782
|
anonId: this.anonId,
|
|
710
|
-
userId: this.
|
|
783
|
+
userId: this.getEventUserId(),
|
|
711
784
|
properties: this.withRuntimeMetadata(properties, sessionId),
|
|
712
785
|
platform: this.platform,
|
|
786
|
+
projectSurface: this.projectSurface,
|
|
713
787
|
appVersion: this.appVersion,
|
|
714
788
|
...this.withEventContext(),
|
|
715
789
|
type: "track"
|
|
@@ -806,6 +880,8 @@ var AnalyticsClient = class {
|
|
|
806
880
|
/**
|
|
807
881
|
* Creates a scoped paywall tracker that applies shared paywall defaults to every journey event.
|
|
808
882
|
* Useful when a flow has a stable `source`, `paywallId`, `offering`, or experiment metadata.
|
|
883
|
+
* Reuse the returned tracker for that flow context; creating a new tracker per event resets
|
|
884
|
+
* paywall entry correlation.
|
|
809
885
|
*/
|
|
810
886
|
createPaywallTracker(defaults) {
|
|
811
887
|
const { source: rawDefaultSource, ...defaultProperties } = defaults;
|
|
@@ -909,9 +985,10 @@ var AnalyticsClient = class {
|
|
|
909
985
|
ts: nowIso(),
|
|
910
986
|
sessionId,
|
|
911
987
|
anonId: this.anonId,
|
|
912
|
-
userId: this.
|
|
988
|
+
userId: this.getEventUserId(),
|
|
913
989
|
properties: this.withRuntimeMetadata(properties, sessionId),
|
|
914
990
|
platform: this.platform,
|
|
991
|
+
projectSurface: this.projectSurface,
|
|
915
992
|
appVersion: this.appVersion,
|
|
916
993
|
...this.withEventContext(),
|
|
917
994
|
type: "screen"
|
|
@@ -944,9 +1021,10 @@ var AnalyticsClient = class {
|
|
|
944
1021
|
ts: nowIso(),
|
|
945
1022
|
sessionId,
|
|
946
1023
|
anonId: this.anonId,
|
|
947
|
-
userId: this.
|
|
1024
|
+
userId: this.getEventUserId(),
|
|
948
1025
|
properties: this.withRuntimeMetadata({ message, rating, ...properties }, sessionId),
|
|
949
1026
|
platform: this.platform,
|
|
1027
|
+
projectSurface: this.projectSurface,
|
|
950
1028
|
appVersion: this.appVersion,
|
|
951
1029
|
...this.withEventContext(),
|
|
952
1030
|
type: "feedback"
|
|
@@ -1034,6 +1112,36 @@ var AnalyticsClient = class {
|
|
|
1034
1112
|
}
|
|
1035
1113
|
}
|
|
1036
1114
|
}
|
|
1115
|
+
parsePersistedConsent(raw) {
|
|
1116
|
+
if (raw === "granted") {
|
|
1117
|
+
return true;
|
|
1118
|
+
}
|
|
1119
|
+
if (raw === "denied") {
|
|
1120
|
+
return false;
|
|
1121
|
+
}
|
|
1122
|
+
return null;
|
|
1123
|
+
}
|
|
1124
|
+
readPersistedConsentSync(storage) {
|
|
1125
|
+
if (!this.persistConsentState) {
|
|
1126
|
+
return null;
|
|
1127
|
+
}
|
|
1128
|
+
if (storage === this.storage && this.storageReadsAreAsync) {
|
|
1129
|
+
return null;
|
|
1130
|
+
}
|
|
1131
|
+
return this.parsePersistedConsent(readStorageSync(storage, this.consentStorageKey));
|
|
1132
|
+
}
|
|
1133
|
+
async readPersistedConsentAsync(storage) {
|
|
1134
|
+
if (!this.persistConsentState) {
|
|
1135
|
+
return null;
|
|
1136
|
+
}
|
|
1137
|
+
return this.parsePersistedConsent(await readStorageAsync(storage, this.consentStorageKey));
|
|
1138
|
+
}
|
|
1139
|
+
writePersistedConsent(storage, granted) {
|
|
1140
|
+
if (!this.persistConsentState) {
|
|
1141
|
+
return;
|
|
1142
|
+
}
|
|
1143
|
+
writeStorageSync(storage, this.consentStorageKey, granted ? "granted" : "denied");
|
|
1144
|
+
}
|
|
1037
1145
|
startAutoFlush() {
|
|
1038
1146
|
if (!this.hasIngestConfig) {
|
|
1039
1147
|
return;
|
|
@@ -1125,10 +1233,11 @@ var AnalyticsClient = class {
|
|
|
1125
1233
|
return;
|
|
1126
1234
|
}
|
|
1127
1235
|
try {
|
|
1128
|
-
const [storedAnonId, storedSessionId, storedLastSeen] = await Promise.all([
|
|
1236
|
+
const [storedAnonId, storedSessionId, storedLastSeen, storedConsent] = await Promise.all([
|
|
1129
1237
|
readStorageAsync(this.storage, DEVICE_ID_KEY),
|
|
1130
1238
|
readStorageAsync(this.storage, SESSION_ID_KEY),
|
|
1131
|
-
readStorageAsync(this.storage, LAST_SEEN_KEY)
|
|
1239
|
+
readStorageAsync(this.storage, LAST_SEEN_KEY),
|
|
1240
|
+
this.readPersistedConsentAsync(this.storage)
|
|
1132
1241
|
]);
|
|
1133
1242
|
if (!this.hasExplicitAnonId && storedAnonId) {
|
|
1134
1243
|
this.anonId = storedAnonId;
|
|
@@ -1140,6 +1249,13 @@ var AnalyticsClient = class {
|
|
|
1140
1249
|
this.inMemoryLastSeenMs = Date.now();
|
|
1141
1250
|
}
|
|
1142
1251
|
}
|
|
1252
|
+
if (!this.hasExplicitInitialConsent && typeof storedConsent === "boolean") {
|
|
1253
|
+
this.consentGranted = this.hasIngestConfig && storedConsent;
|
|
1254
|
+
if (!this.consentGranted) {
|
|
1255
|
+
this.queue = [];
|
|
1256
|
+
this.deferredEventsBeforeHydration = [];
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1143
1259
|
this.sessionEventSeq = await this.readSessionEventSeqAsync(this.sessionId);
|
|
1144
1260
|
await this.hydrateOnboardingStepViewState(this.sessionId);
|
|
1145
1261
|
writeStorageSync(this.storage, DEVICE_ID_KEY, this.anonId);
|
|
@@ -1308,6 +1424,81 @@ var AnalyticsClient = class {
|
|
|
1308
1424
|
return null;
|
|
1309
1425
|
}
|
|
1310
1426
|
}
|
|
1427
|
+
resolveIdentityTrackingModeOption(options) {
|
|
1428
|
+
const explicitMode = this.readRequiredStringOption(options.identityTrackingMode).toLowerCase();
|
|
1429
|
+
if (explicitMode === "strict") {
|
|
1430
|
+
return "strict";
|
|
1431
|
+
}
|
|
1432
|
+
if (explicitMode === "consent_gated") {
|
|
1433
|
+
return "consent_gated";
|
|
1434
|
+
}
|
|
1435
|
+
if (explicitMode === "always_on") {
|
|
1436
|
+
return "always_on";
|
|
1437
|
+
}
|
|
1438
|
+
if (options.enableFullTrackingWithoutConsent === true) {
|
|
1439
|
+
return "always_on";
|
|
1440
|
+
}
|
|
1441
|
+
return "consent_gated";
|
|
1442
|
+
}
|
|
1443
|
+
resolveConfiguredStorage(options) {
|
|
1444
|
+
if (this.identityTrackingMode === "strict") {
|
|
1445
|
+
if (options.storage || options.useCookieStorage || options.cookieDomain) {
|
|
1446
|
+
this.log("Ignoring storage/cookie configuration because identityTrackingMode=strict");
|
|
1447
|
+
}
|
|
1448
|
+
return null;
|
|
1449
|
+
}
|
|
1450
|
+
const customStorage = options.storage ?? null;
|
|
1451
|
+
const browserStorage = resolveBrowserStorageAdapter();
|
|
1452
|
+
const primaryStorage = customStorage ?? browserStorage;
|
|
1453
|
+
const cookieStorage = resolveCookieStorageAdapter(
|
|
1454
|
+
options.useCookieStorage === true,
|
|
1455
|
+
this.readRequiredStringOption(options.cookieDomain) || void 0,
|
|
1456
|
+
this.normalizeCookieMaxAgeSeconds(options.cookieMaxAgeSeconds)
|
|
1457
|
+
);
|
|
1458
|
+
if (primaryStorage && cookieStorage) {
|
|
1459
|
+
return combineStorageAdapters(primaryStorage, cookieStorage);
|
|
1460
|
+
}
|
|
1461
|
+
return primaryStorage ?? cookieStorage;
|
|
1462
|
+
}
|
|
1463
|
+
normalizeCookieMaxAgeSeconds(value) {
|
|
1464
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
1465
|
+
return DEFAULT_COOKIE_MAX_AGE_SECONDS;
|
|
1466
|
+
}
|
|
1467
|
+
return Math.floor(value);
|
|
1468
|
+
}
|
|
1469
|
+
isFullTrackingActive() {
|
|
1470
|
+
if (!this.hasIngestConfig) {
|
|
1471
|
+
return false;
|
|
1472
|
+
}
|
|
1473
|
+
if (this.identityTrackingMode === "always_on") {
|
|
1474
|
+
return true;
|
|
1475
|
+
}
|
|
1476
|
+
if (this.identityTrackingMode === "strict") {
|
|
1477
|
+
return false;
|
|
1478
|
+
}
|
|
1479
|
+
return this.fullTrackingConsentGranted;
|
|
1480
|
+
}
|
|
1481
|
+
applyIdentityTrackingState() {
|
|
1482
|
+
if (!this.isFullTrackingActive()) {
|
|
1483
|
+
this.storage = null;
|
|
1484
|
+
this.storageReadsAreAsync = false;
|
|
1485
|
+
this.userId = null;
|
|
1486
|
+
return;
|
|
1487
|
+
}
|
|
1488
|
+
this.storage = this.configuredStorage;
|
|
1489
|
+
this.storageReadsAreAsync = this.detectAsyncStorageReads();
|
|
1490
|
+
this.sessionId = this.ensureSessionId();
|
|
1491
|
+
this.sessionEventSeq = this.readSessionEventSeq(this.sessionId);
|
|
1492
|
+
writeStorageSync(this.storage, DEVICE_ID_KEY, this.anonId);
|
|
1493
|
+
writeStorageSync(this.storage, SESSION_ID_KEY, this.sessionId);
|
|
1494
|
+
writeStorageSync(this.storage, LAST_SEEN_KEY, String(this.inMemoryLastSeenMs));
|
|
1495
|
+
}
|
|
1496
|
+
getEventUserId() {
|
|
1497
|
+
if (!this.isFullTrackingActive()) {
|
|
1498
|
+
return null;
|
|
1499
|
+
}
|
|
1500
|
+
return this.userId;
|
|
1501
|
+
}
|
|
1311
1502
|
withEventContext() {
|
|
1312
1503
|
return {
|
|
1313
1504
|
appBuild: this.context.appBuild,
|
|
@@ -1343,6 +1534,16 @@ var AnalyticsClient = class {
|
|
|
1343
1534
|
}
|
|
1344
1535
|
return void 0;
|
|
1345
1536
|
}
|
|
1537
|
+
normalizeProjectSurfaceOption(value) {
|
|
1538
|
+
const normalized = this.readRequiredStringOption(value).toLowerCase();
|
|
1539
|
+
if (!normalized) {
|
|
1540
|
+
return void 0;
|
|
1541
|
+
}
|
|
1542
|
+
if (normalized.length > 64) {
|
|
1543
|
+
return normalized.slice(0, 64);
|
|
1544
|
+
}
|
|
1545
|
+
return normalized;
|
|
1546
|
+
}
|
|
1346
1547
|
log(message, data) {
|
|
1347
1548
|
if (!this.debug) {
|
|
1348
1549
|
return;
|
|
@@ -1351,117 +1552,110 @@ var AnalyticsClient = class {
|
|
|
1351
1552
|
}
|
|
1352
1553
|
reportMissingApiKey() {
|
|
1353
1554
|
console.error(
|
|
1354
|
-
"[analyticscli-sdk] Missing required `apiKey`. Tracking is disabled (safe no-op). Pass your
|
|
1555
|
+
"[analyticscli-sdk] Missing required `apiKey`. Tracking is disabled (safe no-op). Pass your publishable API key."
|
|
1355
1556
|
);
|
|
1356
1557
|
}
|
|
1357
1558
|
};
|
|
1358
1559
|
|
|
1359
|
-
// src/
|
|
1360
|
-
var
|
|
1361
|
-
"
|
|
1362
|
-
|
|
1363
|
-
"EXPO_PUBLIC_ANALYTICSCLI_WRITE_KEY",
|
|
1364
|
-
"VITE_ANALYTICSCLI_WRITE_KEY"
|
|
1365
|
-
];
|
|
1366
|
-
var readTrimmedString2 = (value) => {
|
|
1367
|
-
if (typeof value === "string") {
|
|
1368
|
-
return value.trim();
|
|
1369
|
-
}
|
|
1370
|
-
if (typeof value === "number" || typeof value === "boolean") {
|
|
1371
|
-
return String(value).trim();
|
|
1372
|
-
}
|
|
1373
|
-
return "";
|
|
1374
|
-
};
|
|
1375
|
-
var resolveDefaultEnv = () => {
|
|
1376
|
-
const withProcess = globalThis;
|
|
1377
|
-
if (typeof withProcess.process?.env === "object" && withProcess.process.env !== null) {
|
|
1378
|
-
return withProcess.process.env;
|
|
1560
|
+
// src/context.ts
|
|
1561
|
+
var normalizeInitInput = (input) => {
|
|
1562
|
+
if (typeof input === "string") {
|
|
1563
|
+
return { apiKey: input };
|
|
1379
1564
|
}
|
|
1380
|
-
|
|
1381
|
-
};
|
|
1382
|
-
var resolveValueFromEnv = (env, keys) => {
|
|
1383
|
-
for (const key of keys) {
|
|
1384
|
-
const value = readTrimmedString2(env[key]);
|
|
1385
|
-
if (value.length > 0) {
|
|
1386
|
-
return value;
|
|
1387
|
-
}
|
|
1565
|
+
if (input === null || input === void 0) {
|
|
1566
|
+
return {};
|
|
1388
1567
|
}
|
|
1389
|
-
return
|
|
1568
|
+
return input;
|
|
1390
1569
|
};
|
|
1391
|
-
var
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
parts.push(`apiKey (searched: ${details.searchedApiKeyEnvKeys.join(", ") || "none"})`);
|
|
1570
|
+
var resolveClient = (input) => {
|
|
1571
|
+
if (input instanceof AnalyticsClient) {
|
|
1572
|
+
return input;
|
|
1395
1573
|
}
|
|
1396
|
-
return
|
|
1574
|
+
return new AnalyticsClient(normalizeInitInput(input ?? {}));
|
|
1397
1575
|
};
|
|
1398
|
-
var
|
|
1399
|
-
const
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1576
|
+
var createAnalyticsContext = (options = {}) => {
|
|
1577
|
+
const client = resolveClient(options.client);
|
|
1578
|
+
let onboardingTracker = client.createOnboardingTracker(options.onboarding ?? {});
|
|
1579
|
+
let paywallTracker = options.paywall ? client.createPaywallTracker(options.paywall) : null;
|
|
1580
|
+
const consent = {
|
|
1581
|
+
get: () => client.getConsent(),
|
|
1582
|
+
getState: () => client.getConsentState(),
|
|
1583
|
+
set: (granted, setOptions) => client.setConsent(granted, setOptions),
|
|
1584
|
+
optIn: (setOptions) => client.optIn(setOptions),
|
|
1585
|
+
optOut: (setOptions) => client.optOut(setOptions),
|
|
1586
|
+
setFullTracking: (granted, setOptions) => client.setFullTrackingConsent(granted, setOptions),
|
|
1587
|
+
optInFullTracking: (setOptions) => client.optInFullTracking(setOptions),
|
|
1588
|
+
optOutFullTracking: (setOptions) => client.optOutFullTracking(setOptions),
|
|
1589
|
+
isFullTrackingEnabled: () => client.isFullTrackingEnabled()
|
|
1590
|
+
};
|
|
1591
|
+
const user = {
|
|
1592
|
+
identify: (userId, traits) => client.identify(userId, traits),
|
|
1593
|
+
set: (userId, traits) => client.setUser(userId, traits),
|
|
1594
|
+
clear: () => client.clearUser()
|
|
1595
|
+
};
|
|
1596
|
+
return {
|
|
1597
|
+
client,
|
|
1598
|
+
get onboarding() {
|
|
1599
|
+
return onboardingTracker;
|
|
1600
|
+
},
|
|
1601
|
+
get paywall() {
|
|
1602
|
+
return paywallTracker;
|
|
1603
|
+
},
|
|
1604
|
+
consent,
|
|
1605
|
+
user,
|
|
1606
|
+
track: (eventName, properties) => client.track(eventName, properties),
|
|
1607
|
+
trackOnboardingEvent: (eventName, properties) => client.trackOnboardingEvent(eventName, properties),
|
|
1608
|
+
trackOnboardingSurveyResponse: (input, eventName) => client.trackOnboardingSurveyResponse(input, eventName),
|
|
1609
|
+
trackPaywallEvent: (eventName, properties) => client.trackPaywallEvent(eventName, properties),
|
|
1610
|
+
screen: (name, properties) => client.screen(name, properties),
|
|
1611
|
+
page: (name, properties) => client.page(name, properties),
|
|
1612
|
+
feedback: (message, rating, properties) => client.feedback(message, rating, properties),
|
|
1613
|
+
setContext: (context) => client.setContext(context),
|
|
1614
|
+
createOnboarding: (defaults) => client.createOnboardingTracker(defaults),
|
|
1615
|
+
createPaywall: (defaults) => client.createPaywallTracker(defaults),
|
|
1616
|
+
configureOnboarding: (defaults) => {
|
|
1617
|
+
onboardingTracker = client.createOnboardingTracker(defaults);
|
|
1618
|
+
return onboardingTracker;
|
|
1619
|
+
},
|
|
1620
|
+
configurePaywall: (defaults) => {
|
|
1621
|
+
paywallTracker = client.createPaywallTracker(defaults);
|
|
1622
|
+
return paywallTracker;
|
|
1623
|
+
},
|
|
1624
|
+
ready: () => client.ready(),
|
|
1625
|
+
flush: () => client.flush(),
|
|
1626
|
+
shutdown: () => client.shutdown()
|
|
1413
1627
|
};
|
|
1414
|
-
if (missingConfig.missingApiKey) {
|
|
1415
|
-
onMissingConfig?.(missingConfig);
|
|
1416
|
-
if (missingConfigMode === "throw") {
|
|
1417
|
-
throw new Error(toMissingMessage(missingConfig));
|
|
1418
|
-
}
|
|
1419
|
-
}
|
|
1420
|
-
return new AnalyticsClient({
|
|
1421
|
-
...clientOptions,
|
|
1422
|
-
apiKey: resolvedApiKey
|
|
1423
|
-
});
|
|
1424
1628
|
};
|
|
1425
1629
|
|
|
1426
1630
|
// src/index.ts
|
|
1427
|
-
var
|
|
1631
|
+
var normalizeInitInput2 = (input) => {
|
|
1428
1632
|
if (typeof input === "string") {
|
|
1429
1633
|
return { apiKey: input };
|
|
1430
1634
|
}
|
|
1635
|
+
if (input === null || input === void 0) {
|
|
1636
|
+
return {};
|
|
1637
|
+
}
|
|
1431
1638
|
return input;
|
|
1432
1639
|
};
|
|
1433
1640
|
var init = (input = {}) => {
|
|
1434
|
-
return new AnalyticsClient(
|
|
1641
|
+
return new AnalyticsClient(normalizeInitInput2(input));
|
|
1642
|
+
};
|
|
1643
|
+
var initConsentFirst = (input = {}) => {
|
|
1644
|
+
const normalized = normalizeInitInput2(input);
|
|
1645
|
+
return new AnalyticsClient({
|
|
1646
|
+
...normalized,
|
|
1647
|
+
initialConsentGranted: false
|
|
1648
|
+
});
|
|
1435
1649
|
};
|
|
1436
1650
|
var initAsync = async (input = {}) => {
|
|
1437
|
-
const client = new AnalyticsClient(
|
|
1651
|
+
const client = new AnalyticsClient(normalizeInitInput2(input));
|
|
1438
1652
|
await client.ready();
|
|
1439
1653
|
return client;
|
|
1440
1654
|
};
|
|
1441
|
-
var
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
"VITE_ANALYTICSCLI_WRITE_KEY",
|
|
1446
|
-
"EXPO_PUBLIC_ANALYTICSCLI_WRITE_KEY"
|
|
1447
|
-
];
|
|
1448
|
-
var REACT_NATIVE_API_KEY_ENV_KEYS = [
|
|
1449
|
-
"ANALYTICSCLI_WRITE_KEY",
|
|
1450
|
-
"EXPO_PUBLIC_ANALYTICSCLI_WRITE_KEY"
|
|
1451
|
-
];
|
|
1452
|
-
var initBrowserFromEnv = (options = {}) => {
|
|
1453
|
-
const { apiKeyEnvKeys, ...rest } = options;
|
|
1454
|
-
return initFromEnv({
|
|
1455
|
-
...rest,
|
|
1456
|
-
apiKeyEnvKeys: [...apiKeyEnvKeys ?? BROWSER_API_KEY_ENV_KEYS]
|
|
1457
|
-
});
|
|
1458
|
-
};
|
|
1459
|
-
var initReactNativeFromEnv = (options = {}) => {
|
|
1460
|
-
const { apiKeyEnvKeys, ...rest } = options;
|
|
1461
|
-
return initFromEnv({
|
|
1462
|
-
...rest,
|
|
1463
|
-
apiKeyEnvKeys: [...apiKeyEnvKeys ?? REACT_NATIVE_API_KEY_ENV_KEYS]
|
|
1464
|
-
});
|
|
1655
|
+
var initConsentFirstAsync = async (input = {}) => {
|
|
1656
|
+
const client = initConsentFirst(input);
|
|
1657
|
+
await client.ready();
|
|
1658
|
+
return client;
|
|
1465
1659
|
};
|
|
1466
1660
|
|
|
1467
1661
|
export {
|
|
@@ -1476,12 +1670,9 @@ export {
|
|
|
1476
1670
|
PAYWALL_SKIP_EVENT_CANDIDATES,
|
|
1477
1671
|
PURCHASE_SUCCESS_EVENT_CANDIDATES,
|
|
1478
1672
|
AnalyticsClient,
|
|
1479
|
-
|
|
1480
|
-
initFromEnv,
|
|
1673
|
+
createAnalyticsContext,
|
|
1481
1674
|
init,
|
|
1675
|
+
initConsentFirst,
|
|
1482
1676
|
initAsync,
|
|
1483
|
-
|
|
1484
|
-
REACT_NATIVE_API_KEY_ENV_KEYS,
|
|
1485
|
-
initBrowserFromEnv,
|
|
1486
|
-
initReactNativeFromEnv
|
|
1677
|
+
initConsentFirstAsync
|
|
1487
1678
|
};
|