@encatch/web-sdk 0.0.35-beta.8 â 1.0.0-beta.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/README.md +140 -638
- package/dist/encatch.es.js +2 -0
- package/dist/encatch.es.js.map +1 -0
- package/dist/encatch.iife.js +2 -0
- package/dist/encatch.iife.js.map +1 -0
- package/dist/index.d.ts +191 -0
- package/package.json +32 -50
- package/dist-sdk/plugin/sdk/core-wrapper-BMvOyc0u.js +0 -22926
- package/dist-sdk/plugin/sdk/module-DC2Edddk.js +0 -481
- package/dist-sdk/plugin/sdk/module.js +0 -5
- package/dist-sdk/plugin/sdk/preview-sdk.html +0 -1182
- package/dist-sdk/plugin/sdk/vite.svg +0 -15
- package/dist-sdk/plugin/sdk/web-form-engine-core.css +0 -1
- package/index.d.ts +0 -207
- package/src/@types/encatch-type.ts +0 -111
- package/src/encatch-instance.ts +0 -161
- package/src/feedback-api-types.ts +0 -18
- package/src/hooks/useDevice.ts +0 -30
- package/src/hooks/useFeedbackInterval.ts +0 -71
- package/src/hooks/useFeedbackTriggers.ts +0 -342
- package/src/hooks/useFetchElligibleFeedbackConfiguration.ts +0 -363
- package/src/hooks/useFetchFeedbackConfigurationDetails.ts +0 -92
- package/src/hooks/usePageChangeTracker.ts +0 -88
- package/src/hooks/usePrepopulatedAnswers.ts +0 -123
- package/src/hooks/useRefineTextForm.ts +0 -55
- package/src/hooks/useSubmitFeedbackForm.ts +0 -134
- package/src/hooks/useUserSession.ts +0 -53
- package/src/module.tsx +0 -428
- package/src/store/formResponses.ts +0 -211
- package/src/utils/browser-details.ts +0 -36
- package/src/utils/duration-utils.ts +0 -158
- package/src/utils/feedback-frequency-storage.ts +0 -214
- package/src/utils/feedback-storage.ts +0 -166
|
@@ -1,1182 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>Encatch SDK Preview</title>
|
|
7
|
-
<!-- Load the custom element script -->
|
|
8
|
-
<!-- <script type="module" src="./embedded.js"></script> -->
|
|
9
|
-
<link rel="stylesheet" href="preview-sdk.css" />
|
|
10
|
-
<style>
|
|
11
|
-
body {
|
|
12
|
-
font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
|
|
13
|
-
Roboto, sans-serif;
|
|
14
|
-
margin: 0;
|
|
15
|
-
padding: 20px;
|
|
16
|
-
background: black;
|
|
17
|
-
min-height: 100vh;
|
|
18
|
-
overflow-x: hidden;
|
|
19
|
-
overflow-y: auto;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.container {
|
|
23
|
-
max-width: 1400px;
|
|
24
|
-
margin: 0 auto;
|
|
25
|
-
padding-bottom: 2rem;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
.header {
|
|
29
|
-
text-align: center;
|
|
30
|
-
color: white;
|
|
31
|
-
margin-bottom: 2rem;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.header h1 {
|
|
35
|
-
font-size: 2.5rem;
|
|
36
|
-
margin: 0;
|
|
37
|
-
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.header p {
|
|
41
|
-
font-size: 1.2rem;
|
|
42
|
-
opacity: 0.9;
|
|
43
|
-
margin: 0.5rem 0;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.controls {
|
|
47
|
-
display: grid;
|
|
48
|
-
grid-template-columns: 1fr 1fr 1fr;
|
|
49
|
-
gap: 2rem;
|
|
50
|
-
margin-bottom: 2rem;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
.card {
|
|
54
|
-
background: rgba(255, 255, 255, 0.95);
|
|
55
|
-
backdrop-filter: blur(10px);
|
|
56
|
-
border-radius: 12px;
|
|
57
|
-
padding: 1.5rem;
|
|
58
|
-
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
59
|
-
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.card h3 {
|
|
63
|
-
margin: 0 0 1rem 0;
|
|
64
|
-
color: #333;
|
|
65
|
-
font-size: 1.3rem;
|
|
66
|
-
border-bottom: 2px solid #667eea;
|
|
67
|
-
padding-bottom: 0.5rem;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.column {
|
|
71
|
-
display: flex;
|
|
72
|
-
flex-direction: column;
|
|
73
|
-
gap: 1rem;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
select,
|
|
77
|
-
input,
|
|
78
|
-
textarea {
|
|
79
|
-
padding: 0.75rem 1rem;
|
|
80
|
-
border: 2px solid #e1e5e9;
|
|
81
|
-
border-radius: 8px;
|
|
82
|
-
font-size: 0.95rem;
|
|
83
|
-
background: white;
|
|
84
|
-
color: #333;
|
|
85
|
-
transition: all 0.3s ease;
|
|
86
|
-
width: 100%;
|
|
87
|
-
box-sizing: border-box;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
select:focus,
|
|
91
|
-
input:focus,
|
|
92
|
-
textarea:focus {
|
|
93
|
-
outline: none;
|
|
94
|
-
border-color: #667eea;
|
|
95
|
-
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
button {
|
|
99
|
-
padding: 0.75rem 1.5rem;
|
|
100
|
-
border: none;
|
|
101
|
-
border-radius: 8px;
|
|
102
|
-
font-size: 1rem;
|
|
103
|
-
font-weight: 600;
|
|
104
|
-
cursor: pointer;
|
|
105
|
-
background: black;
|
|
106
|
-
color: white;
|
|
107
|
-
transition: all 0.3s ease;
|
|
108
|
-
width: 100%;
|
|
109
|
-
text-transform: uppercase;
|
|
110
|
-
letter-spacing: 0.5px;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
button:hover {
|
|
114
|
-
transform: translateY(-2px);
|
|
115
|
-
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
button:active {
|
|
119
|
-
transform: translateY(0);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
.examples {
|
|
123
|
-
background: rgba(255, 255, 255, 0.95);
|
|
124
|
-
backdrop-filter: blur(10px);
|
|
125
|
-
border-radius: 12px;
|
|
126
|
-
padding: 1.5rem;
|
|
127
|
-
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
128
|
-
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
129
|
-
margin-top: 2rem;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
.examples h3 {
|
|
133
|
-
margin: 0 0 1rem 0;
|
|
134
|
-
color: #333;
|
|
135
|
-
font-size: 1.3rem;
|
|
136
|
-
border-bottom: 2px solid #667eea;
|
|
137
|
-
padding-bottom: 0.5rem;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
.example-grid {
|
|
141
|
-
display: grid;
|
|
142
|
-
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
143
|
-
gap: 1rem;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
.example-item {
|
|
147
|
-
background: #f8f9fa;
|
|
148
|
-
border-radius: 8px;
|
|
149
|
-
padding: 1rem;
|
|
150
|
-
border: 1px solid #e9ecef;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
.example-item h4 {
|
|
154
|
-
margin: 0 0 0.5rem 0;
|
|
155
|
-
color: #495057;
|
|
156
|
-
font-size: 0.9rem;
|
|
157
|
-
font-weight: 600;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.example-code {
|
|
161
|
-
background: #2d3748;
|
|
162
|
-
color: #e2e8f0;
|
|
163
|
-
padding: 0.75rem;
|
|
164
|
-
border-radius: 6px;
|
|
165
|
-
font-family: "Monaco", "Menlo", monospace;
|
|
166
|
-
font-size: 0.85rem;
|
|
167
|
-
overflow-x: auto;
|
|
168
|
-
cursor: pointer;
|
|
169
|
-
transition: all 0.2s ease;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
.example-code:hover {
|
|
173
|
-
background: #4a5568;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
.copy-btn {
|
|
177
|
-
background: #28a745;
|
|
178
|
-
color: white;
|
|
179
|
-
border: none;
|
|
180
|
-
padding: 0.25rem 0.5rem;
|
|
181
|
-
border-radius: 4px;
|
|
182
|
-
font-size: 0.75rem;
|
|
183
|
-
cursor: pointer;
|
|
184
|
-
margin-top: 0.5rem;
|
|
185
|
-
width: auto;
|
|
186
|
-
text-transform: none;
|
|
187
|
-
letter-spacing: normal;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
.copy-btn:hover {
|
|
191
|
-
background: #218838;
|
|
192
|
-
transform: none;
|
|
193
|
-
box-shadow: none;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
.tabs {
|
|
197
|
-
display: flex;
|
|
198
|
-
background: rgba(255, 255, 255, 0.1);
|
|
199
|
-
border-radius: 8px;
|
|
200
|
-
padding: 4px;
|
|
201
|
-
margin-bottom: 1rem;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
.tab {
|
|
205
|
-
flex: 1;
|
|
206
|
-
background: transparent;
|
|
207
|
-
border: none;
|
|
208
|
-
padding: 0.5rem 1rem;
|
|
209
|
-
border-radius: 6px;
|
|
210
|
-
color: rgba(255, 255, 255, 0.7);
|
|
211
|
-
cursor: pointer;
|
|
212
|
-
transition: all 0.3s ease;
|
|
213
|
-
font-weight: 500;
|
|
214
|
-
text-transform: none;
|
|
215
|
-
letter-spacing: normal;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
.tab.active {
|
|
219
|
-
background: white;
|
|
220
|
-
color: #333;
|
|
221
|
-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
.tab-content {
|
|
225
|
-
display: none;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
.tab-content.active {
|
|
229
|
-
display: block;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
@media (max-width: 1200px) {
|
|
233
|
-
.controls {
|
|
234
|
-
grid-template-columns: 1fr 1fr;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
@media (max-width: 768px) {
|
|
239
|
-
.controls {
|
|
240
|
-
grid-template-columns: 1fr;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
.example-grid {
|
|
244
|
-
grid-template-columns: 1fr;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
</style>
|
|
248
|
-
</head>
|
|
249
|
-
<body>
|
|
250
|
-
<div class="container">
|
|
251
|
-
<div class="header">
|
|
252
|
-
<h1>đ Encatch SDK Testing Console</h1>
|
|
253
|
-
<p>Test feedback triggers, user identification, and event tracking</p>
|
|
254
|
-
</div>
|
|
255
|
-
|
|
256
|
-
<div class="controls">
|
|
257
|
-
<!-- Feedback Controls Card -->
|
|
258
|
-
<div class="card">
|
|
259
|
-
<h3>đ Feedback Controls</h3>
|
|
260
|
-
<div class="column">
|
|
261
|
-
<select id="languageSelect">
|
|
262
|
-
<option value="en">đēđ¸ English</option>
|
|
263
|
-
<option value="es">đĒđ¸ Spanish</option>
|
|
264
|
-
<option value="fr">đĢđˇ French</option>
|
|
265
|
-
<option value="de">đŠđĒ German</option>
|
|
266
|
-
<option value="zh">đ¨đŗ Chinese</option>
|
|
267
|
-
<option value="hi">đŽđŗ Hindi</option>
|
|
268
|
-
</select>
|
|
269
|
-
<select id="themeSelect">
|
|
270
|
-
<option value="light">âī¸ Light Theme</option>
|
|
271
|
-
<option value="dark">đ Dark Theme</option>
|
|
272
|
-
</select>
|
|
273
|
-
<input
|
|
274
|
-
type="text"
|
|
275
|
-
id="feedbackId"
|
|
276
|
-
placeholder="Feedback ID"
|
|
277
|
-
value="019865a4-d7f5-79a0-9183-bb1416143b5e"
|
|
278
|
-
/>
|
|
279
|
-
<input
|
|
280
|
-
type="text"
|
|
281
|
-
id="feedbackName"
|
|
282
|
-
placeholder="Feedback Name"
|
|
283
|
-
value="Long and Short answer Test"
|
|
284
|
-
/>
|
|
285
|
-
<textarea
|
|
286
|
-
id="customPropertiesTextarea"
|
|
287
|
-
placeholder="Custom Properties (JSON)"
|
|
288
|
-
rows="4"
|
|
289
|
-
style="resize: vertical; font-family: monospace"
|
|
290
|
-
></textarea>
|
|
291
|
-
<textarea
|
|
292
|
-
id="prepopulatedAnswersTextarea"
|
|
293
|
-
placeholder="Prepopulated Answers (JSON)"
|
|
294
|
-
rows="4"
|
|
295
|
-
style="resize: vertical; font-family: monospace"
|
|
296
|
-
></textarea>
|
|
297
|
-
<button id="openPopupById">Open by ID</button>
|
|
298
|
-
<button id="openPopupByName">Open by Name</button>
|
|
299
|
-
</div>
|
|
300
|
-
</div>
|
|
301
|
-
|
|
302
|
-
<!-- SDK Control-->
|
|
303
|
-
<div class="card">
|
|
304
|
-
<h3>đ SDK Control</h3>
|
|
305
|
-
<div class="column">
|
|
306
|
-
<div style="background: #f8f9fa; padding: 1rem; border-radius: 6px; margin-bottom: 1rem;">
|
|
307
|
-
<strong>Current Session ID:</strong>
|
|
308
|
-
<div id="sessionStatus" style="font-family: monospace; color: #666; margin-top: 0.5rem; word-break: break-all;">
|
|
309
|
-
No session active
|
|
310
|
-
</div>
|
|
311
|
-
</div>
|
|
312
|
-
<button id="startSessionBtn">đ Start SDK (Enable AutoStart)</button>
|
|
313
|
-
<button id="stopSessionBtn">âšī¸ Stop SDK</button>
|
|
314
|
-
<button id="resetSessionBtn">đ Make User Anonymous</button>
|
|
315
|
-
<button id="checkSessionBtn">đ Check Session Status</button>
|
|
316
|
-
</div>
|
|
317
|
-
</div>
|
|
318
|
-
|
|
319
|
-
<!-- Event Tracking Card -->
|
|
320
|
-
<div class="card">
|
|
321
|
-
<h3>đ Event Tracking</h3>
|
|
322
|
-
<div class="column">
|
|
323
|
-
<input
|
|
324
|
-
type="text"
|
|
325
|
-
id="eventName"
|
|
326
|
-
placeholder="Event Name"
|
|
327
|
-
value="customEvent"
|
|
328
|
-
/>
|
|
329
|
-
<textarea
|
|
330
|
-
id="eventProperties"
|
|
331
|
-
placeholder="Event Properties JSON"
|
|
332
|
-
rows="4"
|
|
333
|
-
style="resize: vertical; font-family: monospace"
|
|
334
|
-
>
|
|
335
|
-
{
|
|
336
|
-
"timestamp": "2024-01-15T10:30:00Z",
|
|
337
|
-
"source": "manual_trigger",
|
|
338
|
-
"trackEvent": "trackEvent",
|
|
339
|
-
"userId": "12345"
|
|
340
|
-
}</textarea
|
|
341
|
-
>
|
|
342
|
-
<button id="trackEventBtn">đ¯ Track Event</button>
|
|
343
|
-
</div>
|
|
344
|
-
</div>
|
|
345
|
-
|
|
346
|
-
<!-- User Identification Card -->
|
|
347
|
-
<div class="card">
|
|
348
|
-
<h3>đ¤ User Identification</h3>
|
|
349
|
-
<div class="tabs">
|
|
350
|
-
<button class="tab active" onclick="switchTab('simple')">
|
|
351
|
-
Simple
|
|
352
|
-
</button>
|
|
353
|
-
<button class="tab" onclick="switchTab('json')">JSON</button>
|
|
354
|
-
</div>
|
|
355
|
-
|
|
356
|
-
<!-- Simple Tab -->
|
|
357
|
-
<div id="simple-tab" class="tab-content active">
|
|
358
|
-
<div class="column">
|
|
359
|
-
<input
|
|
360
|
-
type="text"
|
|
361
|
-
id="userName"
|
|
362
|
-
placeholder="User Name"
|
|
363
|
-
value="test@test.com"
|
|
364
|
-
/>
|
|
365
|
-
<input type="text" id="email" placeholder="Email" value="" />
|
|
366
|
-
<input type="text" id="phone" placeholder="Phone" value="" />
|
|
367
|
-
<input type="text" id="name" placeholder="Name" value="" />
|
|
368
|
-
<input type="text" id="age" placeholder="Age" value="" />
|
|
369
|
-
<input
|
|
370
|
-
type="text"
|
|
371
|
-
id="setFields"
|
|
372
|
-
placeholder="$set fields (comma separated)"
|
|
373
|
-
value=""
|
|
374
|
-
/>
|
|
375
|
-
<input
|
|
376
|
-
type="text"
|
|
377
|
-
id="setOnceFields"
|
|
378
|
-
placeholder="$set_once fields (comma separated)"
|
|
379
|
-
value=""
|
|
380
|
-
/>
|
|
381
|
-
<input
|
|
382
|
-
type="text"
|
|
383
|
-
id="counterName"
|
|
384
|
-
placeholder="$counter name"
|
|
385
|
-
value="feedbackCount"
|
|
386
|
-
/>
|
|
387
|
-
<input
|
|
388
|
-
type="text"
|
|
389
|
-
id="counterValue"
|
|
390
|
-
placeholder="$counter value"
|
|
391
|
-
value="1"
|
|
392
|
-
/>
|
|
393
|
-
<input
|
|
394
|
-
type="text"
|
|
395
|
-
id="unsetFields"
|
|
396
|
-
placeholder="$unset fields (comma separated)"
|
|
397
|
-
value=""
|
|
398
|
-
/>
|
|
399
|
-
<button id="identifyUserSimple">đ¤ Set User (Simple)</button>
|
|
400
|
-
</div>
|
|
401
|
-
</div>
|
|
402
|
-
|
|
403
|
-
<!-- JSON Tab -->
|
|
404
|
-
<div id="json-tab" class="tab-content">
|
|
405
|
-
<div class="column">
|
|
406
|
-
<input
|
|
407
|
-
type="text"
|
|
408
|
-
id="userNameJson"
|
|
409
|
-
placeholder="User Name"
|
|
410
|
-
value="test@test.com"
|
|
411
|
-
/>
|
|
412
|
-
<textarea
|
|
413
|
-
id="identifyPayload"
|
|
414
|
-
placeholder="User Payload JSON"
|
|
415
|
-
rows="8"
|
|
416
|
-
style="resize: vertical; font-family: monospace"
|
|
417
|
-
>
|
|
418
|
-
{
|
|
419
|
-
"email": "user@example.com",
|
|
420
|
-
"name": "John Doe",
|
|
421
|
-
"age": 30,
|
|
422
|
-
"$set": {
|
|
423
|
-
"email": "user@example.com",
|
|
424
|
-
"name": "John Doe"
|
|
425
|
-
},
|
|
426
|
-
"$set_once": {
|
|
427
|
-
"first_login": "2024-01-01T00:00:00Z",
|
|
428
|
-
"signup_date": "2024-01-01"
|
|
429
|
-
},
|
|
430
|
-
"$counter": {
|
|
431
|
-
"loginCount": 1,
|
|
432
|
-
"feedbackCount": 1
|
|
433
|
-
},
|
|
434
|
-
"$unset": ["old_field", "deprecated_prop"]
|
|
435
|
-
}</textarea
|
|
436
|
-
>
|
|
437
|
-
<button id="identifyUserJson">đ¤ Set User (JSON)</button>
|
|
438
|
-
</div>
|
|
439
|
-
</div>
|
|
440
|
-
</div>
|
|
441
|
-
</div>
|
|
442
|
-
|
|
443
|
-
<!-- Fetched Feedbacks Section -->
|
|
444
|
-
<div class="examples" style="margin-top: 2rem;">
|
|
445
|
-
<h3>đĻ Available Feedbacks (from Session Storage)</h3>
|
|
446
|
-
<div style="background: #f8f9fa; padding: 1rem; border-radius: 6px; margin-bottom: 1rem;">
|
|
447
|
-
<p style="margin: 0 0 0.5rem 0; color: #666; font-size: 0.9rem;">
|
|
448
|
-
Click on any feedback ID or name to copy and auto-fill the input fields above
|
|
449
|
-
</p>
|
|
450
|
-
<div style="display: flex; gap: 0.5rem;">
|
|
451
|
-
<button
|
|
452
|
-
onclick="displayFeedbacks()"
|
|
453
|
-
style="padding: 0.5rem 1rem; background: #667eea; color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 0.9rem;"
|
|
454
|
-
>
|
|
455
|
-
đ Refresh Display
|
|
456
|
-
</button>
|
|
457
|
-
<button
|
|
458
|
-
onclick="clearSessionStorage()"
|
|
459
|
-
style="padding: 0.5rem 1rem; background: #dc3545; color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 0.9rem;"
|
|
460
|
-
>
|
|
461
|
-
đī¸ Clear Session Storage
|
|
462
|
-
</button>
|
|
463
|
-
</div>
|
|
464
|
-
</div>
|
|
465
|
-
<div id="feedbacksList" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); gap: 1rem;">
|
|
466
|
-
<div style="background: #f8f9fa; padding: 1rem; border-radius: 6px; text-align: center; color: #666;">
|
|
467
|
-
Loading feedbacks from session storage...
|
|
468
|
-
</div>
|
|
469
|
-
</div>
|
|
470
|
-
</div>
|
|
471
|
-
|
|
472
|
-
<!-- Examples Section -->
|
|
473
|
-
<div class="examples">
|
|
474
|
-
<h3>đ Copy-Paste Examples</h3>
|
|
475
|
-
<div class="example-grid">
|
|
476
|
-
<div class="example-item">
|
|
477
|
-
<h4>đ¯ Basic Event Properties</h4>
|
|
478
|
-
<div class="example-code" onclick="copyToClipboard(this)">
|
|
479
|
-
{ "timestamp": "2024-01-15T10:30:00Z", "source": "button_click",
|
|
480
|
-
"page": "/dashboard", "userId": "user123" }
|
|
481
|
-
</div>
|
|
482
|
-
<button
|
|
483
|
-
class="copy-btn"
|
|
484
|
-
onclick="copyToClipboard(this.previousElementSibling)"
|
|
485
|
-
>
|
|
486
|
-
đ Copy
|
|
487
|
-
</button>
|
|
488
|
-
</div>
|
|
489
|
-
|
|
490
|
-
<div class="example-item">
|
|
491
|
-
<h4>đĒ E-commerce Event</h4>
|
|
492
|
-
<div class="example-code" onclick="copyToClipboard(this)">
|
|
493
|
-
{ "productId": "prod_123", "productName": "Premium Plan", "price":
|
|
494
|
-
99.99, "currency": "USD", "category": "subscription" }
|
|
495
|
-
</div>
|
|
496
|
-
<button
|
|
497
|
-
class="copy-btn"
|
|
498
|
-
onclick="copyToClipboard(this.previousElementSibling)"
|
|
499
|
-
>
|
|
500
|
-
đ Copy
|
|
501
|
-
</button>
|
|
502
|
-
</div>
|
|
503
|
-
|
|
504
|
-
<div class="example-item">
|
|
505
|
-
<h4>đ¤ Basic User Properties</h4>
|
|
506
|
-
<div class="example-code" onclick="copyToClipboard(this)">
|
|
507
|
-
{ "email": "user@example.com", "name": "John Doe", "age": 30,
|
|
508
|
-
"plan": "premium", "signup_date": "2024-01-01" }
|
|
509
|
-
</div>
|
|
510
|
-
<button
|
|
511
|
-
class="copy-btn"
|
|
512
|
-
onclick="copyToClipboard(this.previousElementSibling)"
|
|
513
|
-
>
|
|
514
|
-
đ Copy
|
|
515
|
-
</button>
|
|
516
|
-
</div>
|
|
517
|
-
|
|
518
|
-
<div class="example-item">
|
|
519
|
-
<h4>đ§ $set Operation</h4>
|
|
520
|
-
<div class="example-code" onclick="copyToClipboard(this)">
|
|
521
|
-
{ "$set": { "email": "newemail@example.com", "last_login":
|
|
522
|
-
"2024-01-15T10:30:00Z", "subscription_status": "active",
|
|
523
|
-
"preferences": { "theme": "dark", "notifications": true } } }
|
|
524
|
-
</div>
|
|
525
|
-
<button
|
|
526
|
-
class="copy-btn"
|
|
527
|
-
onclick="copyToClipboard(this.previousElementSibling)"
|
|
528
|
-
>
|
|
529
|
-
đ Copy
|
|
530
|
-
</button>
|
|
531
|
-
</div>
|
|
532
|
-
|
|
533
|
-
<div class="example-item">
|
|
534
|
-
<h4>đ¯ $set_once Operation</h4>
|
|
535
|
-
<div class="example-code" onclick="copyToClipboard(this)">
|
|
536
|
-
{ "$set_once": { "first_login": "2024-01-01T00:00:00Z",
|
|
537
|
-
"signup_source": "google_ads", "referrer": "https://google.com",
|
|
538
|
-
"initial_plan": "free" } }
|
|
539
|
-
</div>
|
|
540
|
-
<button
|
|
541
|
-
class="copy-btn"
|
|
542
|
-
onclick="copyToClipboard(this.previousElementSibling)"
|
|
543
|
-
>
|
|
544
|
-
đ Copy
|
|
545
|
-
</button>
|
|
546
|
-
</div>
|
|
547
|
-
|
|
548
|
-
<div class="example-item">
|
|
549
|
-
<h4>đ $counter Operation</h4>
|
|
550
|
-
<div class="example-code" onclick="copyToClipboard(this)">
|
|
551
|
-
{ "$counter": { "loginCount": 1, "pageViews": 5,
|
|
552
|
-
"feedbackSubmitted": 1, "totalPurchases": 2, "supportTickets": 1 }
|
|
553
|
-
}
|
|
554
|
-
</div>
|
|
555
|
-
<button
|
|
556
|
-
class="copy-btn"
|
|
557
|
-
onclick="copyToClipboard(this.previousElementSibling)"
|
|
558
|
-
>
|
|
559
|
-
đ Copy
|
|
560
|
-
</button>
|
|
561
|
-
</div>
|
|
562
|
-
|
|
563
|
-
<div class="example-item">
|
|
564
|
-
<h4>đī¸ $unset Operation</h4>
|
|
565
|
-
<div class="example-code" onclick="copyToClipboard(this)">
|
|
566
|
-
{ "$unset": [ "old_email", "deprecated_field", "temp_token",
|
|
567
|
-
"trial_data", "beta_features" ] }
|
|
568
|
-
</div>
|
|
569
|
-
<button
|
|
570
|
-
class="copy-btn"
|
|
571
|
-
onclick="copyToClipboard(this.previousElementSibling)"
|
|
572
|
-
>
|
|
573
|
-
đ Copy
|
|
574
|
-
</button>
|
|
575
|
-
</div>
|
|
576
|
-
|
|
577
|
-
<div class="example-item">
|
|
578
|
-
<h4>īŋŊ Prepopulated Answers</h4>
|
|
579
|
-
<div class="example-code" onclick="copyToClipboard(this)">
|
|
580
|
-
[ { "sectionIndex": 0, "questionIndex": 0, "value": { "rating": 5
|
|
581
|
-
} }, { "sectionIndex": 0, "questionIndex": 1, "value": {
|
|
582
|
-
"short_answer": "Great product!" } }, { "sectionIndex": 1,
|
|
583
|
-
"questionIndex": 0, "value": { "single_choice": "Very satisfied" }
|
|
584
|
-
}, { "sectionIndex": 1, "questionIndex": 1, "value": { "nps": 9 }
|
|
585
|
-
} ]
|
|
586
|
-
</div>
|
|
587
|
-
<button
|
|
588
|
-
class="copy-btn"
|
|
589
|
-
onclick="copyToClipboard(this.previousElementSibling)"
|
|
590
|
-
>
|
|
591
|
-
đ Copy
|
|
592
|
-
</button>
|
|
593
|
-
</div>
|
|
594
|
-
|
|
595
|
-
<div class="example-item">
|
|
596
|
-
<h4>īŋŊđ Complete Example</h4>
|
|
597
|
-
<div class="example-code" onclick="copyToClipboard(this)">
|
|
598
|
-
{ "email": "premium@example.com", "name": "Premium User", "$set":
|
|
599
|
-
{ "plan": "premium", "last_active": "2024-01-15T10:30:00Z" },
|
|
600
|
-
"$set_once": { "first_purchase": "2024-01-01T00:00:00Z",
|
|
601
|
-
"signup_campaign": "winter_sale" }, "$counter": { "loginCount": 1,
|
|
602
|
-
"totalSpent": 199 }, "$unset": ["trial_expires", "temp_discount"]
|
|
603
|
-
}
|
|
604
|
-
</div>
|
|
605
|
-
<button
|
|
606
|
-
class="copy-btn"
|
|
607
|
-
onclick="copyToClipboard(this.previousElementSibling)"
|
|
608
|
-
>
|
|
609
|
-
đ Copy
|
|
610
|
-
</button>
|
|
611
|
-
</div>
|
|
612
|
-
</div>
|
|
613
|
-
</div>
|
|
614
|
-
</div>
|
|
615
|
-
</body>
|
|
616
|
-
<script>
|
|
617
|
-
(function(){if(!window.encatch){const a={_i:[],apiKey:"",config:{host:void 0,autoStartEnabled:!1,autoStartSessionDisabled:!0,themeMode:"light",language:"en",customCssLink:""},initialized:!1,chunkUrlLoader:t=>window.encatch.config.host+t,init(t,e){if("initialized"in window.encatch&&window.encatch.initialized)return;window.encatch.apiKey=t,e!=null&&e.host&&(window.encatch.config.host=e.host),e!=null&&e.identity&&(window.encatch.config.identity=e.identity),(e==null?void 0:e.autoStartSessionDisabled)!==void 0&&(window.encatch.config.autoStartSessionDisabled=e.autoStartSessionDisabled),(e==null?void 0:e.processAfterIdentitySet)!==void 0?window.encatch.config.processAfterIdentitySet=e.processAfterIdentitySet:window.encatch.config.processAfterIdentitySet=!1,(e==null?void 0:e.autoStartEnabled)!==void 0&&(window.encatch.config.autoStartEnabled=e.autoStartEnabled),e!=null&&e.themeMode?window.encatch.config.themeMode=e.themeMode:window.encatch.config.themeMode="light",e!=null&&e.language?window.encatch.config.language=e.language:window.encatch.config.language="en",e!=null&&e.customCssLink&&(window.encatch.config.customCssLink=e.customCssLink),e!=null&&e.setUser&&(window.encatch.config.setUser=e.setUser),e!=null&&e.onFormEvent&&(window.encatch.config.onFormEvent=e.onFormEvent),window.encatch.initialized=!0;let c="";c&&!c.startsWith("/")&&(c="/"+c),c=c.replace(/\/+$/,"");const d=`${window.encatch.config.host}${c}/encatch-web-sdk.js`,n=document.createElement("script");n.src=d,n.type="module",n.async=!0;const i=document.head.firstChild;i?document.head.insertBefore(n,i):document.head.appendChild(n);const r=document.createElement("div");r.id="enisght-root",document.body.appendChild(r)}};window.encatch=a;const h=["trackEvent","stop","start","setUser","setThemeMode","setLanguage","openFeedbackById","openFeedbackByName","verifyFeedbackIds","forceFetchEligibleFeedbacks","capturePageScrollEvent"];a._eventSubscriptions=[],a.on=((t,e)=>{const c={eventType:t,callback:e};return a._eventSubscriptions.push(c),()=>{const d=a._eventSubscriptions.indexOf(c);d>-1&&a._eventSubscriptions.splice(d,1)}}),h.forEach(t=>{a[t]=((...e)=>{window.encatch._i.push([t,...e])})})}})();
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
encatch.init("eng_dev_13cj63w5tJ396e30U0pWBAIt1pk1VhdWDQHgAbIdlNnhvbnANXNyQTgCmG4sMr5IroSz9a3Hx5iZ_c4c9d17c", {
|
|
622
|
-
autoStartEnabled: true,
|
|
623
|
-
processAfterIdentitySet: true,
|
|
624
|
-
|
|
625
|
-
...(window.location.hostname === 'localhost' ? { host: "http://localhost:4173" } : {}),
|
|
626
|
-
|
|
627
|
-
// Form event listeners - Config-based approach
|
|
628
|
-
onFormEvent: (formEvent) => {
|
|
629
|
-
formEvent.onSubmit((data) => {
|
|
630
|
-
console.log('đ [Config] Form submitted:', data);
|
|
631
|
-
alert(`Form submitted!\nFeedback ID: ${data.feedbackIdentifier || 'N/A'}\nConfig ID: ${data.feedbackConfigurationId}`);
|
|
632
|
-
});
|
|
633
|
-
|
|
634
|
-
formEvent.onView((data) => {
|
|
635
|
-
console.log('đī¸ [Config] Form viewed:', data);
|
|
636
|
-
});
|
|
637
|
-
|
|
638
|
-
formEvent.onClose((data) => {
|
|
639
|
-
console.log('â [Config] Form closed:', data);
|
|
640
|
-
});
|
|
641
|
-
|
|
642
|
-
formEvent.onQuestionAnswered((data) => {
|
|
643
|
-
console.log('âī¸ [Config] Question answered:', data.questionId, data.answer);
|
|
644
|
-
});
|
|
645
|
-
|
|
646
|
-
formEvent.onSectionChange((data) => {
|
|
647
|
-
console.log('đ [Config] Section changed to:', data.sectionIndex);
|
|
648
|
-
});
|
|
649
|
-
|
|
650
|
-
formEvent.onError((data) => {
|
|
651
|
-
console.error('â ī¸ [Config] Form error:', data.error);
|
|
652
|
-
});
|
|
653
|
-
}
|
|
654
|
-
});
|
|
655
|
-
|
|
656
|
-
// Runtime subscription example - Alternative approach using window.encatch.on()
|
|
657
|
-
// You can also subscribe to events at runtime like this:
|
|
658
|
-
const unsubscribeSubmit = encatch.on('form:submit', (data) => {
|
|
659
|
-
console.log('đ¯ [Runtime] Form submitted:', data);
|
|
660
|
-
});
|
|
661
|
-
|
|
662
|
-
// To unsubscribe later: unsubscribeSubmit();
|
|
663
|
-
// Add this to test in the browser console:
|
|
664
|
-
console.log("autoStartEnabled:", window.encatch.config.autoStartEnabled);
|
|
665
|
-
// setTimeout(() => {
|
|
666
|
-
// encatch.identify("test@test.com",{"email":"test@test.com", "age":38});
|
|
667
|
-
// }, 5000);
|
|
668
|
-
// Example usage in the HTML preview file
|
|
669
|
-
window.encatch.onSessionDisabled = (functionName, message) => {
|
|
670
|
-
console.error(`Function ${functionName} is disabled: ${message}`);
|
|
671
|
-
// Show user notification
|
|
672
|
-
alert(`Session management is disabled. Please contact your administrator to enable session functions.`);
|
|
673
|
-
};
|
|
674
|
-
// Tab switching functionality
|
|
675
|
-
function switchTab(tabName) {
|
|
676
|
-
// Update tab buttons
|
|
677
|
-
document
|
|
678
|
-
.querySelectorAll(".tab")
|
|
679
|
-
.forEach((tab) => tab.classList.remove("active"));
|
|
680
|
-
document
|
|
681
|
-
.querySelector(`.tab:nth-child(${tabName === "simple" ? "1" : "2"})`)
|
|
682
|
-
.classList.add("active");
|
|
683
|
-
|
|
684
|
-
// Update tab content
|
|
685
|
-
document
|
|
686
|
-
.querySelectorAll(".tab-content")
|
|
687
|
-
.forEach((content) => content.classList.remove("active"));
|
|
688
|
-
document.getElementById(`${tabName}-tab`).classList.add("active");
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
// Copy to clipboard functionality
|
|
692
|
-
function copyToClipboard(element) {
|
|
693
|
-
const text = element.textContent;
|
|
694
|
-
navigator.clipboard
|
|
695
|
-
.writeText(text)
|
|
696
|
-
.then(() => {
|
|
697
|
-
// Visual feedback
|
|
698
|
-
const originalText = element.textContent;
|
|
699
|
-
element.style.backgroundColor = "#28a745";
|
|
700
|
-
element.textContent = "â
Copied!";
|
|
701
|
-
setTimeout(() => {
|
|
702
|
-
element.style.backgroundColor = "#2d3748";
|
|
703
|
-
element.textContent = originalText;
|
|
704
|
-
}, 1000);
|
|
705
|
-
})
|
|
706
|
-
.catch((err) => {
|
|
707
|
-
console.error("Failed to copy: ", err);
|
|
708
|
-
});
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
// Make functions global
|
|
712
|
-
window.switchTab = switchTab;
|
|
713
|
-
window.copyToClipboard = copyToClipboard;
|
|
714
|
-
|
|
715
|
-
// Add popup functionality
|
|
716
|
-
document.getElementById("openPopupById").addEventListener("click", () => {
|
|
717
|
-
const feedbackId = document.getElementById("feedbackId").value;
|
|
718
|
-
const prepopulatedAnswersText = document.getElementById(
|
|
719
|
-
"prepopulatedAnswersTextarea"
|
|
720
|
-
).value;
|
|
721
|
-
|
|
722
|
-
if (feedbackId) {
|
|
723
|
-
let prepopulatedAnswers = null;
|
|
724
|
-
|
|
725
|
-
// Parse prepopulated answers if provided
|
|
726
|
-
if (prepopulatedAnswersText.trim()) {
|
|
727
|
-
try {
|
|
728
|
-
prepopulatedAnswers = JSON.parse(prepopulatedAnswersText);
|
|
729
|
-
console.log("đ Prepopulated Answers:", prepopulatedAnswers);
|
|
730
|
-
} catch (error) {
|
|
731
|
-
console.error("Invalid JSON in prepopulated answers:", error);
|
|
732
|
-
alert(
|
|
733
|
-
"Invalid JSON format in prepopulated answers. Please check your JSON syntax."
|
|
734
|
-
);
|
|
735
|
-
return;
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
console.log("đ¯ Opening feedback by ID:", feedbackId);
|
|
740
|
-
// Pass all parameters including prepopulated answers
|
|
741
|
-
encatch.openFeedbackById(
|
|
742
|
-
feedbackId,
|
|
743
|
-
undefined, // theme
|
|
744
|
-
undefined, // language
|
|
745
|
-
undefined, // event
|
|
746
|
-
undefined, // customProperties
|
|
747
|
-
prepopulatedAnswers // prepopulatedAnswers
|
|
748
|
-
);
|
|
749
|
-
}
|
|
750
|
-
});
|
|
751
|
-
|
|
752
|
-
document.getElementById("openPopupByName").addEventListener("click", () => {
|
|
753
|
-
const feedbackName = document.getElementById("feedbackName").value;
|
|
754
|
-
const prepopulatedAnswersText = document.getElementById(
|
|
755
|
-
"prepopulatedAnswersTextarea"
|
|
756
|
-
).value;
|
|
757
|
-
|
|
758
|
-
if (feedbackName) {
|
|
759
|
-
let prepopulatedAnswers = null;
|
|
760
|
-
|
|
761
|
-
// Parse prepopulated answers if provided
|
|
762
|
-
if (prepopulatedAnswersText.trim()) {
|
|
763
|
-
try {
|
|
764
|
-
prepopulatedAnswers = JSON.parse(prepopulatedAnswersText);
|
|
765
|
-
console.log("đ Prepopulated Answers:", prepopulatedAnswers);
|
|
766
|
-
} catch (error) {
|
|
767
|
-
console.error("Invalid JSON in prepopulated answers:", error);
|
|
768
|
-
alert(
|
|
769
|
-
"Invalid JSON format in prepopulated answers. Please check your JSON syntax."
|
|
770
|
-
);
|
|
771
|
-
return;
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
console.log("đ¯ Opening feedback by name:", feedbackName);
|
|
776
|
-
// Note: openFeedbackByName doesn't currently support prepopulated answers
|
|
777
|
-
// So we just log them for now
|
|
778
|
-
if (prepopulatedAnswers) {
|
|
779
|
-
console.log(
|
|
780
|
-
"đ Prepopulated Answers (will be ignored by openFeedbackByName):",
|
|
781
|
-
prepopulatedAnswers
|
|
782
|
-
);
|
|
783
|
-
}
|
|
784
|
-
encatch.openFeedbackByName(feedbackName);
|
|
785
|
-
}
|
|
786
|
-
});
|
|
787
|
-
|
|
788
|
-
// Add track event functionality
|
|
789
|
-
document.getElementById("trackEventBtn").addEventListener("click", () => {
|
|
790
|
-
const eventName = document.getElementById("eventName").value;
|
|
791
|
-
const propertiesText = document.getElementById("eventProperties").value;
|
|
792
|
-
|
|
793
|
-
if (eventName) {
|
|
794
|
-
try {
|
|
795
|
-
const properties = propertiesText.trim()
|
|
796
|
-
? JSON.parse(propertiesText)
|
|
797
|
-
: {};
|
|
798
|
-
console.log("đ¯ Tracking event:", { eventName, properties });
|
|
799
|
-
encatch.trackEvent(eventName, properties);
|
|
800
|
-
} catch (error) {
|
|
801
|
-
console.error("Invalid JSON in event properties:", error);
|
|
802
|
-
alert(
|
|
803
|
-
"Invalid JSON format in event properties. Please check your JSON syntax."
|
|
804
|
-
);
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
});
|
|
808
|
-
|
|
809
|
-
// Add theme change functionality
|
|
810
|
-
document.getElementById("themeSelect").addEventListener("change", (e) => {
|
|
811
|
-
const theme = e.target.value;
|
|
812
|
-
document.body.setAttribute("data-theme", theme);
|
|
813
|
-
console.log("đ¨ Setting theme:", theme);
|
|
814
|
-
encatch.setThemeMode(theme);
|
|
815
|
-
});
|
|
816
|
-
|
|
817
|
-
document.getElementById("customPropertiesTextarea").addEventListener("change", (e) => {
|
|
818
|
-
const customPropertiesText = e.target.value;
|
|
819
|
-
|
|
820
|
-
if (customPropertiesText.trim()) {
|
|
821
|
-
try {
|
|
822
|
-
const customProperties = JSON.parse(customPropertiesText);
|
|
823
|
-
console.log("đĻ Setting custom Properties:", customProperties);
|
|
824
|
-
encatch.setCustomProperties(customProperties);
|
|
825
|
-
} catch (error) {
|
|
826
|
-
console.error("Invalid JSON in custom properties:", error);
|
|
827
|
-
alert("Invalid JSON format in custom properties. Please check your JSON syntax.");
|
|
828
|
-
}
|
|
829
|
-
} else {
|
|
830
|
-
encatch.setCustomProperties({});
|
|
831
|
-
}
|
|
832
|
-
});
|
|
833
|
-
|
|
834
|
-
// Add language change functionality
|
|
835
|
-
document
|
|
836
|
-
.getElementById("languageSelect")
|
|
837
|
-
.addEventListener("change", (e) => {
|
|
838
|
-
const language = e.target.value;
|
|
839
|
-
console.log("đ Setting language:", language);
|
|
840
|
-
encatch.setLanguage(language);
|
|
841
|
-
});
|
|
842
|
-
|
|
843
|
-
// Simple setUser functionality
|
|
844
|
-
document
|
|
845
|
-
.getElementById("identifyUserSimple")
|
|
846
|
-
.addEventListener("click", () => {
|
|
847
|
-
const userName = document.getElementById("userName").value;
|
|
848
|
-
const email = document.getElementById("email").value;
|
|
849
|
-
const phone = document.getElementById("phone").value;
|
|
850
|
-
const name = document.getElementById("name").value;
|
|
851
|
-
const age = document.getElementById("age").value;
|
|
852
|
-
|
|
853
|
-
// Get operation configuration from UI
|
|
854
|
-
const setFieldsInput = document.getElementById("setFields").value;
|
|
855
|
-
const setOnceFieldsInput =
|
|
856
|
-
document.getElementById("setOnceFields").value;
|
|
857
|
-
const counterName = document.getElementById("counterName").value;
|
|
858
|
-
const counterValue = document.getElementById("counterValue").value;
|
|
859
|
-
const unsetFieldsInput = document.getElementById("unsetFields").value;
|
|
860
|
-
|
|
861
|
-
if (userName) {
|
|
862
|
-
const userPayload = {};
|
|
863
|
-
|
|
864
|
-
// Available user data
|
|
865
|
-
const userData = {
|
|
866
|
-
email,
|
|
867
|
-
phone,
|
|
868
|
-
name,
|
|
869
|
-
age: age ? parseInt(age) : undefined,
|
|
870
|
-
};
|
|
871
|
-
|
|
872
|
-
// Handle $set operation
|
|
873
|
-
if (setFieldsInput.trim()) {
|
|
874
|
-
const setFieldNames = setFieldsInput
|
|
875
|
-
.split(",")
|
|
876
|
-
.map((f) => f.trim())
|
|
877
|
-
.filter((f) => f);
|
|
878
|
-
const setData = {};
|
|
879
|
-
setFieldNames.forEach((fieldName) => {
|
|
880
|
-
if (
|
|
881
|
-
userData[fieldName] !== undefined &&
|
|
882
|
-
userData[fieldName] !== ""
|
|
883
|
-
) {
|
|
884
|
-
setData[fieldName] = userData[fieldName];
|
|
885
|
-
}
|
|
886
|
-
});
|
|
887
|
-
if (Object.keys(setData).length > 0) {
|
|
888
|
-
userPayload.$set = setData;
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
// Handle $set_once operation
|
|
893
|
-
if (setOnceFieldsInput.trim()) {
|
|
894
|
-
const setOnceFieldNames = setOnceFieldsInput
|
|
895
|
-
.split(",")
|
|
896
|
-
.map((f) => f.trim())
|
|
897
|
-
.filter((f) => f);
|
|
898
|
-
const setOnceData = {};
|
|
899
|
-
setOnceFieldNames.forEach((fieldName) => {
|
|
900
|
-
if (
|
|
901
|
-
userData[fieldName] !== undefined &&
|
|
902
|
-
userData[fieldName] !== ""
|
|
903
|
-
) {
|
|
904
|
-
setOnceData[fieldName] = userData[fieldName];
|
|
905
|
-
}
|
|
906
|
-
});
|
|
907
|
-
// Always add date to set_once
|
|
908
|
-
setOnceData.date = new Date().toISOString();
|
|
909
|
-
if (Object.keys(setOnceData).length > 0) {
|
|
910
|
-
userPayload.$set_once = setOnceData;
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
// Handle $counter operation
|
|
915
|
-
if (counterName.trim() && counterValue.trim()) {
|
|
916
|
-
userPayload.$counter = {
|
|
917
|
-
[counterName]: parseInt(counterValue) || 1,
|
|
918
|
-
};
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
// Handle $unset operation
|
|
922
|
-
if (unsetFieldsInput.trim()) {
|
|
923
|
-
const unsetFieldNames = unsetFieldsInput
|
|
924
|
-
.split(",")
|
|
925
|
-
.map((f) => f.trim())
|
|
926
|
-
.filter((f) => f);
|
|
927
|
-
if (unsetFieldNames.length > 0) {
|
|
928
|
-
userPayload.$unset = unsetFieldNames;
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
console.log("đ¤ Setting user (Simple):", {
|
|
933
|
-
userId: userName,
|
|
934
|
-
payload: userPayload,
|
|
935
|
-
});
|
|
936
|
-
encatch.setUser(userName, userPayload);
|
|
937
|
-
} else {
|
|
938
|
-
alert("Please provide a User Name");
|
|
939
|
-
}
|
|
940
|
-
});
|
|
941
|
-
|
|
942
|
-
// JSON setUser functionality
|
|
943
|
-
document
|
|
944
|
-
.getElementById("identifyUserJson")
|
|
945
|
-
.addEventListener("click", () => {
|
|
946
|
-
const userName = document.getElementById("userNameJson").value;
|
|
947
|
-
const payloadText = document.getElementById("identifyPayload").value;
|
|
948
|
-
|
|
949
|
-
if (userName && payloadText.trim()) {
|
|
950
|
-
try {
|
|
951
|
-
const userPayload = JSON.parse(payloadText);
|
|
952
|
-
|
|
953
|
-
console.log("đ¤ Setting user (JSON):", {
|
|
954
|
-
userId: userName,
|
|
955
|
-
payload: userPayload,
|
|
956
|
-
});
|
|
957
|
-
|
|
958
|
-
encatch.setUser(userName, userPayload);
|
|
959
|
-
} catch (error) {
|
|
960
|
-
console.error("Invalid JSON payload:", error);
|
|
961
|
-
alert("Invalid JSON format. Please check your JSON syntax.");
|
|
962
|
-
}
|
|
963
|
-
} else {
|
|
964
|
-
alert("Please provide both User Name and User Payload JSON");
|
|
965
|
-
}
|
|
966
|
-
});
|
|
967
|
-
// Function to update session status display
|
|
968
|
-
function updateSessionStatus() {
|
|
969
|
-
const sessionId = sessionStorage.getItem('app_session');
|
|
970
|
-
const sessionStatusElement = document.getElementById('sessionStatus');
|
|
971
|
-
|
|
972
|
-
if (sessionId) {
|
|
973
|
-
sessionStatusElement.textContent = sessionId;
|
|
974
|
-
sessionStatusElement.style.color = '#28a745';
|
|
975
|
-
} else {
|
|
976
|
-
sessionStatusElement.textContent = 'No session active';
|
|
977
|
-
sessionStatusElement.style.color = '#666';
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
// Session Management Event Listeners
|
|
982
|
-
document.getElementById("startSessionBtn").addEventListener("click", () => {
|
|
983
|
-
console.log("đ Starting SDK (enables autoStart)");
|
|
984
|
-
encatch.start();
|
|
985
|
-
setTimeout(updateSessionStatus, 100); // Small delay to ensure session is set
|
|
986
|
-
});
|
|
987
|
-
|
|
988
|
-
document.getElementById("stopSessionBtn").addEventListener("click", () => {
|
|
989
|
-
console.log("âšī¸ Stopping SDK");
|
|
990
|
-
encatch.stop();
|
|
991
|
-
setTimeout(updateSessionStatus, 100);
|
|
992
|
-
});
|
|
993
|
-
|
|
994
|
-
document.getElementById("resetSessionBtn").addEventListener("click", () => {
|
|
995
|
-
console.log("đ Making user anonymous");
|
|
996
|
-
encatch.setUser();
|
|
997
|
-
setTimeout(updateSessionStatus, 100);
|
|
998
|
-
});
|
|
999
|
-
|
|
1000
|
-
document.getElementById("checkSessionBtn").addEventListener("click", () => {
|
|
1001
|
-
const sessionId = sessionStorage.getItem('app_session');
|
|
1002
|
-
const userData = sessionStorage.getItem('encatch_app_user');
|
|
1003
|
-
|
|
1004
|
-
console.log("đ Session Status Check:");
|
|
1005
|
-
console.log("Session ID:", sessionId);
|
|
1006
|
-
console.log("User Data:", userData ? JSON.parse(userData) : "No user data");
|
|
1007
|
-
|
|
1008
|
-
updateSessionStatus();
|
|
1009
|
-
});
|
|
1010
|
-
|
|
1011
|
-
// Initialize session status on page load
|
|
1012
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
1013
|
-
updateSessionStatus();
|
|
1014
|
-
});
|
|
1015
|
-
|
|
1016
|
-
// Add scroll event listener to automatically trigger capturePageScrollEvent
|
|
1017
|
-
function calculateScrollPercentage() {
|
|
1018
|
-
const scrollY = window.scrollY;
|
|
1019
|
-
const windowHeight = window.innerHeight;
|
|
1020
|
-
const documentHeight = document.documentElement.scrollHeight;
|
|
1021
|
-
const maxScroll = documentHeight - windowHeight;
|
|
1022
|
-
const percentage = maxScroll > 0 ? (scrollY / maxScroll) * 100 : 0;
|
|
1023
|
-
return Math.round(percentage);
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
let scrollTimeout;
|
|
1027
|
-
window.addEventListener('scroll', () => {
|
|
1028
|
-
// Throttle scroll events to avoid excessive calls
|
|
1029
|
-
clearTimeout(scrollTimeout);
|
|
1030
|
-
scrollTimeout = setTimeout(() => {
|
|
1031
|
-
const scrollPercent = calculateScrollPercentage();
|
|
1032
|
-
console.log(`đ Current scroll percentage: ${scrollPercent}%`);
|
|
1033
|
-
|
|
1034
|
-
// Call encatch.capturePageScrollEvent with current scroll percentage
|
|
1035
|
-
if (window.encatch && window.encatch.capturePageScrollEvent) {
|
|
1036
|
-
encatch.capturePageScrollEvent(`${scrollPercent}%`);
|
|
1037
|
-
}
|
|
1038
|
-
}, 100); // Throttle to every 100ms
|
|
1039
|
-
}, { passive: true });
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
// Function to clear session storage
|
|
1043
|
-
function clearSessionStorage() {
|
|
1044
|
-
if (confirm('Are you sure you want to clear the session storage? This will remove all cached feedbacks.')) {
|
|
1045
|
-
sessionStorage.removeItem('encatch-configuration');
|
|
1046
|
-
console.log("đī¸ Session storage cleared");
|
|
1047
|
-
displayFeedbacks();
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
// Function to display feedbacks
|
|
1052
|
-
function displayFeedbacks() {
|
|
1053
|
-
const feedbacksList = document.getElementById('feedbacksList');
|
|
1054
|
-
|
|
1055
|
-
// Get the configuration from sessionStorage
|
|
1056
|
-
const configData = sessionStorage.getItem('encatch-configuration');
|
|
1057
|
-
|
|
1058
|
-
if (!configData) {
|
|
1059
|
-
feedbacksList.innerHTML = `
|
|
1060
|
-
<div style="background: #fff3cd; padding: 1rem; border-radius: 6px; color: #856404;">
|
|
1061
|
-
â ī¸ No feedbacks found. Make sure you've initialized the SDK and fetched configurations.
|
|
1062
|
-
</div>
|
|
1063
|
-
`;
|
|
1064
|
-
return;
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
try {
|
|
1068
|
-
const config = JSON.parse(configData);
|
|
1069
|
-
const feedbacks = config.data?.feedbackConfigurations || [];
|
|
1070
|
-
|
|
1071
|
-
if (feedbacks.length === 0) {
|
|
1072
|
-
feedbacksList.innerHTML = `
|
|
1073
|
-
<div style="background: #e7f3ff; padding: 1rem; border-radius: 6px; color: #004085;">
|
|
1074
|
-
âšī¸ No feedbacks available for this configuration.
|
|
1075
|
-
</div>
|
|
1076
|
-
`;
|
|
1077
|
-
return;
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
console.log(`đĻ Found ${feedbacks.length} feedbacks`);
|
|
1081
|
-
|
|
1082
|
-
// Create feedback cards
|
|
1083
|
-
let feedbacksHTML = '';
|
|
1084
|
-
feedbacks.forEach((feedback, index) => {
|
|
1085
|
-
const feedbackId = feedback.feedbackConfigurationId || 'N/A';
|
|
1086
|
-
const feedbackName = feedback.feedbackTitle || 'Untitled Feedback';
|
|
1087
|
-
const isActive = feedback.isActive !== undefined ? feedback.isActive : true;
|
|
1088
|
-
|
|
1089
|
-
feedbacksHTML += `
|
|
1090
|
-
<div style="background: white; border: 1px solid #e1e5e9; border-radius: 8px; padding: 1rem; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
|
|
1091
|
-
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 0.75rem;">
|
|
1092
|
-
<h4 style="margin: 0; color: #333; font-size: 1rem; flex: 1;">
|
|
1093
|
-
${feedbackName}
|
|
1094
|
-
</h4>
|
|
1095
|
-
<span style="padding: 0.25rem 0.5rem; background: ${isActive ? '#d4edda' : '#f8d7da'}; color: ${isActive ? '#155724' : '#721c24'}; border-radius: 4px; font-size: 0.75rem; white-space: nowrap;">
|
|
1096
|
-
${isActive ? 'â Active' : 'â Inactive'}
|
|
1097
|
-
</span>
|
|
1098
|
-
</div>
|
|
1099
|
-
|
|
1100
|
-
<div style="margin-bottom: 0.5rem;">
|
|
1101
|
-
<div style="font-size: 0.75rem; color: #666; margin-bottom: 0.25rem; font-weight: 600;">FEEDBACK ID:</div>
|
|
1102
|
-
<div
|
|
1103
|
-
onclick="copyToClipboardAndFill('${feedbackId}', 'feedbackId', this)"
|
|
1104
|
-
style="background: #f8f9fa; padding: 0.5rem; border-radius: 4px; font-family: monospace; font-size: 0.85rem; cursor: pointer; transition: all 0.2s; border: 1px solid #e1e5e9; word-break: break-all;"
|
|
1105
|
-
onmouseover="this.style.background='#e9ecef'; this.style.borderColor='#667eea'"
|
|
1106
|
-
onmouseout="this.style.background='#f8f9fa'; this.style.borderColor='#e1e5e9'"
|
|
1107
|
-
>
|
|
1108
|
-
${feedbackId}
|
|
1109
|
-
</div>
|
|
1110
|
-
</div>
|
|
1111
|
-
|
|
1112
|
-
<div>
|
|
1113
|
-
<div style="font-size: 0.75rem; color: #666; margin-bottom: 0.25rem; font-weight: 600;">FEEDBACK NAME:</div>
|
|
1114
|
-
<div
|
|
1115
|
-
onclick="copyToClipboardAndFill('${feedbackName.replace(/'/g, "\\'")}', 'feedbackName', this)"
|
|
1116
|
-
style="background: #f8f9fa; padding: 0.5rem; border-radius: 4px; font-family: monospace; font-size: 0.85rem; cursor: pointer; transition: all 0.2s; border: 1px solid #e1e5e9; word-break: break-all;"
|
|
1117
|
-
onmouseover="this.style.background='#e9ecef'; this.style.borderColor='#667eea'"
|
|
1118
|
-
onmouseout="this.style.background='#f8f9fa'; this.style.borderColor='#e1e5e9'"
|
|
1119
|
-
>
|
|
1120
|
-
${feedbackName}
|
|
1121
|
-
</div>
|
|
1122
|
-
</div>
|
|
1123
|
-
</div>
|
|
1124
|
-
`;
|
|
1125
|
-
});
|
|
1126
|
-
|
|
1127
|
-
feedbacksList.innerHTML = feedbacksHTML;
|
|
1128
|
-
console.log("â
Feedbacks displayed successfully");
|
|
1129
|
-
|
|
1130
|
-
} catch (error) {
|
|
1131
|
-
console.error("Error parsing feedback configuration:", error);
|
|
1132
|
-
feedbacksList.innerHTML = `
|
|
1133
|
-
<div style="background: #fee; padding: 1rem; border-radius: 6px; color: #c33;">
|
|
1134
|
-
â Error parsing feedback data. Please check console for details.
|
|
1135
|
-
</div>
|
|
1136
|
-
`;
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
// Function to copy to clipboard and fill input
|
|
1141
|
-
function copyToClipboardAndFill(text, inputId, element) {
|
|
1142
|
-
// Copy to clipboard
|
|
1143
|
-
navigator.clipboard.writeText(text).then(() => {
|
|
1144
|
-
// Fill the input field
|
|
1145
|
-
const input = document.getElementById(inputId);
|
|
1146
|
-
if (input) {
|
|
1147
|
-
input.value = text;
|
|
1148
|
-
}
|
|
1149
|
-
|
|
1150
|
-
// Visual feedback
|
|
1151
|
-
const originalBg = element.style.background;
|
|
1152
|
-
const originalText = element.textContent;
|
|
1153
|
-
element.style.background = '#28a745';
|
|
1154
|
-
element.style.color = 'white';
|
|
1155
|
-
element.textContent = 'â
Copied & Filled!';
|
|
1156
|
-
|
|
1157
|
-
setTimeout(() => {
|
|
1158
|
-
element.style.background = originalBg;
|
|
1159
|
-
element.style.color = '';
|
|
1160
|
-
element.textContent = originalText;
|
|
1161
|
-
}, 1000);
|
|
1162
|
-
}).catch(err => {
|
|
1163
|
-
console.error('Failed to copy:', err);
|
|
1164
|
-
alert('Failed to copy to clipboard');
|
|
1165
|
-
});
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
// Auto-display feedbacks on page load and set up periodic refresh
|
|
1169
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
1170
|
-
// Initial display
|
|
1171
|
-
setTimeout(() => {
|
|
1172
|
-
displayFeedbacks();
|
|
1173
|
-
}, 500);
|
|
1174
|
-
|
|
1175
|
-
// Auto-refresh every 2 seconds to pick up any new feedbacks
|
|
1176
|
-
setInterval(() => {
|
|
1177
|
-
displayFeedbacks();
|
|
1178
|
-
}, 2000);
|
|
1179
|
-
});
|
|
1180
|
-
|
|
1181
|
-
</script>
|
|
1182
|
-
</html>
|