@magicfeedback/popup-sdk 1.1.8 → 1.3.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 +113 -70
- package/dist/assets/assets/style.css +5 -1
- package/dist/chunk-R4B3K2ZW.mjs +176 -0
- package/dist/chunk-R4B3K2ZW.mjs.map +1 -0
- package/dist/chunk-XFA2Y6CK.mjs +197 -0
- package/dist/chunk-XFA2Y6CK.mjs.map +1 -0
- package/dist/index.d.mts +130 -14
- package/dist/index.d.ts +130 -14
- package/dist/index.js +426 -910
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +416 -44
- package/dist/index.mjs.map +1 -1
- package/dist/react-native.d.mts +60 -8
- package/dist/react-native.d.ts +60 -8
- package/dist/react-native.js +425 -911
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +415 -45
- package/dist/react-native.mjs.map +1 -1
- package/dist/{renderPopup-EZKDMLVZ.mjs → renderPopup-NJK7Z46E.mjs} +10 -870
- package/dist/renderPopup-NJK7Z46E.mjs.map +1 -0
- package/dist/{renderPopup-PS3NJDUR.mjs → renderPopup-ZYXOUBCP.mjs} +10 -870
- package/dist/renderPopup-ZYXOUBCP.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-4UXOEIAB.mjs +0 -172
- package/dist/chunk-4UXOEIAB.mjs.map +0 -1
- package/dist/chunk-XOTM5CHX.mjs +0 -193
- package/dist/chunk-XOTM5CHX.mjs.map +0 -1
- package/dist/renderPopup-EZKDMLVZ.mjs.map +0 -1
- package/dist/renderPopup-PS3NJDUR.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -7,8 +7,9 @@ import {
|
|
|
7
7
|
buildSurveyIdentity,
|
|
8
8
|
createDefaultStorage,
|
|
9
9
|
sdkWarn,
|
|
10
|
-
setLogger
|
|
11
|
-
|
|
10
|
+
setLogger,
|
|
11
|
+
style_default
|
|
12
|
+
} from "./chunk-XFA2Y6CK.mjs";
|
|
12
13
|
|
|
13
14
|
// src/types/index.ts
|
|
14
15
|
var POPUP_TRIGGER_CONDITION_STATUSES = [
|
|
@@ -195,6 +196,15 @@ function resolveEnvironment(nodeEnv) {
|
|
|
195
196
|
}
|
|
196
197
|
|
|
197
198
|
// src/ui/surveyHtml.ts
|
|
199
|
+
var POSITION_MAP = {
|
|
200
|
+
center: { justifyContent: "center", alignItems: "center", padding: "0", background: "rgba(0,0,0,0.5)" },
|
|
201
|
+
bottom: { justifyContent: "center", alignItems: "flex-end", padding: "16px", background: "transparent" },
|
|
202
|
+
"bottom-right": { justifyContent: "flex-end", alignItems: "flex-end", padding: "16px", background: "transparent" },
|
|
203
|
+
"bottom-left": { justifyContent: "flex-start", alignItems: "flex-end", padding: "16px", background: "transparent" },
|
|
204
|
+
top: { justifyContent: "center", alignItems: "flex-start", padding: "16px", background: "transparent" },
|
|
205
|
+
"top-right": { justifyContent: "flex-end", alignItems: "flex-start", padding: "16px", background: "transparent" },
|
|
206
|
+
"top-left": { justifyContent: "flex-start", alignItems: "flex-start", padding: "16px", background: "transparent" }
|
|
207
|
+
};
|
|
198
208
|
function buildSurveyHtml(opts) {
|
|
199
209
|
const env = opts.env === "development" ? "dev" : "prod";
|
|
200
210
|
const version = opts.version ?? "2.2.4";
|
|
@@ -205,17 +215,141 @@ function buildSurveyHtml(opts) {
|
|
|
205
215
|
const metaJson = JSON.stringify(opts.metadata ?? []);
|
|
206
216
|
const fontFaceCss = opts.font ? buildFontFaceCss(opts.font.family, opts.font.url) : "";
|
|
207
217
|
const fontFamilyValue = opts.font ? buildFontFamilyValue(opts.font.family) : "-apple-system,system-ui,sans-serif";
|
|
218
|
+
const popupClass = opts.font?.family ? "deepdots-popup deepdots-has-font" : "deepdots-popup";
|
|
219
|
+
const isDark = opts.theme === "dark";
|
|
220
|
+
const popupBg = isDark ? "#1e1e1e" : "#fff";
|
|
221
|
+
const colorScheme = isDark ? "dark" : "light";
|
|
222
|
+
const textPrimary = isDark ? "#f0f0f0" : "#111";
|
|
223
|
+
const pos = POSITION_MAP[opts.position ?? "center"] ?? POSITION_MAP.center;
|
|
224
|
+
const backLabel = JSON.stringify(opts.actions?.back?.label ?? "Back");
|
|
225
|
+
const startLabel = JSON.stringify(opts.actions?.start?.label ?? "Start survey");
|
|
226
|
+
const completeLabel = JSON.stringify(opts.actions?.complete?.label ?? "Complete survey");
|
|
227
|
+
const submitLabel = JSON.stringify(opts.actions?.accept?.label ?? "Send");
|
|
208
228
|
return `<!DOCTYPE html><html><head>
|
|
209
229
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
210
|
-
<meta name="color-scheme" content="
|
|
211
|
-
<style
|
|
230
|
+
<meta name="color-scheme" content="${colorScheme}"/>
|
|
231
|
+
<style>
|
|
232
|
+
${style_default}
|
|
233
|
+
${fontFaceCss}
|
|
234
|
+
html,body{margin:0;padding:0;height:100%;font-family:${fontFamilyValue}}
|
|
235
|
+
body{display:flex;justify-content:${pos.justifyContent};align-items:${pos.alignItems};background:${pos.background};padding:${pos.padding};box-sizing:border-box}
|
|
236
|
+
.deepdots-popup{position:relative;display:flex;flex-direction:column;justify-content:flex-start;background:${popupBg};color-scheme:${colorScheme};border-radius:8px;padding:24px;box-shadow:0 4px 6px rgba(0,0,0,0.1);max-width:600px;width:90%;min-height:200px;box-sizing:border-box}
|
|
237
|
+
.deepdots-popup-header{display:flex;justify-content:flex-end;align-items:center;width:100%}
|
|
238
|
+
#dd-close{background:transparent;border:none;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:8px;cursor:pointer;color:${textPrimary};padding:4px}
|
|
239
|
+
.deepdots-popup-container-content{display:flex;flex-direction:column;padding:0 20px 12px 20px;max-height:80vh;overflow:hidden;box-sizing:border-box}
|
|
240
|
+
.deepdots-popup-main{display:flex;flex-direction:column;width:100%;max-height:80vh;overflow-y:auto;overflow-x:hidden;position:relative}
|
|
241
|
+
#dd-form-wrapper{width:100%;flex:1 1 auto}
|
|
242
|
+
#mf{width:100%;box-sizing:border-box;visibility:hidden}
|
|
243
|
+
.deepdots-popup-main *{max-width:100%;box-sizing:border-box}
|
|
244
|
+
#dd-logo{max-height:40px;max-width:100%;object-fit:contain}
|
|
245
|
+
.deepdots-error-hint{display:none;margin:12px 0 0 0;padding:10px 12px;border-radius:6px;background:#FEF3C7;color:#92400E;border:1px solid #FCD34D;font-size:13px}
|
|
246
|
+
.deepdots-popup-footer{display:flex;flex-direction:row-reverse;justify-content:space-between;align-items:center;gap:8px;margin-top:auto;width:100%;padding-top:16px}
|
|
247
|
+
.dd-nav-btn{display:none;border:none;padding:12px 24px;border-radius:4px;cursor:pointer;font-size:14px;box-shadow:0 2px 4px rgba(0,0,0,0.1);align-items:center;justify-content:center;text-align:center}
|
|
248
|
+
#dd-back{background:transparent;color:#333;border:1px solid #999}
|
|
249
|
+
#dd-start,#dd-complete,#dd-submit{background:#1E293B;color:#fff;border:none}
|
|
250
|
+
#dd-submit:disabled,#dd-start:disabled,#dd-back:disabled,#dd-complete:disabled{opacity:0.6;cursor:not-allowed}
|
|
251
|
+
.mf-spinner{display:none;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}
|
|
252
|
+
.mf-spinner-circle{width:28px;height:28px;border:3px solid #e0e6ed;border-top-color:#1E293B;border-radius:50%;animation:ddspin 0.9s linear infinite}
|
|
253
|
+
@keyframes ddspin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}
|
|
254
|
+
@media (max-width:640px){
|
|
255
|
+
.deepdots-popup{width:calc(100% - 24px);max-width:calc(100% - 24px);border-radius:12px}
|
|
256
|
+
.deepdots-popup-footer{flex-direction:column-reverse;gap:12px}
|
|
257
|
+
.dd-nav-btn{width:100%}
|
|
258
|
+
.magicfeedback-checkbox-container,.magicfeedback-radio-container{margin:4px 0;padding:4px 8px}
|
|
259
|
+
.magicfeedback-checkbox label,.magicfeedback-radio-container label{font-size:15px}
|
|
260
|
+
.deepdots-popup input[type="radio"]{margin:6px 0 6px 8px}
|
|
261
|
+
.deepdots-popup input[type="checkbox"]{width:16px;height:16px}
|
|
262
|
+
}
|
|
263
|
+
</style>
|
|
212
264
|
</head><body>
|
|
213
|
-
<div id="
|
|
265
|
+
<div class="${popupClass}" id="dd-popup">
|
|
266
|
+
<div class="deepdots-popup-header">
|
|
267
|
+
<button type="button" id="dd-close" aria-label="Close popup">
|
|
268
|
+
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
269
|
+
<path d="M6 6L18 18M6 18L18 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
270
|
+
</svg>
|
|
271
|
+
</button>
|
|
272
|
+
</div>
|
|
273
|
+
<div class="deepdots-popup-container-content">
|
|
274
|
+
<div class="deepdots-popup-main" id="dd-main">
|
|
275
|
+
<div id="dd-form-wrapper">
|
|
276
|
+
<div class="mf-spinner" id="dd-spinner" role="status" aria-label="Loading survey"><div class="mf-spinner-circle"></div></div>
|
|
277
|
+
<div id="mf"></div>
|
|
278
|
+
</div>
|
|
279
|
+
<div class="deepdots-error-hint" id="dd-error" role="alert" aria-live="polite"></div>
|
|
280
|
+
<div class="deepdots-popup-footer" id="dd-footer">
|
|
281
|
+
<button type="button" class="dd-nav-btn" id="dd-submit">Send</button>
|
|
282
|
+
<button type="button" class="dd-nav-btn" id="dd-back">Back</button>
|
|
283
|
+
<button type="button" class="dd-nav-btn" id="dd-complete">Complete survey</button>
|
|
284
|
+
<button type="button" class="dd-nav-btn" id="dd-start">Start survey</button>
|
|
285
|
+
</div>
|
|
286
|
+
</div>
|
|
287
|
+
</div>
|
|
288
|
+
</div>
|
|
214
289
|
<script>
|
|
215
290
|
(function(){
|
|
216
291
|
function emit(s){ try{ if(window.ReactNativeWebView){ window.ReactNativeWebView.postMessage(s); } }catch(e){} }
|
|
217
292
|
function emitJSON(n,p){ try{ emit(JSON.stringify({name:n,payload:p||{}})); }catch(e){} }
|
|
218
293
|
window.DeepdotsClose = function(){ emitJSON('popup_close'); };
|
|
294
|
+
|
|
295
|
+
var popup=document.getElementById('dd-popup');
|
|
296
|
+
var main=document.getElementById('dd-main');
|
|
297
|
+
var footer=document.getElementById('dd-footer');
|
|
298
|
+
var spinner=document.getElementById('dd-spinner');
|
|
299
|
+
var formHost=document.getElementById('mf');
|
|
300
|
+
var errorHint=document.getElementById('dd-error');
|
|
301
|
+
var backBtn=document.getElementById('dd-back');
|
|
302
|
+
var startBtn=document.getElementById('dd-start');
|
|
303
|
+
var completeBtn=document.getElementById('dd-complete');
|
|
304
|
+
var submitBtn=document.getElementById('dd-submit');
|
|
305
|
+
|
|
306
|
+
backBtn.textContent=${backLabel};
|
|
307
|
+
startBtn.textContent=${startLabel};
|
|
308
|
+
completeBtn.textContent=${completeLabel};
|
|
309
|
+
submitBtn.textContent=${submitLabel};
|
|
310
|
+
|
|
311
|
+
document.getElementById('dd-close').onclick=function(){ emitJSON('popup_close'); };
|
|
312
|
+
backBtn.onclick=function(){ if(window.DeepdotsForm && window.DeepdotsForm.back){ window.DeepdotsForm.back(); } };
|
|
313
|
+
startBtn.onclick=function(){ if(window.DeepdotsForm && window.DeepdotsForm.startForm){ window.DeepdotsForm.startForm(); } };
|
|
314
|
+
completeBtn.onclick=function(){ emitJSON('popup_close'); };
|
|
315
|
+
var surveyCompletedEmitted=false;
|
|
316
|
+
submitBtn.onclick=function(){
|
|
317
|
+
if(surveyCompletedEmitted) return;
|
|
318
|
+
if(window.DeepdotsForm && window.DeepdotsForm.send){ window.DeepdotsForm.send(); }
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
function updateButtons(state){
|
|
322
|
+
backBtn.style.display='none';
|
|
323
|
+
startBtn.style.display='none';
|
|
324
|
+
submitBtn.style.display='none';
|
|
325
|
+
completeBtn.style.display='none';
|
|
326
|
+
backBtn.style.width='';
|
|
327
|
+
startBtn.style.width='';
|
|
328
|
+
submitBtn.style.width='';
|
|
329
|
+
completeBtn.style.width='';
|
|
330
|
+
if(state==='start'){
|
|
331
|
+
startBtn.style.display='inline-flex';
|
|
332
|
+
startBtn.style.width='100%';
|
|
333
|
+
} else if(state==='in_progress_first'){
|
|
334
|
+
submitBtn.style.display='inline-flex';
|
|
335
|
+
} else if(state==='in_progress_next'){
|
|
336
|
+
backBtn.style.display='inline-flex';
|
|
337
|
+
submitBtn.style.display='inline-flex';
|
|
338
|
+
} else if(state==='completed'){
|
|
339
|
+
completeBtn.style.display='inline-flex';
|
|
340
|
+
completeBtn.style.width='100%';
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function setLoading(isLoading){
|
|
345
|
+
spinner.style.display=isLoading?'flex':'none';
|
|
346
|
+
if(!isLoading){ formHost.style.visibility='visible'; }
|
|
347
|
+
footer.style.display=isLoading?'none':'flex';
|
|
348
|
+
backBtn.disabled=isLoading; startBtn.disabled=isLoading; completeBtn.disabled=isLoading; submitBtn.disabled=isLoading;
|
|
349
|
+
if(isLoading){ updateButtons(null); }
|
|
350
|
+
}
|
|
351
|
+
setLoading(true);
|
|
352
|
+
|
|
219
353
|
var initialized=false;
|
|
220
354
|
function initMF(){
|
|
221
355
|
if(initialized || !window.magicfeedback) return initialized;
|
|
@@ -224,23 +358,85 @@ function buildSurveyHtml(opts) {
|
|
|
224
358
|
window.magicfeedback.init({ debug:false, env:'${env}' });
|
|
225
359
|
var form = window.magicfeedback.form(${sid}, ${pid}, ${profileJson}, ${metaJson});
|
|
226
360
|
window.DeepdotsForm = form;
|
|
361
|
+
var stylesInjected=false;
|
|
227
362
|
form.generate('mf', {
|
|
228
363
|
addButton:false,
|
|
229
364
|
getMetaData:true,
|
|
230
|
-
onLoadedEvent:function(){
|
|
231
|
-
|
|
365
|
+
onLoadedEvent:function(args){
|
|
366
|
+
var s=args && args.formData ? args.formData.style : null;
|
|
367
|
+
if(s && !stylesInjected){
|
|
368
|
+
stylesInjected=true;
|
|
369
|
+
if(s.boxBackgroundColor){ popup.style.background=s.boxBackgroundColor; }
|
|
370
|
+
if(s.contentAlign){ main.style.justifyContent = s.contentAlign==='center' ? 'center' : 'flex-start'; }
|
|
371
|
+
if(s.buttonPrimaryColor){
|
|
372
|
+
submitBtn.style.background=s.buttonPrimaryColor; submitBtn.style.border='none'; submitBtn.style.color='#fff';
|
|
373
|
+
startBtn.style.background=s.buttonPrimaryColor; startBtn.style.border='none'; startBtn.style.color='#fff';
|
|
374
|
+
completeBtn.style.background=s.buttonPrimaryColor; completeBtn.style.border='none'; completeBtn.style.color='#fff';
|
|
375
|
+
}
|
|
376
|
+
if(s.buttonSecondaryColor){
|
|
377
|
+
backBtn.style.background='#fff'; backBtn.style.color=s.buttonSecondaryColor; backBtn.style.border='1px solid '+s.buttonSecondaryColor;
|
|
378
|
+
}
|
|
379
|
+
if(s.logo && !document.getElementById('dd-logo')){
|
|
380
|
+
var logoImg=document.createElement('img');
|
|
381
|
+
logoImg.id='dd-logo'; logoImg.src=s.logo; logoImg.alt='Logo';
|
|
382
|
+
if(s.logoSize==='small'){ logoImg.style.maxHeight='30px'; }
|
|
383
|
+
else if(s.logoSize==='medium'){ logoImg.style.maxHeight='50px'; }
|
|
384
|
+
else if(s.logoSize==='large'){ logoImg.style.maxHeight='70px'; }
|
|
385
|
+
if(s.logoPosition==='left'){ logoImg.style.margin='0 16px 20px 0'; logoImg.style.display='block'; logoImg.style.marginLeft='0'; }
|
|
386
|
+
else if(s.logoPosition==='right'){ logoImg.style.margin='0 0 20px 16px'; logoImg.style.display='block'; logoImg.style.marginLeft='auto'; }
|
|
387
|
+
else if(s.logoPosition==='center'){ logoImg.style.margin='0 auto 20px auto'; logoImg.style.display='block'; }
|
|
388
|
+
main.insertBefore(logoImg, document.getElementById('dd-form-wrapper'));
|
|
389
|
+
}
|
|
390
|
+
if(s.startMessage && s.startMessage!==''){ updateButtons('start'); }
|
|
391
|
+
else { updateButtons('in_progress_first'); }
|
|
392
|
+
} else {
|
|
393
|
+
updateButtons('in_progress_first');
|
|
394
|
+
}
|
|
395
|
+
emitJSON('loaded');
|
|
396
|
+
setLoading(false);
|
|
397
|
+
},
|
|
398
|
+
beforeSubmitEvent:function(){
|
|
399
|
+
setLoading(true);
|
|
400
|
+
emitJSON('before_submit');
|
|
401
|
+
},
|
|
232
402
|
afterSubmitEvent:function(p){
|
|
233
|
-
|
|
234
|
-
|
|
403
|
+
var error=p && p.error ? (typeof p.error==='string' ? p.error : String(p.error)) : '';
|
|
404
|
+
if(error){
|
|
405
|
+
setLoading(false);
|
|
406
|
+
if(error.toLowerCase().indexOf('no response')!==-1){
|
|
407
|
+
errorHint.textContent='Please answer the required question to continue.';
|
|
408
|
+
errorHint.style.display='block';
|
|
409
|
+
updateButtons('in_progress_next');
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
errorHint.textContent='An error occurred while submitting. Please try again or close the popup.';
|
|
413
|
+
errorHint.style.display='block';
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
errorHint.style.display='none';
|
|
417
|
+
setLoading(false);
|
|
418
|
+
if(p && p.completed){
|
|
419
|
+
surveyCompletedEmitted=true;
|
|
420
|
+
updateButtons('completed');
|
|
421
|
+
emitJSON('survey_completed', p);
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
if(p && p.total>1 && p.progress>0 && p.progress<p.total){ updateButtons('in_progress_next'); }
|
|
425
|
+
else { updateButtons('in_progress_first'); }
|
|
426
|
+
emitJSON('after_submit', p);
|
|
235
427
|
},
|
|
236
|
-
onBackEvent:function(p){
|
|
237
|
-
|
|
238
|
-
|
|
428
|
+
onBackEvent:function(p){
|
|
429
|
+
if(p && p.progress===0){ updateButtons('in_progress_first'); }
|
|
430
|
+
else { updateButtons('in_progress_next'); }
|
|
431
|
+
emitJSON('back', p);
|
|
432
|
+
}
|
|
433
|
+
}).catch(function(e){ setLoading(false); emit('error:init'); });
|
|
434
|
+
}catch(e){ setLoading(false); emit('error:exception'); }
|
|
239
435
|
return true;
|
|
240
436
|
}
|
|
241
437
|
var s=document.createElement('script'); s.src=${JSON.stringify(cdn)}; s.async=true;
|
|
242
438
|
s.onload=function(){ initMF(); };
|
|
243
|
-
s.onerror=function(){ emit('error:load'); };
|
|
439
|
+
s.onerror=function(){ setLoading(false); emit('error:load'); };
|
|
244
440
|
document.head.appendChild(s);
|
|
245
441
|
var tries=0, t=setInterval(function(){ if(initMF()||++tries>40){ clearInterval(t); } },150);
|
|
246
442
|
})();
|
|
@@ -259,18 +455,28 @@ var ReactNativePopupRenderer = class {
|
|
|
259
455
|
}
|
|
260
456
|
init() {
|
|
261
457
|
}
|
|
262
|
-
show(surveyId, productId,
|
|
458
|
+
show(surveyId, productId, actions, emit, onClose, env = "production", userId, style, sessionId, miniService, analyticsFeedbackSessionId) {
|
|
263
459
|
this.emitFn = emit;
|
|
264
460
|
this.onCloseFn = onClose;
|
|
265
461
|
this.currentSurveyId = surveyId;
|
|
266
462
|
this.partialEmitted = false;
|
|
267
463
|
const { profile, metadata } = buildSurveyIdentity(userId ?? null, sessionId ?? null, miniService ?? null, analyticsFeedbackSessionId ?? null);
|
|
268
|
-
const html = buildSurveyHtml({
|
|
464
|
+
const html = buildSurveyHtml({
|
|
465
|
+
surveyId,
|
|
466
|
+
productId,
|
|
467
|
+
env,
|
|
468
|
+
profile,
|
|
469
|
+
metadata,
|
|
470
|
+
font: style?.font,
|
|
471
|
+
theme: style?.theme,
|
|
472
|
+
position: style?.position,
|
|
473
|
+
actions
|
|
474
|
+
});
|
|
269
475
|
if (this.options.onShow) {
|
|
270
476
|
this.options.onShow({ surveyId, productId, html });
|
|
271
477
|
} else {
|
|
272
478
|
sdkWarn(
|
|
273
|
-
"[Deepdots] ReactNativePopupRenderer
|
|
479
|
+
"[Deepdots] ReactNativePopupRenderer has no onShow: pass { onShow } to new ReactNativePopupRenderer({...}) to mount the survey WebView."
|
|
274
480
|
);
|
|
275
481
|
}
|
|
276
482
|
}
|
|
@@ -361,7 +567,7 @@ var BrowserPopupRenderer = class {
|
|
|
361
567
|
if (!this.container) return;
|
|
362
568
|
this.visible = true;
|
|
363
569
|
const container = this.container;
|
|
364
|
-
void import("./renderPopup-
|
|
570
|
+
void import("./renderPopup-NJK7Z46E.mjs").then(({ renderPopup }) => {
|
|
365
571
|
renderPopup(container, surveyId, productId, actions, emit, onClose, env, userId, style, sessionId, miniService, analyticsFeedbackSessionId);
|
|
366
572
|
});
|
|
367
573
|
}
|
|
@@ -385,7 +591,7 @@ function createDefaultRenderer() {
|
|
|
385
591
|
// src/analytics/analytics-manager.ts
|
|
386
592
|
function createDryRunSink(log = console.log) {
|
|
387
593
|
return (payload) => log(
|
|
388
|
-
"[DeepdotsAnalytics] (dry-run \xB7
|
|
594
|
+
"[DeepdotsAnalytics] (dry-run \xB7 NOT sent \xB7 no init.analytics) POST /sdk/feedback \u2192",
|
|
389
595
|
JSON.stringify(payload, null, 2)
|
|
390
596
|
);
|
|
391
597
|
}
|
|
@@ -454,6 +660,15 @@ var AnalyticsManager = class {
|
|
|
454
660
|
this.exitMiniService(name);
|
|
455
661
|
}
|
|
456
662
|
}
|
|
663
|
+
/**
|
|
664
|
+
* Olvida lo que pertenecía al usuario anterior (user attributes + métricas) al cambiar de
|
|
665
|
+
* usuario. NO toca el buffer de eventos: el cierre de sesión ya lo vació con la identidad
|
|
666
|
+
* vieja, y lo que llegue después es del usuario nuevo.
|
|
667
|
+
*/
|
|
668
|
+
resetUserScope() {
|
|
669
|
+
this.attributes = {};
|
|
670
|
+
this.metrics = {};
|
|
671
|
+
}
|
|
457
672
|
/** Registra un evento de analítica (modelo GA: nombre + params). */
|
|
458
673
|
track(name, params) {
|
|
459
674
|
const current = this.getMiniService();
|
|
@@ -541,7 +756,7 @@ function pushKV(list, key, value) {
|
|
|
541
756
|
if (value === void 0 || value === null || value === "") return;
|
|
542
757
|
list.push({ key, value: [String(value)] });
|
|
543
758
|
}
|
|
544
|
-
function buildAnalyticsFeedbackBody(envelope, keys, feedbackSessionId) {
|
|
759
|
+
function buildAnalyticsFeedbackBody(envelope, keys, feedbackSessionId, options) {
|
|
545
760
|
const { context } = envelope;
|
|
546
761
|
const profile = [];
|
|
547
762
|
pushKV(profile, "external-user-id", envelope.userId);
|
|
@@ -592,7 +807,8 @@ function buildAnalyticsFeedbackBody(envelope, keys, feedbackSessionId) {
|
|
|
592
807
|
},
|
|
593
808
|
publicKey: keys.publicKey,
|
|
594
809
|
integration: keys.integration,
|
|
595
|
-
|
|
810
|
+
// Único marcador de cierre acordado con backend: el último lote de la sesión.
|
|
811
|
+
completed: options?.sessionEnd === true,
|
|
596
812
|
...feedbackSessionId ? { sessionId: feedbackSessionId } : {}
|
|
597
813
|
};
|
|
598
814
|
}
|
|
@@ -611,20 +827,20 @@ function createFeedbackSink(options) {
|
|
|
611
827
|
let feedbackSessionId;
|
|
612
828
|
let firstPostInFlight = null;
|
|
613
829
|
const url = `${options.baseUrl}/sdk/feedback`;
|
|
614
|
-
const post = async (body, final) => {
|
|
830
|
+
const post = async (body, final, sessionEnd = false) => {
|
|
615
831
|
const json = JSON.stringify(body);
|
|
616
832
|
const small = json.length <= KEEPALIVE_MAX_BYTES;
|
|
617
833
|
if (final && options.sendBeaconImpl && small) {
|
|
618
834
|
const payload = typeof Blob !== "undefined" ? new Blob([json], { type: "application/json" }) : json;
|
|
619
835
|
if (options.sendBeaconImpl(url, payload)) {
|
|
620
|
-
options.log?.("[DeepdotsAnalytics] flush
|
|
836
|
+
options.log?.("[DeepdotsAnalytics] final flush via sendBeacon");
|
|
621
837
|
return;
|
|
622
838
|
}
|
|
623
|
-
options.log?.("[DeepdotsAnalytics] sendBeacon
|
|
839
|
+
options.log?.("[DeepdotsAnalytics] sendBeacon rejected the batch; falling back to fetch");
|
|
624
840
|
}
|
|
625
841
|
const f = options.fetchImpl ?? (typeof fetch !== "undefined" ? fetch : void 0);
|
|
626
842
|
if (!f) {
|
|
627
|
-
options.log?.("[DeepdotsAnalytics] no fetch
|
|
843
|
+
options.log?.("[DeepdotsAnalytics] no fetch available; payload not sent", body);
|
|
628
844
|
return;
|
|
629
845
|
}
|
|
630
846
|
const res = await f(url, {
|
|
@@ -637,19 +853,20 @@ function createFeedbackSink(options) {
|
|
|
637
853
|
if (!res.ok) {
|
|
638
854
|
const detail = await safeBodyText(res);
|
|
639
855
|
if (isRetryableStatus(res.status)) {
|
|
640
|
-
throw new Error(`POST /sdk/feedback ${res.status} (
|
|
856
|
+
throw new Error(`POST /sdk/feedback ${res.status} (retryable): ${detail}`);
|
|
641
857
|
}
|
|
642
858
|
options.log?.(
|
|
643
|
-
`[DeepdotsAnalytics] POST /sdk/feedback
|
|
859
|
+
`[DeepdotsAnalytics] POST /sdk/feedback rejected with ${res.status}; batch DISCARDED:`,
|
|
644
860
|
detail
|
|
645
861
|
);
|
|
646
862
|
return;
|
|
647
863
|
}
|
|
864
|
+
if (sessionEnd) return;
|
|
648
865
|
try {
|
|
649
866
|
const data = await res.json();
|
|
650
867
|
if (data?.sessionId && data.sessionId !== feedbackSessionId) {
|
|
651
868
|
feedbackSessionId = data.sessionId;
|
|
652
|
-
options.log?.("[DeepdotsAnalytics] feedbackSessionId
|
|
869
|
+
options.log?.("[DeepdotsAnalytics] feedbackSessionId cached:", feedbackSessionId);
|
|
653
870
|
options.onSessionId?.(feedbackSessionId);
|
|
654
871
|
}
|
|
655
872
|
} catch {
|
|
@@ -657,13 +874,18 @@ function createFeedbackSink(options) {
|
|
|
657
874
|
};
|
|
658
875
|
return async (envelope, meta) => {
|
|
659
876
|
const final = meta?.final === true;
|
|
877
|
+
const sessionEnd = meta?.sessionEnd === true;
|
|
660
878
|
if (!feedbackSessionId && firstPostInFlight && !final) {
|
|
661
879
|
await firstPostInFlight;
|
|
662
880
|
}
|
|
663
|
-
const body = buildAnalyticsFeedbackBody(envelope, options.keys, feedbackSessionId);
|
|
881
|
+
const body = buildAnalyticsFeedbackBody(envelope, options.keys, feedbackSessionId, { sessionEnd });
|
|
664
882
|
options.log?.("[DeepdotsAnalytics] POST /sdk/feedback \u2192", body);
|
|
665
|
-
const sent = post(body, final);
|
|
666
|
-
if (
|
|
883
|
+
const sent = post(body, final, sessionEnd);
|
|
884
|
+
if (sessionEnd) {
|
|
885
|
+
feedbackSessionId = void 0;
|
|
886
|
+
firstPostInFlight = null;
|
|
887
|
+
options.onSessionReset?.();
|
|
888
|
+
} else if (!feedbackSessionId) {
|
|
667
889
|
firstPostInFlight = sent.then(
|
|
668
890
|
() => void 0,
|
|
669
891
|
() => void 0
|
|
@@ -1098,6 +1320,7 @@ var CrashReporter = class {
|
|
|
1098
1320
|
};
|
|
1099
1321
|
|
|
1100
1322
|
// src/analytics/messaging.ts
|
|
1323
|
+
var MESSAGE_CHANNELS = ["push", "in_app"];
|
|
1101
1324
|
function buildMessageParams(stage, o) {
|
|
1102
1325
|
const p = {
|
|
1103
1326
|
stage,
|
|
@@ -1110,6 +1333,57 @@ function buildMessageParams(stage, o) {
|
|
|
1110
1333
|
if (o.currency) p.currency = o.currency;
|
|
1111
1334
|
return { ...p, ...o.params ?? {} };
|
|
1112
1335
|
}
|
|
1336
|
+
var MAX_TRACKED_MESSAGES = 500;
|
|
1337
|
+
var MessageGuard = class {
|
|
1338
|
+
constructor(maxTrackedMessages = MAX_TRACKED_MESSAGES) {
|
|
1339
|
+
this.maxTrackedMessages = maxTrackedMessages;
|
|
1340
|
+
/** message_id → canal fijado + stages ya emitidos. El orden de inserción marca la eviction. */
|
|
1341
|
+
this.seen = /* @__PURE__ */ new Map();
|
|
1342
|
+
}
|
|
1343
|
+
evaluate(stage, options) {
|
|
1344
|
+
const channel = options.channel;
|
|
1345
|
+
if (!MESSAGE_CHANNELS.includes(channel)) {
|
|
1346
|
+
return {
|
|
1347
|
+
emit: false,
|
|
1348
|
+
reason: "invalid_channel",
|
|
1349
|
+
detail: `invalid channel "${channel}" (expected ${MESSAGE_CHANNELS.join(" | ")})`
|
|
1350
|
+
};
|
|
1351
|
+
}
|
|
1352
|
+
const entry = this.seen.get(options.id);
|
|
1353
|
+
if (!entry) {
|
|
1354
|
+
this.remember(options.id, channel, stage);
|
|
1355
|
+
return { emit: true };
|
|
1356
|
+
}
|
|
1357
|
+
if (entry.channel !== channel) {
|
|
1358
|
+
return {
|
|
1359
|
+
emit: false,
|
|
1360
|
+
reason: "channel_conflict",
|
|
1361
|
+
detail: `message_id "${options.id}" was already reported on channel "${entry.channel}"; discarding "${channel}"`
|
|
1362
|
+
};
|
|
1363
|
+
}
|
|
1364
|
+
if (entry.stages.has(stage)) {
|
|
1365
|
+
return {
|
|
1366
|
+
emit: false,
|
|
1367
|
+
reason: "duplicate_stage",
|
|
1368
|
+
detail: `stage "${stage}" was already sent for message_id "${options.id}"`
|
|
1369
|
+
};
|
|
1370
|
+
}
|
|
1371
|
+
entry.stages.add(stage);
|
|
1372
|
+
return { emit: true };
|
|
1373
|
+
}
|
|
1374
|
+
/** Olvida todo lo vigilado (nueva sesión). */
|
|
1375
|
+
reset() {
|
|
1376
|
+
this.seen.clear();
|
|
1377
|
+
}
|
|
1378
|
+
remember(id, channel, stage) {
|
|
1379
|
+
this.seen.set(id, { channel, stages: /* @__PURE__ */ new Set([stage]) });
|
|
1380
|
+
while (this.seen.size > this.maxTrackedMessages) {
|
|
1381
|
+
const oldest = this.seen.keys().next();
|
|
1382
|
+
if (oldest.done) break;
|
|
1383
|
+
this.seen.delete(oldest.value);
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
};
|
|
1113
1387
|
|
|
1114
1388
|
// src/core/deepdots-popups.ts
|
|
1115
1389
|
var EXIT_QUEUE_STORAGE_KEY = "__deepdots_exit_popup_queue__";
|
|
@@ -1151,14 +1425,24 @@ var DeepdotsPopups = class {
|
|
|
1151
1425
|
this.analyticsFlushTimer = void 0;
|
|
1152
1426
|
/** Crash & error reporting (#14–17). Null hasta init(). */
|
|
1153
1427
|
this.crashReporter = null;
|
|
1428
|
+
/** Protecciones del funnel de Messaging (#18–22). Vigencia de sesión: se reinicia en init(). */
|
|
1429
|
+
this.messageGuard = new MessageGuard();
|
|
1154
1430
|
/** Observador de navegación (Fase 2): emite page_view por el canal de analytics. */
|
|
1155
1431
|
this.navObserver = null;
|
|
1156
1432
|
/** Tiempo activo (engagement time, #8). */
|
|
1157
1433
|
this.engagement = null;
|
|
1158
1434
|
/** Atributos internos del usuario identificado → POST /sdk/popups/contact. Null si no hay userId. */
|
|
1159
1435
|
this.contact = null;
|
|
1436
|
+
/** Storage resuelto en init() (inyectado por el host o localStorage). Reusado al cambiar de usuario. */
|
|
1437
|
+
this.storage = null;
|
|
1160
1438
|
/** Marca si ya se inició la navegación manual (setScreen) — para RN sin History API. */
|
|
1161
1439
|
this.navStarted = false;
|
|
1440
|
+
/**
|
|
1441
|
+
* `true` entre `session_start` y `session_end`. Hace idempotente tanto la apertura como
|
|
1442
|
+
* el cierre (p. ej. `visibilitychange` + `pagehide` seguidos) y permite abrir una sesión
|
|
1443
|
+
* nueva al volver a foreground o al conceder el consentimiento más tarde.
|
|
1444
|
+
*/
|
|
1445
|
+
this.sessionOpen = false;
|
|
1162
1446
|
/**
|
|
1163
1447
|
* Idioma resuelto en init() (explícito > navigator.language > Intl). Única fuente de
|
|
1164
1448
|
* verdad para el context de analytics Y para la segmentación por idioma de los popups.
|
|
@@ -1170,6 +1454,11 @@ var DeepdotsPopups = class {
|
|
|
1170
1454
|
this.logger = config.logger ?? console;
|
|
1171
1455
|
setLogger(this.logger);
|
|
1172
1456
|
if (this.initialized) {
|
|
1457
|
+
const nextUserId = config.userId || void 0;
|
|
1458
|
+
if (nextUserId !== this.config?.userId) {
|
|
1459
|
+
this.setUserId(nextUserId);
|
|
1460
|
+
return;
|
|
1461
|
+
}
|
|
1173
1462
|
this.log("SDK already initialized");
|
|
1174
1463
|
return;
|
|
1175
1464
|
}
|
|
@@ -1182,6 +1471,7 @@ var DeepdotsPopups = class {
|
|
|
1182
1471
|
userId: config.userId || void 0
|
|
1183
1472
|
};
|
|
1184
1473
|
const storage = config.storage ?? createDefaultStorage();
|
|
1474
|
+
this.storage = storage;
|
|
1185
1475
|
this.tracking = new TrackingManager({
|
|
1186
1476
|
storage,
|
|
1187
1477
|
clientUserId: this.config.userId,
|
|
@@ -1209,6 +1499,9 @@ var DeepdotsPopups = class {
|
|
|
1209
1499
|
sendBeaconImpl: typeof navigator !== "undefined" && typeof navigator.sendBeacon === "function" ? (url, body) => navigator.sendBeacon(url, body) : void 0,
|
|
1210
1500
|
onSessionId: (id) => {
|
|
1211
1501
|
this.analyticsFeedbackSessionId = id;
|
|
1502
|
+
},
|
|
1503
|
+
onSessionReset: () => {
|
|
1504
|
+
this.analyticsFeedbackSessionId = void 0;
|
|
1212
1505
|
}
|
|
1213
1506
|
}) : createDryRunSink((...a) => this.logger.log(...a));
|
|
1214
1507
|
const device = config.device ?? collectDeviceInfo(config.appVersion);
|
|
@@ -1217,6 +1510,7 @@ var DeepdotsPopups = class {
|
|
|
1217
1510
|
navigator: typeof navigator !== "undefined" ? navigator : void 0,
|
|
1218
1511
|
intl: typeof Intl !== "undefined" ? Intl : void 0
|
|
1219
1512
|
});
|
|
1513
|
+
this.messageGuard.reset();
|
|
1220
1514
|
this.analytics = new AnalyticsManager({
|
|
1221
1515
|
sink: analyticsSink,
|
|
1222
1516
|
publicKey: config.analytics?.publicKey ?? this.config.apiKey,
|
|
@@ -1252,7 +1546,7 @@ var DeepdotsPopups = class {
|
|
|
1252
1546
|
this.engagement = new EngagementTracker();
|
|
1253
1547
|
this.engagement.resume();
|
|
1254
1548
|
this.setupAnalyticsFlush();
|
|
1255
|
-
this.
|
|
1549
|
+
this.openSession();
|
|
1256
1550
|
const pendingCrashes = this.crashReporter.drainPendingCrashes();
|
|
1257
1551
|
if (this.tracking?.isTrackingEnabled()) {
|
|
1258
1552
|
for (const rec of pendingCrashes) {
|
|
@@ -1284,7 +1578,9 @@ var DeepdotsPopups = class {
|
|
|
1284
1578
|
}
|
|
1285
1579
|
/** Activa/desactiva el tracking (identidad + sesión + analytics). Kill-switch del contrato §7bis. */
|
|
1286
1580
|
setTrackingEnabled(enabled) {
|
|
1581
|
+
if (!enabled) this.closeSession("tracking_disabled");
|
|
1287
1582
|
this.tracking?.setTrackingEnabled(enabled);
|
|
1583
|
+
if (enabled) this.openSession();
|
|
1288
1584
|
this.log("tracking \xB7 setTrackingEnabled:", enabled, "\xB7 session_id:", this.tracking?.getSessionId() ?? null);
|
|
1289
1585
|
}
|
|
1290
1586
|
// ───────── Analytics (canal separado del feedback, vinculado por user_id) ─────────
|
|
@@ -1354,8 +1650,18 @@ var DeepdotsPopups = class {
|
|
|
1354
1650
|
trackFunnelStep(funnel, step, taskId, params) {
|
|
1355
1651
|
this.track("deepdots_funnel_step", { funnel, step, task_id: taskId, ...params ?? {} });
|
|
1356
1652
|
}
|
|
1357
|
-
/**
|
|
1653
|
+
/**
|
|
1654
|
+
* Messaging (#18–22): registra una etapa del funnel de una notificación (push/in-app).
|
|
1655
|
+
* No-op si tracking off. El evento se descarta (con warning) si el `channel` no es válido,
|
|
1656
|
+
* si ese `(message_id, stage)` ya se emitió en la sesión, o si el `message_id` ya se reportó
|
|
1657
|
+
* en otro canal — ver `MessageGuard`.
|
|
1658
|
+
*/
|
|
1358
1659
|
trackMessage(stage, options) {
|
|
1660
|
+
const verdict = this.messageGuard.evaluate(stage, options);
|
|
1661
|
+
if (!verdict.emit) {
|
|
1662
|
+
console.warn(`[DeepdotsPopups] trackMessage discarded (${verdict.reason}): ${verdict.detail}`);
|
|
1663
|
+
return;
|
|
1664
|
+
}
|
|
1359
1665
|
this.track("deepdots_message", buildMessageParams(stage, options));
|
|
1360
1666
|
}
|
|
1361
1667
|
/**
|
|
@@ -1371,21 +1677,86 @@ var DeepdotsPopups = class {
|
|
|
1371
1677
|
this.navObserver.visit(name);
|
|
1372
1678
|
}
|
|
1373
1679
|
}
|
|
1374
|
-
/** App a foreground (RN: AppState 'active'): reanuda el engagement time. */
|
|
1680
|
+
/** App a foreground (RN: AppState 'active'): reanuda el engagement time y abre sesión nueva. */
|
|
1375
1681
|
onForeground() {
|
|
1376
1682
|
this.engagement?.resume();
|
|
1683
|
+
this.openSession();
|
|
1377
1684
|
}
|
|
1378
1685
|
/**
|
|
1379
|
-
* App a background (RN: AppState 'background'):
|
|
1380
|
-
* mini-
|
|
1686
|
+
* App a background (RN: AppState 'background'): FIN DE SESIÓN. Cierra pantalla actual
|
|
1687
|
+
* (page_view), mini-services (mini_service_exit), emite engagement + `session_end` y
|
|
1688
|
+
* envía el último lote con `completed:true`.
|
|
1689
|
+
*
|
|
1690
|
+
* Es la única señal disponible en móvil: el kill de la app (swipe) NO da callback.
|
|
1381
1691
|
*/
|
|
1382
1692
|
onBackground() {
|
|
1693
|
+
this.closeSession("background");
|
|
1694
|
+
this.engagement?.pause();
|
|
1695
|
+
}
|
|
1696
|
+
/**
|
|
1697
|
+
* Cierre EXPLÍCITO de la sesión por parte del host (logout, fin de flujo…): emite
|
|
1698
|
+
* `session_end` y envía el último lote con `completed:true`.
|
|
1699
|
+
*/
|
|
1700
|
+
endSession() {
|
|
1701
|
+
this.closeSession("manual");
|
|
1702
|
+
}
|
|
1703
|
+
/**
|
|
1704
|
+
* Cambio de usuario (login / logout / cambio de cuenta). Cierra la sesión del usuario
|
|
1705
|
+
* anterior (`session_end` con `reason: 'user_change'` + `completed:true`), cambia la
|
|
1706
|
+
* identidad y abre una sesión nueva. Sin `userId` vuelve al id anónimo del SDK.
|
|
1707
|
+
*
|
|
1708
|
+
* Equivale a llamar a `init()` otra vez con otro `userId`.
|
|
1709
|
+
*/
|
|
1710
|
+
setUserId(userId) {
|
|
1711
|
+
const next = userId || void 0;
|
|
1712
|
+
if (!this.initialized || !this.config || next === this.config.userId) return;
|
|
1713
|
+
this.closeSession("user_change");
|
|
1714
|
+
const enabled = this.tracking?.isTrackingEnabled() ?? true;
|
|
1715
|
+
const storage = this.storage ?? createDefaultStorage();
|
|
1716
|
+
this.config.userId = next;
|
|
1717
|
+
this.tracking = new TrackingManager({ storage, clientUserId: next, enabled });
|
|
1718
|
+
this.contact = next ? new ContactManager({
|
|
1719
|
+
storage,
|
|
1720
|
+
publicKey: this.config.apiKey ?? "",
|
|
1721
|
+
userId: next,
|
|
1722
|
+
post: (body) => this.postContact(body)
|
|
1723
|
+
}) : null;
|
|
1724
|
+
this.analytics?.resetUserScope();
|
|
1725
|
+
this.messageGuard.reset();
|
|
1726
|
+
this.log("tracking \xB7 user_change \xB7 user_id:", this.tracking.getUserId());
|
|
1727
|
+
this.openSession();
|
|
1728
|
+
}
|
|
1729
|
+
/**
|
|
1730
|
+
* Cierra la sesión actual: vuelca todo lo que quedaba abierto y envía el último lote
|
|
1731
|
+
* marcado con `completed:true`, para que el backend cierre el registro. El `sessionId`
|
|
1732
|
+
* cacheado se olvida → el lote siguiente abre un registro nuevo.
|
|
1733
|
+
*
|
|
1734
|
+
* Idempotente: dos cierres seguidos (p. ej. `visibilitychange` + `pagehide`) no duplican
|
|
1735
|
+
* el `session_end`.
|
|
1736
|
+
*/
|
|
1737
|
+
closeSession(reason) {
|
|
1738
|
+
if (!this.sessionOpen) return;
|
|
1739
|
+
if (!this.tracking?.isTrackingEnabled()) return;
|
|
1740
|
+
this.sessionOpen = false;
|
|
1383
1741
|
this.navObserver?.stop();
|
|
1384
1742
|
this.navStarted = false;
|
|
1385
|
-
|
|
1743
|
+
this.analytics?.exitAllMiniServices();
|
|
1386
1744
|
this.flushEngagement();
|
|
1387
|
-
this.
|
|
1388
|
-
this.flushAnalytics();
|
|
1745
|
+
this.track("deepdots_session_end", { reason });
|
|
1746
|
+
this.flushAnalytics({ final: reason === "page_hide", sessionEnd: true });
|
|
1747
|
+
this.analyticsFeedbackSessionId = void 0;
|
|
1748
|
+
this.tracking?.setSessionId(null);
|
|
1749
|
+
this.log("tracking \xB7 session_end:", reason);
|
|
1750
|
+
}
|
|
1751
|
+
/**
|
|
1752
|
+
* Abre sesión (`session_start`) si no hay una abierta y el tracking está activo. Idempotente:
|
|
1753
|
+
* se llama en init(), al volver a foreground y al conceder el consentimiento.
|
|
1754
|
+
*/
|
|
1755
|
+
openSession() {
|
|
1756
|
+
if (this.sessionOpen) return;
|
|
1757
|
+
if (!this.tracking?.isTrackingEnabled()) return;
|
|
1758
|
+
this.sessionOpen = true;
|
|
1759
|
+
this.track("deepdots_session_start", {});
|
|
1389
1760
|
}
|
|
1390
1761
|
/** Payload que se ENVIARÍA al endpoint de analytics (no envía ni vacía el buffer). */
|
|
1391
1762
|
previewAnalytics() {
|
|
@@ -1423,10 +1794,7 @@ var DeepdotsPopups = class {
|
|
|
1423
1794
|
this.analyticsFlushTimer = setInterval(() => this.flushAnalytics(), ANALYTICS_FLUSH_INTERVAL_MS);
|
|
1424
1795
|
window.addEventListener("pagehide", () => {
|
|
1425
1796
|
clearInterval(this.analyticsFlushTimer);
|
|
1426
|
-
this.
|
|
1427
|
-
if (this.tracking?.isTrackingEnabled()) this.analytics?.exitAllMiniServices();
|
|
1428
|
-
this.flushEngagement();
|
|
1429
|
-
this.flushAnalytics({ final: true });
|
|
1797
|
+
this.closeSession("page_hide");
|
|
1430
1798
|
});
|
|
1431
1799
|
document.addEventListener("visibilitychange", () => {
|
|
1432
1800
|
if (document.visibilityState === "hidden") {
|
|
@@ -1888,7 +2256,7 @@ var DeepdotsPopups = class {
|
|
|
1888
2256
|
}
|
|
1889
2257
|
if (!this.popupContainer) return;
|
|
1890
2258
|
const container = this.popupContainer;
|
|
1891
|
-
void import("./renderPopup-
|
|
2259
|
+
void import("./renderPopup-NJK7Z46E.mjs").then(({ renderPopup }) => {
|
|
1892
2260
|
renderPopup(
|
|
1893
2261
|
container,
|
|
1894
2262
|
surveyId,
|
|
@@ -2101,7 +2469,8 @@ function setupReactNative(sdk, config, deps = {}) {
|
|
|
2101
2469
|
if (deps.appState?.addEventListener) {
|
|
2102
2470
|
subscription = deps.appState.addEventListener("change", (state) => {
|
|
2103
2471
|
if (state === "active") sdk.onForeground();
|
|
2104
|
-
else sdk.onBackground();
|
|
2472
|
+
else if (state === "background") sdk.onBackground();
|
|
2473
|
+
else sdk.flushAnalytics();
|
|
2105
2474
|
});
|
|
2106
2475
|
}
|
|
2107
2476
|
return () => {
|
|
@@ -2114,6 +2483,9 @@ export {
|
|
|
2114
2483
|
CrashReporter,
|
|
2115
2484
|
DeepdotsPopups,
|
|
2116
2485
|
InMemoryStorage,
|
|
2486
|
+
MAX_TRACKED_MESSAGES,
|
|
2487
|
+
MESSAGE_CHANNELS,
|
|
2488
|
+
MessageGuard,
|
|
2117
2489
|
NoopPopupRenderer,
|
|
2118
2490
|
POPUP_TRIGGER_CONDITION_STATUSES,
|
|
2119
2491
|
ReactNativePopupRenderer,
|