@chordcommerce/analytics 1.19.0 → 1.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/client/index.d.ts +18 -1
- package/dist/cjs/client/index.js +260 -32
- package/dist/cjs/setupTests.js +23 -0
- package/dist/cjs/types/formatters.d.ts +6 -2
- package/dist/cjs/types/input.d.ts +245 -0
- package/dist/client/index.d.ts +18 -1
- package/dist/client/index.js +243 -26
- package/dist/setupTests.js +23 -0
- package/dist/types/formatters.d.ts +6 -2
- package/dist/types/input.d.ts +245 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyAnalytics, EventProperties, Options, ValidateResult, ChordAnalyticsOptions, AnyOptions, CartViewedInput, IdentifyTraits, CheckoutStartedInput, CheckoutStepCompletedInput, CheckoutStepViewedInput, EmailCapturedInput, ProductListViewedInput, ProductListFilteredInput, ProductAddedInput, ProductClickedInput, VariantClickedInput, ProductRemovedInput, ProductViewedInput, ProductsSearchedInput, CouponAppliedInput, CouponDeniedInput, CouponEnteredInput, CouponRemovedInput, SignedInInput, SignedOutInput, SignedUpInput, LoginStartedInput, ObjectTypes, SubscriptionCancelledInput, NavigationClickedInput, PaymentInfoEnteredInput } from '../types/index.js';
|
|
1
|
+
import type { AnyAnalytics, EventProperties, Options, ValidateResult, ChordAnalyticsOptions, AnyOptions, CartViewedInput, IdentifyTraits, CheckoutStartedInput, CheckoutStepCompletedInput, CheckoutStepViewedInput, EmailCapturedInput, ProductListViewedInput, ProductListFilteredInput, ProductAddedInput, ProductClickedInput, VariantClickedInput, ProductRemovedInput, ProductViewedInput, ProductsSearchedInput, CouponAppliedInput, CouponDeniedInput, CouponEnteredInput, CouponRemovedInput, SignedInInput, SignedOutInput, SignedUpInput, LoginStartedInput, ObjectTypes, OrderCompletedInput, SubscriptionCancelledInput, NavigationClickedInput, PaymentInfoEnteredInput } from '../types/index.js';
|
|
2
2
|
import { AnalyticsMiddleware } from '../types/client.js';
|
|
3
3
|
export interface ChordAnalyticsSnippet {
|
|
4
4
|
_loadOptions: ChordAnalyticsOptions<ObjectTypes>;
|
|
@@ -45,6 +45,20 @@ export declare class ChordAnalytics<T extends ObjectTypes = ObjectTypes> {
|
|
|
45
45
|
*/
|
|
46
46
|
private consentReadyPromise;
|
|
47
47
|
constructor(options: ChordAnalyticsOptions<T>);
|
|
48
|
+
/**
|
|
49
|
+
* Persist the consent event queue to sessionStorage for recovery on instance recreation.
|
|
50
|
+
* Validates queue size before storing to prevent QuotaExceededError.
|
|
51
|
+
*/
|
|
52
|
+
private persistQueueToStorage;
|
|
53
|
+
/**
|
|
54
|
+
* Restore pending events from sessionStorage (keeps events less than 5 min old).
|
|
55
|
+
* Called on new instance initialization.
|
|
56
|
+
*/
|
|
57
|
+
private restoreQueueFromStorage;
|
|
58
|
+
/**
|
|
59
|
+
* Clear the persisted queue from sessionStorage after successful flush.
|
|
60
|
+
*/
|
|
61
|
+
private clearQueueFromStorage;
|
|
48
62
|
/**
|
|
49
63
|
* Initialize CDP snippet and wait for it to be ready.
|
|
50
64
|
* Fires initial consent track event after CDP is fully initialized to avoid circular await.
|
|
@@ -66,6 +80,7 @@ export declare class ChordAnalytics<T extends ObjectTypes = ObjectTypes> {
|
|
|
66
80
|
private waitForConsent;
|
|
67
81
|
/**
|
|
68
82
|
* Queue an event to be sent when consent is ready.
|
|
83
|
+
* Persists to sessionStorage for recovery on instance recreation.
|
|
69
84
|
* Starts a consent watcher if not already active.
|
|
70
85
|
*/
|
|
71
86
|
private queueEventForConsent;
|
|
@@ -75,6 +90,7 @@ export declare class ChordAnalytics<T extends ObjectTypes = ObjectTypes> {
|
|
|
75
90
|
private watchForConsentAndFlush;
|
|
76
91
|
/**
|
|
77
92
|
* Flush all queued events now that consent is ready.
|
|
93
|
+
* Clears sessionStorage after successful flush.
|
|
78
94
|
*/
|
|
79
95
|
private flushConsentQueue;
|
|
80
96
|
/**
|
|
@@ -159,4 +175,5 @@ export declare class ChordAnalytics<T extends ObjectTypes = ObjectTypes> {
|
|
|
159
175
|
trackSubscriptionCancelled: (props: SubscriptionCancelledInput, options?: AnyOptions) => Promise<void>;
|
|
160
176
|
trackNavigationClicked: (props: NavigationClickedInput, options?: AnyOptions) => Promise<void>;
|
|
161
177
|
trackPaymentInfoEntered: (props: PaymentInfoEnteredInput, options?: AnyOptions) => Promise<void>;
|
|
178
|
+
trackOrderCompleted: (props: OrderCompletedInput, options?: AnyOptions) => Promise<void>;
|
|
162
179
|
}
|
package/dist/cjs/client/index.js
CHANGED
|
@@ -62,6 +62,10 @@ var index_js_1 = require("./consent/index.js");
|
|
|
62
62
|
var index_js_2 = require("../validators/index.js");
|
|
63
63
|
var utils_js_1 = require("../utils.js");
|
|
64
64
|
var DEBUG_MODE_STORAGE_KEY = 'chordcommerce/analytics/debug';
|
|
65
|
+
var CONSENT_QUEUE_STORAGE_KEY = 'chordcommerce/analytics/consent-queue';
|
|
66
|
+
var CONSENT_QUEUE_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
67
|
+
var CONSENT_QUEUE_MAX_SIZE_BYTES = 100 * 1024; // 100KB max queue size
|
|
68
|
+
var CONSENT_QUEUE_MAX_EVENTS = 50; // Max number of events to queue
|
|
65
69
|
var ChordAnalytics = /** @class */ (function () {
|
|
66
70
|
function ChordAnalytics(options) {
|
|
67
71
|
var _this = this;
|
|
@@ -96,6 +100,123 @@ var ChordAnalytics = /** @class */ (function () {
|
|
|
96
100
|
* Promise that resolves when consent is ready (shared across all queued events)
|
|
97
101
|
*/
|
|
98
102
|
this.consentReadyPromise = null;
|
|
103
|
+
/**
|
|
104
|
+
* Persist the consent event queue to sessionStorage for recovery on instance recreation.
|
|
105
|
+
* Validates queue size before storing to prevent QuotaExceededError.
|
|
106
|
+
*/
|
|
107
|
+
this.persistQueueToStorage = function () {
|
|
108
|
+
if (typeof window === 'undefined' || !window.sessionStorage)
|
|
109
|
+
return;
|
|
110
|
+
try {
|
|
111
|
+
// Limit number of events to prevent unbounded queue growth
|
|
112
|
+
var eventsToStore = _this.consentEventQueue.slice(-CONSENT_QUEUE_MAX_EVENTS);
|
|
113
|
+
var persistedEvents = eventsToStore.map(function (item) { return ({
|
|
114
|
+
type: item.type,
|
|
115
|
+
args: item.args,
|
|
116
|
+
timestamp: item.timestamp,
|
|
117
|
+
}); });
|
|
118
|
+
var serialized = JSON.stringify(persistedEvents);
|
|
119
|
+
// Check serialized size before attempting to store
|
|
120
|
+
var sizeInBytes = new Blob([serialized]).size;
|
|
121
|
+
if (sizeInBytes > CONSENT_QUEUE_MAX_SIZE_BYTES) {
|
|
122
|
+
_this.logger("[Chord Analytics]: Consent queue too large (".concat(Math.round(sizeInBytes / 1024), "KB), skipping persistence"));
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
window.sessionStorage.setItem(CONSENT_QUEUE_STORAGE_KEY, serialized);
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
_this.logger('[Chord Analytics]: Error persisting queue to storage:', error);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Restore pending events from sessionStorage (keeps events less than 5 min old).
|
|
133
|
+
* Called on new instance initialization.
|
|
134
|
+
*/
|
|
135
|
+
this.restoreQueueFromStorage = function () {
|
|
136
|
+
if (typeof window === 'undefined' || !window.sessionStorage)
|
|
137
|
+
return;
|
|
138
|
+
try {
|
|
139
|
+
var stored = window.sessionStorage.getItem(CONSENT_QUEUE_STORAGE_KEY);
|
|
140
|
+
if (!stored)
|
|
141
|
+
return;
|
|
142
|
+
var persistedEvents = void 0;
|
|
143
|
+
try {
|
|
144
|
+
persistedEvents = JSON.parse(stored);
|
|
145
|
+
}
|
|
146
|
+
catch (parseError) {
|
|
147
|
+
_this.logger('[Chord Analytics]: Invalid JSON in stored consent queue, clearing storage:', parseError);
|
|
148
|
+
window.sessionStorage.removeItem(CONSENT_QUEUE_STORAGE_KEY);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
// Validate that parsed data is an array
|
|
152
|
+
if (!Array.isArray(persistedEvents)) {
|
|
153
|
+
_this.logger('[Chord Analytics]: Stored consent queue is not an array, clearing storage');
|
|
154
|
+
window.sessionStorage.removeItem(CONSENT_QUEUE_STORAGE_KEY);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
var now_1 = Date.now();
|
|
158
|
+
// Filter out expired events and events with invalid structure
|
|
159
|
+
var validEvents = persistedEvents.filter(function (event) {
|
|
160
|
+
// Validate event structure
|
|
161
|
+
if (typeof event !== 'object' || event === null)
|
|
162
|
+
return false;
|
|
163
|
+
if (!['track', 'page', 'identify'].includes(event.type))
|
|
164
|
+
return false;
|
|
165
|
+
if (!Array.isArray(event.args))
|
|
166
|
+
return false;
|
|
167
|
+
if (typeof event.timestamp !== 'number')
|
|
168
|
+
return false;
|
|
169
|
+
// Filter out expired events
|
|
170
|
+
return now_1 - event.timestamp < CONSENT_QUEUE_TTL_MS;
|
|
171
|
+
});
|
|
172
|
+
if (validEvents.length === 0) {
|
|
173
|
+
window.sessionStorage.removeItem(CONSENT_QUEUE_STORAGE_KEY);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (_this.options.enableLogging && _this.options.debug) {
|
|
177
|
+
// eslint-disable-next-line no-console
|
|
178
|
+
console.log("[Chord Analytics DEBUG]: Restoring ".concat(validEvents.length, " events from sessionStorage"));
|
|
179
|
+
}
|
|
180
|
+
// Add restored events to the queue
|
|
181
|
+
validEvents.forEach(function (event) {
|
|
182
|
+
_this.consentEventQueue.push({
|
|
183
|
+
type: event.type,
|
|
184
|
+
args: event.args,
|
|
185
|
+
timestamp: event.timestamp,
|
|
186
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
187
|
+
resolve: function () { },
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
// Start watching for consent if we restored events
|
|
191
|
+
if (validEvents.length > 0 && !_this.consentWatcherActive) {
|
|
192
|
+
_this.consentWatcherActive = true;
|
|
193
|
+
_this.watchForConsentAndFlush();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
_this.logger('[Chord Analytics]: Error restoring queue from storage:', error);
|
|
198
|
+
// Clear corrupted storage
|
|
199
|
+
try {
|
|
200
|
+
window.sessionStorage.removeItem(CONSENT_QUEUE_STORAGE_KEY);
|
|
201
|
+
}
|
|
202
|
+
catch (_a) {
|
|
203
|
+
// Ignore cleanup errors
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* Clear the persisted queue from sessionStorage after successful flush.
|
|
209
|
+
*/
|
|
210
|
+
this.clearQueueFromStorage = function () {
|
|
211
|
+
if (typeof window === 'undefined' || !window.sessionStorage)
|
|
212
|
+
return;
|
|
213
|
+
try {
|
|
214
|
+
window.sessionStorage.removeItem(CONSENT_QUEUE_STORAGE_KEY);
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
_this.logger('[Chord Analytics]: Error clearing queue from storage:', error);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
99
220
|
/**
|
|
100
221
|
* Set debug mode for Chord Analytics
|
|
101
222
|
* @param enabled - Whether debug mode should be enabled
|
|
@@ -180,11 +301,19 @@ var ChordAnalytics = /** @class */ (function () {
|
|
|
180
301
|
}); };
|
|
181
302
|
/**
|
|
182
303
|
* Queue an event to be sent when consent is ready.
|
|
304
|
+
* Persists to sessionStorage for recovery on instance recreation.
|
|
183
305
|
* Starts a consent watcher if not already active.
|
|
184
306
|
*/
|
|
185
307
|
this.queueEventForConsent = function (type, args) {
|
|
186
308
|
return new Promise(function (resolve) {
|
|
187
|
-
_this.consentEventQueue.push({
|
|
309
|
+
_this.consentEventQueue.push({
|
|
310
|
+
type: type,
|
|
311
|
+
args: args,
|
|
312
|
+
timestamp: Date.now(),
|
|
313
|
+
resolve: resolve,
|
|
314
|
+
});
|
|
315
|
+
// Persist queue to sessionStorage for recovery on instance recreation
|
|
316
|
+
_this.persistQueueToStorage();
|
|
188
317
|
// Start watching for consent if not already
|
|
189
318
|
if (!_this.consentWatcherActive) {
|
|
190
319
|
_this.consentWatcherActive = true;
|
|
@@ -211,6 +340,7 @@ var ChordAnalytics = /** @class */ (function () {
|
|
|
211
340
|
}); };
|
|
212
341
|
/**
|
|
213
342
|
* Flush all queued events now that consent is ready.
|
|
343
|
+
* Clears sessionStorage after successful flush.
|
|
214
344
|
*/
|
|
215
345
|
this.flushConsentQueue = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
216
346
|
var queue, sendPromises;
|
|
@@ -220,6 +350,12 @@ var ChordAnalytics = /** @class */ (function () {
|
|
|
220
350
|
case 0:
|
|
221
351
|
queue = __spreadArray([], this.consentEventQueue, true);
|
|
222
352
|
this.consentEventQueue = [];
|
|
353
|
+
// Clear persisted queue from storage since we're processing them now
|
|
354
|
+
this.clearQueueFromStorage();
|
|
355
|
+
if (this.options.enableLogging && this.options.debug) {
|
|
356
|
+
// eslint-disable-next-line no-console
|
|
357
|
+
console.log("[Chord Analytics DEBUG]: Flushing ".concat(queue.length, " queued events"));
|
|
358
|
+
}
|
|
223
359
|
sendPromises = queue.map(function (item) { return __awaiter(_this, void 0, void 0, function () {
|
|
224
360
|
var _a, error_1;
|
|
225
361
|
return __generator(this, function (_b) {
|
|
@@ -425,12 +561,7 @@ var ChordAnalytics = /** @class */ (function () {
|
|
|
425
561
|
}));
|
|
426
562
|
}
|
|
427
563
|
if (cdpPromises.length > 0) {
|
|
428
|
-
Promise.allSettled(cdpPromises)
|
|
429
|
-
.then(function () { return resolve(); })
|
|
430
|
-
.catch(function (error) {
|
|
431
|
-
_this.logger(error);
|
|
432
|
-
resolve();
|
|
433
|
-
});
|
|
564
|
+
Promise.allSettled(cdpPromises).then(function () { return resolve(); });
|
|
434
565
|
}
|
|
435
566
|
else {
|
|
436
567
|
resolve();
|
|
@@ -564,34 +695,50 @@ var ChordAnalytics = /** @class */ (function () {
|
|
|
564
695
|
this.sendPageEvent = function (options, props) {
|
|
565
696
|
if (props === void 0) { props = {}; }
|
|
566
697
|
return __awaiter(_this, void 0, void 0, function () {
|
|
567
|
-
var pagePromises, a_3, b_3;
|
|
568
698
|
var _this = this;
|
|
569
699
|
return __generator(this, function (_a) {
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
700
|
+
switch (_a.label) {
|
|
701
|
+
case 0:
|
|
702
|
+
// Configure CDP with fresh consent before sending
|
|
703
|
+
this.configureConsentOnCdp();
|
|
704
|
+
return [4 /*yield*/, new Promise(function (resolve) {
|
|
705
|
+
var pagePromises = [];
|
|
706
|
+
try {
|
|
707
|
+
var a_3 = _this.ccdp();
|
|
708
|
+
if (a_3 && typeof a_3.page === 'function') {
|
|
709
|
+
pagePromises.push(new Promise(function (cdpResolve) {
|
|
710
|
+
a_3.page(__assign(__assign({}, props), { meta: _this.meta() }), options, function () {
|
|
711
|
+
return cdpResolve();
|
|
712
|
+
});
|
|
713
|
+
}));
|
|
714
|
+
}
|
|
715
|
+
var b_3 = _this.cdp();
|
|
716
|
+
if (b_3 && typeof b_3.page === 'function') {
|
|
717
|
+
pagePromises.push(new Promise(function (cdpResolve) {
|
|
718
|
+
b_3.page(__assign(__assign({}, props), { meta: _this.meta() }), options, function () {
|
|
719
|
+
return cdpResolve();
|
|
720
|
+
});
|
|
721
|
+
}));
|
|
722
|
+
}
|
|
723
|
+
if (pagePromises.length > 0) {
|
|
724
|
+
Promise.allSettled(pagePromises).then(function (results) {
|
|
725
|
+
_this.logger('page event sent', results);
|
|
726
|
+
resolve();
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
else {
|
|
730
|
+
resolve();
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
catch (error) {
|
|
734
|
+
_this.logger(error);
|
|
735
|
+
resolve();
|
|
736
|
+
}
|
|
737
|
+
})];
|
|
738
|
+
case 1:
|
|
739
|
+
_a.sent();
|
|
740
|
+
return [2 /*return*/];
|
|
593
741
|
}
|
|
594
|
-
return [2 /*return*/];
|
|
595
742
|
});
|
|
596
743
|
});
|
|
597
744
|
};
|
|
@@ -1101,6 +1248,85 @@ var ChordAnalytics = /** @class */ (function () {
|
|
|
1101
1248
|
return [2 /*return*/, this.track('Payment Info Entered', payload, options)];
|
|
1102
1249
|
});
|
|
1103
1250
|
}); };
|
|
1251
|
+
this.trackOrderCompleted = function (props, options) { return __awaiter(_this, void 0, void 0, function () {
|
|
1252
|
+
var formatter, payload, formattedPayload;
|
|
1253
|
+
var _a, _b, _c, _d;
|
|
1254
|
+
return __generator(this, function (_e) {
|
|
1255
|
+
formatter = (_c = (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.formatters) === null || _b === void 0 ? void 0 : _b.events) === null || _c === void 0 ? void 0 : _c.orderCompleted;
|
|
1256
|
+
payload = {
|
|
1257
|
+
affiliation: props === null || props === void 0 ? void 0 : props.affiliation,
|
|
1258
|
+
campaign_id: props === null || props === void 0 ? void 0 : props.campaignId,
|
|
1259
|
+
category: props === null || props === void 0 ? void 0 : props.category,
|
|
1260
|
+
channel: props === null || props === void 0 ? void 0 : props.channel,
|
|
1261
|
+
checkout_id: props === null || props === void 0 ? void 0 : props.checkoutId,
|
|
1262
|
+
checkout_type: props === null || props === void 0 ? void 0 : props.checkoutType,
|
|
1263
|
+
coupon: props === null || props === void 0 ? void 0 : props.coupon,
|
|
1264
|
+
currency: props === null || props === void 0 ? void 0 : props.currency,
|
|
1265
|
+
discount: props === null || props === void 0 ? void 0 : props.discount,
|
|
1266
|
+
email: props === null || props === void 0 ? void 0 : props.email,
|
|
1267
|
+
first_name: props === null || props === void 0 ? void 0 : props.firstName,
|
|
1268
|
+
has_subscription: props === null || props === void 0 ? void 0 : props.hasSubscription,
|
|
1269
|
+
is_recurring: props === null || props === void 0 ? void 0 : props.isRecurring,
|
|
1270
|
+
last_name: props === null || props === void 0 ? void 0 : props.lastName,
|
|
1271
|
+
metadata: props === null || props === void 0 ? void 0 : props.metadata,
|
|
1272
|
+
order_date: props === null || props === void 0 ? void 0 : props.orderDate,
|
|
1273
|
+
order_id: props === null || props === void 0 ? void 0 : props.orderId,
|
|
1274
|
+
phone: props === null || props === void 0 ? void 0 : props.phone,
|
|
1275
|
+
products: (_d = props === null || props === void 0 ? void 0 : props.products) === null || _d === void 0 ? void 0 : _d.map(function (p, i) {
|
|
1276
|
+
var _a;
|
|
1277
|
+
return ({
|
|
1278
|
+
affiliation: p === null || p === void 0 ? void 0 : p.affiliation,
|
|
1279
|
+
brand: p === null || p === void 0 ? void 0 : p.brand,
|
|
1280
|
+
bundle: p === null || p === void 0 ? void 0 : p.bundle,
|
|
1281
|
+
bundle_size: p === null || p === void 0 ? void 0 : p.bundleSize,
|
|
1282
|
+
category: p === null || p === void 0 ? void 0 : p.category,
|
|
1283
|
+
coupon: p === null || p === void 0 ? void 0 : p.coupon,
|
|
1284
|
+
cross_sold_quantity: p === null || p === void 0 ? void 0 : p.crossSoldQuantity,
|
|
1285
|
+
description: p === null || p === void 0 ? void 0 : p.description,
|
|
1286
|
+
image_url: p === null || p === void 0 ? void 0 : p.imageUrl,
|
|
1287
|
+
line_item_id: p === null || p === void 0 ? void 0 : p.lineItemId,
|
|
1288
|
+
name: p === null || p === void 0 ? void 0 : p.name,
|
|
1289
|
+
option_values: p === null || p === void 0 ? void 0 : p.optionValues,
|
|
1290
|
+
position: (_a = p === null || p === void 0 ? void 0 : p.position) !== null && _a !== void 0 ? _a : i + 1,
|
|
1291
|
+
price: p === null || p === void 0 ? void 0 : p.price,
|
|
1292
|
+
product_id: p === null || p === void 0 ? void 0 : p.productId,
|
|
1293
|
+
quantity: p === null || p === void 0 ? void 0 : p.quantity,
|
|
1294
|
+
revenue: p === null || p === void 0 ? void 0 : p.revenue,
|
|
1295
|
+
sku: p === null || p === void 0 ? void 0 : p.sku,
|
|
1296
|
+
slug: p === null || p === void 0 ? void 0 : p.slug,
|
|
1297
|
+
url: p === null || p === void 0 ? void 0 : p.url,
|
|
1298
|
+
variant: p === null || p === void 0 ? void 0 : p.variant,
|
|
1299
|
+
variant_metadata: p === null || p === void 0 ? void 0 : p.variantMetadata,
|
|
1300
|
+
});
|
|
1301
|
+
}),
|
|
1302
|
+
purl_link: props === null || props === void 0 ? void 0 : props.purlLink,
|
|
1303
|
+
referral_identifier_id: props === null || props === void 0 ? void 0 : props.referralIdentifierId,
|
|
1304
|
+
repeat: props === null || props === void 0 ? void 0 : props.repeat,
|
|
1305
|
+
revenue: props === null || props === void 0 ? void 0 : props.revenue,
|
|
1306
|
+
shipping: props === null || props === void 0 ? void 0 : props.shipping,
|
|
1307
|
+
shipping_city: props === null || props === void 0 ? void 0 : props.shippingCity,
|
|
1308
|
+
shipping_country: props === null || props === void 0 ? void 0 : props.shippingCountry,
|
|
1309
|
+
shipping_method_details: (props === null || props === void 0 ? void 0 : props.shippingMethodDetails)
|
|
1310
|
+
? {
|
|
1311
|
+
shipping_code: props.shippingMethodDetails.shippingCode,
|
|
1312
|
+
shipping_method: props.shippingMethodDetails.shippingMethod,
|
|
1313
|
+
}
|
|
1314
|
+
: undefined,
|
|
1315
|
+
shipping_state: props === null || props === void 0 ? void 0 : props.shippingState,
|
|
1316
|
+
shipping_zipcode: props === null || props === void 0 ? void 0 : props.shippingZipcode,
|
|
1317
|
+
subtotal: props === null || props === void 0 ? void 0 : props.subtotal,
|
|
1318
|
+
tax: props === null || props === void 0 ? void 0 : props.tax,
|
|
1319
|
+
template_id: props === null || props === void 0 ? void 0 : props.templateId,
|
|
1320
|
+
total: props === null || props === void 0 ? void 0 : props.total,
|
|
1321
|
+
tracking_ids: props === null || props === void 0 ? void 0 : props.trackingIds,
|
|
1322
|
+
};
|
|
1323
|
+
if (typeof formatter === 'function') {
|
|
1324
|
+
formattedPayload = formatter(props, payload);
|
|
1325
|
+
return [2 /*return*/, this.track('Order Completed', formattedPayload, options)];
|
|
1326
|
+
}
|
|
1327
|
+
return [2 /*return*/, this.track('Order Completed', payload, options)];
|
|
1328
|
+
});
|
|
1329
|
+
}); };
|
|
1104
1330
|
var debug = ((_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.getItem(DEBUG_MODE_STORAGE_KEY)) === 'true';
|
|
1105
1331
|
var defaults = {
|
|
1106
1332
|
debug: debug,
|
|
@@ -1113,6 +1339,8 @@ var ChordAnalytics = /** @class */ (function () {
|
|
|
1113
1339
|
var consentManager = (0, index_js_1.addCdpConsent)(this.options);
|
|
1114
1340
|
this.consentConfig = consentManager.getConsentConfig() || null;
|
|
1115
1341
|
}
|
|
1342
|
+
// Restore any pending events from sessionStorage (survives instance recreation)
|
|
1343
|
+
this.restoreQueueFromStorage();
|
|
1116
1344
|
if (((_b = this.options) === null || _b === void 0 ? void 0 : _b.cdpDomain) && ((_c = this.options) === null || _c === void 0 ? void 0 : _c.cdpWriteKey) && window) {
|
|
1117
1345
|
window[this.options.namespace] = (window === null || window === void 0 ? void 0 : window[this.options.namespace]) || this;
|
|
1118
1346
|
this.initializeCdp();
|
package/dist/cjs/setupTests.js
CHANGED
|
@@ -4,3 +4,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
var globals_1 = require("@jest/globals");
|
|
5
5
|
// Make jest available globally
|
|
6
6
|
globalThis.jest = globals_1.jest;
|
|
7
|
+
// Mock sessionStorage for tests
|
|
8
|
+
var sessionStorageMock = (function () {
|
|
9
|
+
var store = {};
|
|
10
|
+
return {
|
|
11
|
+
getItem: function (key) { return store[key] || null; },
|
|
12
|
+
setItem: function (key, value) {
|
|
13
|
+
store[key] = value;
|
|
14
|
+
},
|
|
15
|
+
removeItem: function (key) {
|
|
16
|
+
delete store[key];
|
|
17
|
+
},
|
|
18
|
+
clear: function () {
|
|
19
|
+
store = {};
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
})();
|
|
23
|
+
Object.defineProperty(window, 'sessionStorage', {
|
|
24
|
+
value: sessionStorageMock,
|
|
25
|
+
});
|
|
26
|
+
// Clear sessionStorage before each test to ensure test isolation
|
|
27
|
+
beforeEach(function () {
|
|
28
|
+
sessionStorageMock.clear();
|
|
29
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { CartViewed, CheckoutStarted, CheckoutStepCompleted, CheckoutStepViewed, ProductAdded, ProductClicked, VariantClicked, ProductViewed, ProductListViewed, CouponApplied, CouponDenied, CouponEntered, CouponRemoved, EmailCaptured, ProductListFiltered, ProductRemoved, ProductsSearched, SignedIn, SignedOut, SignedUp, LoginStarted, SubscriptionCancelled, NavigationClicked, PaymentInfoEntered } from './typewriter.js';
|
|
1
|
+
import type { CartViewed, CheckoutStarted, CheckoutStepCompleted, CheckoutStepViewed, ProductAdded, ProductClicked, VariantClicked, ProductViewed, ProductListViewed, CouponApplied, CouponDenied, CouponEntered, CouponRemoved, EmailCaptured, ProductListFiltered, ProductRemoved, ProductsSearched, SignedIn, SignedOut, SignedUp, LoginStarted, OrderCompleted, SubscriptionCancelled, NavigationClicked, PaymentInfoEntered } from './typewriter.js';
|
|
2
2
|
import type { Cart, Checkout, LineItem, Product } from './objects.js';
|
|
3
|
-
import type { CartInput, CheckoutInput, CheckoutStepCompletedInput, CheckoutStepViewedInput, LineItemInput, ProductInput, CartViewedInput, CheckoutStartedInput, ProductAddedInput, ProductClickedInput, VariantClickedInput, ProductViewedInput, ProductListViewedInput, ProductListFilteredInput, ProductRemovedInput, CouponAppliedInput, CouponDeniedInput, CouponEnteredInput, CouponRemovedInput, EmailCapturedInput, ProductsSearchedInput, SignedInInput, SignedOutInput, SignedUpInput, LoginStartedInput, SubscriptionCancelledInput, NavigationClickedInput, PaymentInfoEnteredInput } from './input.js';
|
|
3
|
+
import type { CartInput, CheckoutInput, CheckoutStepCompletedInput, CheckoutStepViewedInput, LineItemInput, ProductInput, CartViewedInput, CheckoutStartedInput, ProductAddedInput, ProductClickedInput, VariantClickedInput, ProductViewedInput, ProductListViewedInput, ProductListFilteredInput, ProductRemovedInput, CouponAppliedInput, CouponDeniedInput, CouponEnteredInput, CouponRemovedInput, EmailCapturedInput, ProductsSearchedInput, SignedInInput, SignedOutInput, SignedUpInput, LoginStartedInput, OrderCompletedInput, SubscriptionCancelledInput, NavigationClickedInput, PaymentInfoEnteredInput } from './input.js';
|
|
4
4
|
import type { ObjectTypes } from './client.js';
|
|
5
5
|
export type CartFormatter<T = ObjectTypes['Cart']> = (props: CartInput<T>) => Cart;
|
|
6
6
|
export type CheckoutFormatter<T = ObjectTypes['Checkout']> = (props: CheckoutInput<T>) => Checkout;
|
|
@@ -78,6 +78,9 @@ export interface NavigationClickedFormatter {
|
|
|
78
78
|
export interface PaymentInfoEnteredFormatter {
|
|
79
79
|
(props: PaymentInfoEnteredInput, event: PaymentInfoEntered): PaymentInfoEntered;
|
|
80
80
|
}
|
|
81
|
+
export interface OrderCompletedFormatter {
|
|
82
|
+
(props: OrderCompletedInput, event: OrderCompleted): OrderCompleted;
|
|
83
|
+
}
|
|
81
84
|
export interface ChordAnalyticsFormatters<T extends ObjectTypes = ObjectTypes> {
|
|
82
85
|
events?: {
|
|
83
86
|
cartViewed?: CartViewedFormatter<T>;
|
|
@@ -104,6 +107,7 @@ export interface ChordAnalyticsFormatters<T extends ObjectTypes = ObjectTypes> {
|
|
|
104
107
|
subscriptionCancelled?: SubscriptionCancelledFormatter;
|
|
105
108
|
navigationClicked?: NavigationClickedFormatter;
|
|
106
109
|
paymentInfoEntered?: PaymentInfoEnteredFormatter;
|
|
110
|
+
orderCompleted?: OrderCompletedFormatter;
|
|
107
111
|
};
|
|
108
112
|
objects: {
|
|
109
113
|
cart: CartFormatter<T['Cart']>;
|