@salesforcedevs/dx-components 1.37.2 → 1.38.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/lwc.config.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforcedevs/dx-components",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.38.0",
|
|
4
4
|
"description": "DX Lightning web components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -44,5 +44,5 @@
|
|
|
44
44
|
"luxon": "3.4.4",
|
|
45
45
|
"msw": "^2.12.4"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "fc9d953dd79b76e37578fc43691fa56d6c4dd028"
|
|
48
48
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<template></template>
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { LightningElement, api } from "lwc";
|
|
2
|
+
import {
|
|
3
|
+
TRACKING_EVENT_NAME as DX_TRACKING_EVENT_NAME,
|
|
4
|
+
LISTENER_QUEUE as DX_LISTENER_QUEUE,
|
|
5
|
+
LISTENER_INDICATOR as DX_LISTENER_INDICATOR,
|
|
6
|
+
track as dxTrack
|
|
7
|
+
} from "dxUtils/analytics";
|
|
8
|
+
|
|
9
|
+
// Architect ("architectssite_track") namespace. These mirror the constants used
|
|
10
|
+
// by <arch-instrumentation> in @salesforcedevs/arch-components. They are declared
|
|
11
|
+
// locally rather than imported because dx-components does not depend on
|
|
12
|
+
// arch-components.
|
|
13
|
+
const ARCH_TRACKING_EVENT_NAME = "architectssite_track";
|
|
14
|
+
const ARCH_LISTENER_QUEUE = "__TDS_INSTRUMENTATION_QUEUE__";
|
|
15
|
+
const ARCH_LISTENER_INDICATOR = "__TDS_INSTRUMENTATION_IS_INITIALIZED__";
|
|
16
|
+
|
|
17
|
+
// Arch-namespace equivalent of dxUtils/analytics `track`: either dispatch the
|
|
18
|
+
// architect tracking event (once the listener is mounted) or queue it. Used to
|
|
19
|
+
// replay events that were queued in __TDS_INSTRUMENTATION_QUEUE__ before this
|
|
20
|
+
// component mounted.
|
|
21
|
+
function archTrack(
|
|
22
|
+
element: EventTarget,
|
|
23
|
+
event: string,
|
|
24
|
+
payload: Record<string, unknown>
|
|
25
|
+
): void {
|
|
26
|
+
const detail = { event, payload };
|
|
27
|
+
if ((window as any)[ARCH_LISTENER_INDICATOR] === undefined) {
|
|
28
|
+
(window as any)[ARCH_LISTENER_QUEUE] =
|
|
29
|
+
(window as any)[ARCH_LISTENER_QUEUE] || [];
|
|
30
|
+
(window as any)[ARCH_LISTENER_QUEUE].push(detail);
|
|
31
|
+
} else {
|
|
32
|
+
const e = new CustomEvent(ARCH_TRACKING_EVENT_NAME, {
|
|
33
|
+
bubbles: true,
|
|
34
|
+
composed: true,
|
|
35
|
+
detail
|
|
36
|
+
});
|
|
37
|
+
element.dispatchEvent(e);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const googleTagManager = {
|
|
42
|
+
track: function (e: Event) {
|
|
43
|
+
if ((window as any).dataLayer === undefined) {
|
|
44
|
+
(window as any).dataLayer = [];
|
|
45
|
+
}
|
|
46
|
+
const { event, payload } = (e as CustomEvent).detail;
|
|
47
|
+
(window as any).dataLayer.push({ ...payload, event });
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
interface TrackEventListener {
|
|
52
|
+
add: () => void;
|
|
53
|
+
remove: () => void;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Attaches a listener for BOTH the developer (`developerwebsite_track`) and
|
|
58
|
+
* architect (`architectssite_track`) tracking events, forwarding each caught
|
|
59
|
+
* event to every tracker function. A single component can therefore bridge both
|
|
60
|
+
* event namespaces into the dataLayer.
|
|
61
|
+
*/
|
|
62
|
+
export function instrumentationTrackEventListener(
|
|
63
|
+
trackerFns: { track: (e: Event) => void }[] = []
|
|
64
|
+
): TrackEventListener {
|
|
65
|
+
if (trackerFns.length === 0) {
|
|
66
|
+
throw new Error("No tracker functions passed");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const handleTrackEvent = (e: Event) => {
|
|
70
|
+
trackerFns.forEach((tracker) => {
|
|
71
|
+
tracker.track(e);
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const attachEventListener = () => {
|
|
76
|
+
document.addEventListener(DX_TRACKING_EVENT_NAME, handleTrackEvent);
|
|
77
|
+
document.addEventListener(ARCH_TRACKING_EVENT_NAME, handleTrackEvent);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const removeEventListener = () => {
|
|
81
|
+
document.removeEventListener(DX_TRACKING_EVENT_NAME, handleTrackEvent);
|
|
82
|
+
document.removeEventListener(
|
|
83
|
+
ARCH_TRACKING_EVENT_NAME,
|
|
84
|
+
handleTrackEvent
|
|
85
|
+
);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
add: attachEventListener,
|
|
90
|
+
remove: removeEventListener
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Unified instrumentation bridge. Mount a single <dx-instrumentation> to forward
|
|
96
|
+
* both developer-website and architect-website tracking events into the GTM
|
|
97
|
+
* dataLayer — replacing the need to mount <dw-instrumentation> and
|
|
98
|
+
* <arch-instrumentation> separately. Renders nothing.
|
|
99
|
+
*/
|
|
100
|
+
export default class Instrumentation extends LightningElement {
|
|
101
|
+
@api useGoogleTagManager = false;
|
|
102
|
+
|
|
103
|
+
private tracker: TrackEventListener | null = null;
|
|
104
|
+
|
|
105
|
+
private setupTracker() {
|
|
106
|
+
const trackerFunctions = this.useGoogleTagManager
|
|
107
|
+
? [googleTagManager]
|
|
108
|
+
: [];
|
|
109
|
+
this.tracker = instrumentationTrackEventListener(trackerFunctions);
|
|
110
|
+
this.tracker.add();
|
|
111
|
+
// Mark both namespaces initialized so track() calls from either the
|
|
112
|
+
// developer or architect stacks dispatch live events instead of queueing.
|
|
113
|
+
(window as any)[DX_LISTENER_INDICATOR] = true;
|
|
114
|
+
(window as any)[ARCH_LISTENER_INDICATOR] = true;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private dispatchQueuedEvents() {
|
|
118
|
+
const dxQueue = (window as any)[DX_LISTENER_QUEUE];
|
|
119
|
+
if (Array.isArray(dxQueue)) {
|
|
120
|
+
while (dxQueue.length > 0) {
|
|
121
|
+
const event = dxQueue.pop() as {
|
|
122
|
+
event: string;
|
|
123
|
+
payload: Record<string, unknown>;
|
|
124
|
+
};
|
|
125
|
+
dxTrack(this, event.event, event.payload);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const archQueue = (window as any)[ARCH_LISTENER_QUEUE];
|
|
130
|
+
if (Array.isArray(archQueue)) {
|
|
131
|
+
while (archQueue.length > 0) {
|
|
132
|
+
const event = archQueue.pop() as {
|
|
133
|
+
event: string;
|
|
134
|
+
payload: Record<string, unknown>;
|
|
135
|
+
};
|
|
136
|
+
archTrack(this, event.event, event.payload);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
renderedCallback() {
|
|
142
|
+
if (this.tracker === null) {
|
|
143
|
+
this.setupTracker();
|
|
144
|
+
this.dispatchQueuedEvents();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
disconnectedCallback() {
|
|
149
|
+
if (this.tracker !== null) {
|
|
150
|
+
this.tracker.remove();
|
|
151
|
+
this.tracker = null;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|