@chordcommerce/analytics 1.16.0 → 1.17.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/client/cdp.js +17 -13
- package/dist/client/consent/index.js +3 -1
- package/dist/client/index.d.ts +14 -0
- package/dist/client/index.js +78 -9
- package/dist/setupTests.d.ts +1 -0
- package/dist/setupTests.js +4 -0
- package/dist/types/client.d.ts +21 -1
- package/package.json +2 -1
package/dist/client/cdp.js
CHANGED
|
@@ -16,6 +16,19 @@ export const addCdpSnippet = (options) => __awaiter(void 0, void 0, void 0, func
|
|
|
16
16
|
if (!document || typeof document.createElement === 'undefined')
|
|
17
17
|
return;
|
|
18
18
|
const normalizedCDPDomain = normalizeCDPDomain(options.cdpDomain);
|
|
19
|
+
// Create a promise that resolves when CDP is ready
|
|
20
|
+
const cdpReadyPromise = new Promise((resolve) => {
|
|
21
|
+
const checkCdpReady = () => {
|
|
22
|
+
const cdp = window[`_${options.namespace}`];
|
|
23
|
+
if (cdp && typeof cdp.configure === 'function') {
|
|
24
|
+
resolve();
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
setTimeout(checkCdpReady, 50);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
checkCdpReady();
|
|
31
|
+
});
|
|
19
32
|
const s = document.createElement('script');
|
|
20
33
|
s.async = true;
|
|
21
34
|
s.src = `${normalizedCDPDomain}/p.js`;
|
|
@@ -23,20 +36,11 @@ export const addCdpSnippet = (options) => __awaiter(void 0, void 0, void 0, func
|
|
|
23
36
|
s.setAttribute('data-init-only', 'true');
|
|
24
37
|
s.setAttribute('data-namespace', `_${options.namespace}`);
|
|
25
38
|
s.setAttribute('data-write-key', options.cdpWriteKey);
|
|
39
|
+
document.head.appendChild(s);
|
|
40
|
+
// Wait for CDP to be ready before setting up consent
|
|
41
|
+
yield cdpReadyPromise;
|
|
26
42
|
if (options.consent) {
|
|
27
|
-
|
|
28
|
-
if (options.awaitConsent) {
|
|
29
|
-
yield addCdpConsent(options).init();
|
|
30
|
-
document.head.appendChild(s);
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
document.head.appendChild(s);
|
|
34
|
-
// If not awaiting consent, initialize in the background
|
|
35
|
-
addCdpConsent(options).init().catch(console.error);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
document.head.appendChild(s);
|
|
43
|
+
addCdpConsent(options).init();
|
|
40
44
|
}
|
|
41
45
|
});
|
|
42
46
|
/*
|
|
@@ -68,7 +68,9 @@ export const addCdpConsent = (options) => {
|
|
|
68
68
|
const cdp = window[`_${options.namespace}`];
|
|
69
69
|
if (cdp && typeof cdp.configure === 'function') {
|
|
70
70
|
try {
|
|
71
|
-
|
|
71
|
+
if (Object.keys(updatedConsent).length > 0) {
|
|
72
|
+
cdp.configure({ privacy: updatedConsent });
|
|
73
|
+
}
|
|
72
74
|
return true;
|
|
73
75
|
}
|
|
74
76
|
catch (error) {
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
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';
|
|
2
|
+
import { AnalyticsMiddleware } from '../types/client.js';
|
|
2
3
|
export interface ChordAnalyticsSnippet {
|
|
3
4
|
_loadOptions: ChordAnalyticsOptions<ObjectTypes>;
|
|
4
5
|
invoked: boolean;
|
|
@@ -21,7 +22,19 @@ export declare class ChordAnalytics<T extends ObjectTypes = ObjectTypes> {
|
|
|
21
22
|
* Options for ChordAnalytics.
|
|
22
23
|
*/
|
|
23
24
|
options: ChordAnalyticsOptions<T>;
|
|
25
|
+
/**
|
|
26
|
+
* Middleware to be applied to the event properties
|
|
27
|
+
*/
|
|
28
|
+
middleware: any[];
|
|
29
|
+
/**
|
|
30
|
+
* Promise that resolves when CDP is ready
|
|
31
|
+
*/
|
|
32
|
+
private cdpReadyPromise;
|
|
24
33
|
constructor(options: ChordAnalyticsOptions<T>);
|
|
34
|
+
/**
|
|
35
|
+
* Initialize CDP snippet and wait for it to be ready
|
|
36
|
+
*/
|
|
37
|
+
private initializeCdp;
|
|
25
38
|
/**
|
|
26
39
|
* Set debug mode for Chord Analytics
|
|
27
40
|
* @param enabled - Whether debug mode should be enabled
|
|
@@ -52,6 +65,7 @@ export declare class ChordAnalytics<T extends ObjectTypes = ObjectTypes> {
|
|
|
52
65
|
platform: import("../types/client.js").platformMetadata;
|
|
53
66
|
store: import("../types/client.js").storeMetadata;
|
|
54
67
|
};
|
|
68
|
+
addSourceMiddleware: (func: AnalyticsMiddleware) => void;
|
|
55
69
|
/**
|
|
56
70
|
* Send a `track` event to the CDP with any event name and properties.
|
|
57
71
|
*/
|
package/dist/client/index.js
CHANGED
|
@@ -22,6 +22,14 @@ export class ChordAnalytics {
|
|
|
22
22
|
* Allows snippet.js to detect whether the snippet has started running yet.
|
|
23
23
|
*/
|
|
24
24
|
this.invoked = true;
|
|
25
|
+
/**
|
|
26
|
+
* Middleware to be applied to the event properties
|
|
27
|
+
*/
|
|
28
|
+
this.middleware = [];
|
|
29
|
+
/**
|
|
30
|
+
* Promise that resolves when CDP is ready
|
|
31
|
+
*/
|
|
32
|
+
this.cdpReadyPromise = null;
|
|
25
33
|
/**
|
|
26
34
|
* Set debug mode for Chord Analytics
|
|
27
35
|
* @param enabled - Whether debug mode should be enabled
|
|
@@ -89,14 +97,54 @@ export class ChordAnalytics {
|
|
|
89
97
|
patch: 0,
|
|
90
98
|
} });
|
|
91
99
|
};
|
|
100
|
+
// eslint-disable-next-line class-methods-use-this
|
|
101
|
+
this.addSourceMiddleware = (func) => {
|
|
102
|
+
this.middleware.push(func);
|
|
103
|
+
};
|
|
92
104
|
/**
|
|
93
105
|
* Send a `track` event to the CDP with any event name and properties.
|
|
94
106
|
*/
|
|
95
|
-
this.track = (event, props, options) => {
|
|
107
|
+
this.track = (event, props, options) => __awaiter(this, void 0, void 0, function* () {
|
|
96
108
|
if (!event)
|
|
97
109
|
this.logger('No event name provided');
|
|
110
|
+
// Wait for CDP to be ready before sending track events
|
|
111
|
+
if (this.cdpReadyPromise) {
|
|
112
|
+
yield this.cdpReadyPromise;
|
|
113
|
+
}
|
|
98
114
|
const formattedProps = this.options.stripNull && props ? pruneNullValues(props) : props;
|
|
99
|
-
|
|
115
|
+
let middlewareProps = {};
|
|
116
|
+
if (this.middleware.length > 0) {
|
|
117
|
+
const searchParams = typeof window !== 'undefined' ? window.location.search : '';
|
|
118
|
+
const urlSearchParams = new URLSearchParams(searchParams);
|
|
119
|
+
const searchData = Object.fromEntries(urlSearchParams.entries());
|
|
120
|
+
// process middleware synchronously
|
|
121
|
+
this.middleware.forEach((func) => {
|
|
122
|
+
try {
|
|
123
|
+
const result = func({
|
|
124
|
+
payload: {
|
|
125
|
+
obj: {
|
|
126
|
+
properties: props,
|
|
127
|
+
event,
|
|
128
|
+
context: {
|
|
129
|
+
page: {
|
|
130
|
+
search: searchParams,
|
|
131
|
+
searchParams: searchData,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
next: (_) => _,
|
|
137
|
+
});
|
|
138
|
+
if (result && typeof result === 'object') {
|
|
139
|
+
middlewareProps = Object.assign(Object.assign({}, middlewareProps), result);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
console.warn('Middleware error:', error);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
const finalEventProps = Object.assign(Object.assign(Object.assign({}, formattedProps), middlewareProps), { meta: this.meta() });
|
|
100
148
|
if (this.options.debug) {
|
|
101
149
|
this.validate(event, finalEventProps).forEach((valid) => {
|
|
102
150
|
if (!valid.success) {
|
|
@@ -136,11 +184,15 @@ export class ChordAnalytics {
|
|
|
136
184
|
resolve();
|
|
137
185
|
}
|
|
138
186
|
});
|
|
139
|
-
};
|
|
187
|
+
});
|
|
140
188
|
/**
|
|
141
189
|
* Send an `identify` event to the CDP with user id and traits.
|
|
142
190
|
*/
|
|
143
|
-
this.identify = (...props) => {
|
|
191
|
+
this.identify = (...props) => __awaiter(this, void 0, void 0, function* () {
|
|
192
|
+
// Wait for CDP to be ready before sending identify events
|
|
193
|
+
if (this.cdpReadyPromise) {
|
|
194
|
+
yield this.cdpReadyPromise;
|
|
195
|
+
}
|
|
144
196
|
try {
|
|
145
197
|
const identifyPromises = [];
|
|
146
198
|
const a = this.ccdp();
|
|
@@ -163,11 +215,15 @@ export class ChordAnalytics {
|
|
|
163
215
|
catch (error) {
|
|
164
216
|
this.logger(error);
|
|
165
217
|
}
|
|
166
|
-
};
|
|
218
|
+
});
|
|
167
219
|
/**
|
|
168
220
|
* Send a `page` event to the CDP.
|
|
169
221
|
*/
|
|
170
|
-
this.page = (props = {}) => {
|
|
222
|
+
this.page = (props = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
223
|
+
// Wait for CDP to be ready before sending page events
|
|
224
|
+
if (this.cdpReadyPromise) {
|
|
225
|
+
yield this.cdpReadyPromise;
|
|
226
|
+
}
|
|
171
227
|
try {
|
|
172
228
|
const pagePromises = [];
|
|
173
229
|
const a = this.ccdp();
|
|
@@ -190,7 +246,7 @@ export class ChordAnalytics {
|
|
|
190
246
|
catch (error) {
|
|
191
247
|
this.logger(error);
|
|
192
248
|
}
|
|
193
|
-
};
|
|
249
|
+
});
|
|
194
250
|
this.reset = () => {
|
|
195
251
|
try {
|
|
196
252
|
const resetPromises = [];
|
|
@@ -609,12 +665,25 @@ export class ChordAnalytics {
|
|
|
609
665
|
enableLogging: debug,
|
|
610
666
|
namespace: 'chord',
|
|
611
667
|
stripNull: true,
|
|
612
|
-
awaitConsent: true,
|
|
613
668
|
};
|
|
614
669
|
this.options = Object.assign(Object.assign({}, defaults), options);
|
|
615
670
|
if (((_b = this.options) === null || _b === void 0 ? void 0 : _b.cdpDomain) && ((_c = this.options) === null || _c === void 0 ? void 0 : _c.cdpWriteKey) && window) {
|
|
616
671
|
window[this.options.namespace] = (window === null || window === void 0 ? void 0 : window[this.options.namespace]) || this;
|
|
617
|
-
|
|
672
|
+
this.initializeCdp();
|
|
618
673
|
}
|
|
619
674
|
}
|
|
675
|
+
/**
|
|
676
|
+
* Initialize CDP snippet and wait for it to be ready
|
|
677
|
+
*/
|
|
678
|
+
initializeCdp() {
|
|
679
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
680
|
+
try {
|
|
681
|
+
this.cdpReadyPromise = addCdpSnippet(this.options);
|
|
682
|
+
yield this.cdpReadyPromise;
|
|
683
|
+
}
|
|
684
|
+
catch (error) {
|
|
685
|
+
console.error('CDP initialization failed:', error);
|
|
686
|
+
}
|
|
687
|
+
});
|
|
688
|
+
}
|
|
620
689
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/types/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnalyticsSnippet, Analytics, AnalyticsBrowser, Options } from '@segment/analytics-next';
|
|
1
|
+
import type { EventProperties, AnalyticsSnippet, Analytics, AnalyticsBrowser, Options } from '@segment/analytics-next';
|
|
2
2
|
import { ChordAnalyticsFormatters } from './formatters.js';
|
|
3
3
|
export interface ValidateResult {
|
|
4
4
|
success: boolean;
|
|
@@ -39,6 +39,7 @@ export interface ChordAnalyticsOptions<T extends ObjectTypes = ObjectTypes> {
|
|
|
39
39
|
stripNull?: boolean;
|
|
40
40
|
metadata: EventMetadata;
|
|
41
41
|
awaitConsentTimeout?: number;
|
|
42
|
+
middleware?: Array<() => void>;
|
|
42
43
|
}
|
|
43
44
|
export interface EventMetadata {
|
|
44
45
|
i18n: i18nMetadata;
|
|
@@ -74,3 +75,22 @@ export type ChordAnalyticsQueue = {
|
|
|
74
75
|
page: (...args: any[]) => void;
|
|
75
76
|
reset: (...args: any[]) => void;
|
|
76
77
|
};
|
|
78
|
+
type PageContext = {
|
|
79
|
+
search: string;
|
|
80
|
+
searchParams: Record<string, string>;
|
|
81
|
+
};
|
|
82
|
+
type MiddlewarePayload = {
|
|
83
|
+
obj: {
|
|
84
|
+
properties?: EventProperties;
|
|
85
|
+
event: string;
|
|
86
|
+
context: {
|
|
87
|
+
page: PageContext;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
type MiddlewareArgs = {
|
|
92
|
+
payload: MiddlewarePayload;
|
|
93
|
+
next: <T>(arg: T) => T;
|
|
94
|
+
};
|
|
95
|
+
export type AnalyticsMiddleware = (args: MiddlewareArgs) => Partial<EventProperties> | void;
|
|
96
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chordcommerce/analytics",
|
|
3
3
|
"description": "Chord Commerce event tracking",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.17.0",
|
|
5
5
|
"author": "Chord Commerce <help@chord.co> (https://www.chord.co)",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"clean": "rimraf dist",
|
|
19
19
|
"test": "jest",
|
|
20
20
|
"test:watch": "jest --watch",
|
|
21
|
+
"test:file": "NODE_OPTIONS=--experimental-vm-modules jest",
|
|
21
22
|
"test:ci": "yarn test --ci --runInBand --reporters=default --passWithNoTests",
|
|
22
23
|
"zod": "yarn ts-to-zod src/types/typewriter.ts src/validators/tracking-plan.ts && yarn ts-to-zod src/types/objects.ts src/validators/objects.ts"
|
|
23
24
|
},
|