@magicfeedback/popup-sdk 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-5VVCJBND.mjs → chunk-6WTOQGET.mjs} +3 -2
- package/dist/chunk-6WTOQGET.mjs.map +1 -0
- package/dist/{chunk-M6PEFLLQ.mjs → chunk-IOAZQPZE.mjs} +3 -2
- package/dist/chunk-IOAZQPZE.mjs.map +1 -0
- package/dist/index.d.mts +32 -15
- package/dist/index.d.ts +32 -15
- package/dist/index.js +113 -29
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +112 -29
- package/dist/index.mjs.map +1 -1
- package/dist/react-native.d.mts +26 -10
- package/dist/react-native.d.ts +26 -10
- package/dist/react-native.js +113 -29
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +112 -29
- package/dist/react-native.mjs.map +1 -1
- package/dist/{renderPopup-7GGKR5BY.mjs → renderPopup-KBDWWSUU.mjs} +4 -4
- package/dist/renderPopup-KBDWWSUU.mjs.map +1 -0
- package/dist/{renderPopup-Y4WG3575.mjs → renderPopup-YLFRGPQN.mjs} +4 -4
- package/dist/renderPopup-YLFRGPQN.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-5VVCJBND.mjs.map +0 -1
- package/dist/chunk-M6PEFLLQ.mjs.map +0 -1
- package/dist/renderPopup-7GGKR5BY.mjs.map +0 -1
- package/dist/renderPopup-Y4WG3575.mjs.map +0 -1
package/dist/react-native.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
__require,
|
|
5
5
|
buildSurveyIdentity,
|
|
6
6
|
createDefaultStorage
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-IOAZQPZE.mjs";
|
|
8
8
|
|
|
9
9
|
// src/react-native/index.tsx
|
|
10
10
|
import { createContext, useContext, useEffect, useRef, useState } from "react";
|
|
@@ -258,12 +258,12 @@ var ReactNativePopupRenderer = class {
|
|
|
258
258
|
}
|
|
259
259
|
init() {
|
|
260
260
|
}
|
|
261
|
-
show(surveyId, productId, _actions, emit, onClose, env = "production", userId, _style, sessionId, miniService) {
|
|
261
|
+
show(surveyId, productId, _actions, emit, onClose, env = "production", userId, _style, sessionId, miniService, analyticsFeedbackSessionId) {
|
|
262
262
|
this.emitFn = emit;
|
|
263
263
|
this.onCloseFn = onClose;
|
|
264
264
|
this.currentSurveyId = surveyId;
|
|
265
265
|
this.partialEmitted = false;
|
|
266
|
-
const { profile, metadata } = buildSurveyIdentity(userId ?? null, sessionId ?? null, miniService ?? null);
|
|
266
|
+
const { profile, metadata } = buildSurveyIdentity(userId ?? null, sessionId ?? null, miniService ?? null, analyticsFeedbackSessionId ?? null);
|
|
267
267
|
const html = buildSurveyHtml({ surveyId, productId, env, profile, metadata });
|
|
268
268
|
if (this.options.onShow) {
|
|
269
269
|
this.options.onShow({ surveyId, productId, html });
|
|
@@ -354,14 +354,14 @@ var BrowserPopupRenderer = class {
|
|
|
354
354
|
document.body.appendChild(this.container);
|
|
355
355
|
}
|
|
356
356
|
}
|
|
357
|
-
show(surveyId, productId, actions, emit, onClose, env = "production", userId, style, sessionId, miniService) {
|
|
357
|
+
show(surveyId, productId, actions, emit, onClose, env = "production", userId, style, sessionId, miniService, analyticsFeedbackSessionId) {
|
|
358
358
|
if (this.visible) return;
|
|
359
359
|
if (!this.container || !document.body.contains(this.container)) this.init();
|
|
360
360
|
if (!this.container) return;
|
|
361
361
|
this.visible = true;
|
|
362
362
|
const container = this.container;
|
|
363
|
-
void import("./renderPopup-
|
|
364
|
-
renderPopup(container, surveyId, productId, actions, emit, onClose, env, userId, style, sessionId, miniService);
|
|
363
|
+
void import("./renderPopup-KBDWWSUU.mjs").then(({ renderPopup }) => {
|
|
364
|
+
renderPopup(container, surveyId, productId, actions, emit, onClose, env, userId, style, sessionId, miniService, analyticsFeedbackSessionId);
|
|
365
365
|
});
|
|
366
366
|
}
|
|
367
367
|
hide() {
|
|
@@ -400,6 +400,12 @@ var AnalyticsManager = class {
|
|
|
400
400
|
this.language = options.language;
|
|
401
401
|
this.device = options.device;
|
|
402
402
|
this.platform = options.platform ?? "web";
|
|
403
|
+
this.maxBatchSize = options.maxBatchSize ?? 20;
|
|
404
|
+
this.onFlushNeeded = options.onFlushNeeded;
|
|
405
|
+
}
|
|
406
|
+
/** Actualiza campos de device en runtime (p.ej. country/city tras resolver geo). */
|
|
407
|
+
updateDevice(partial) {
|
|
408
|
+
this.device = { ...this.device, ...partial };
|
|
403
409
|
}
|
|
404
410
|
/** Mezcla user attributes (se coercionan a string). Mutable en runtime. */
|
|
405
411
|
setUserAttributes(attrs) {
|
|
@@ -433,6 +439,9 @@ var AnalyticsManager = class {
|
|
|
433
439
|
timestamp: this.now(),
|
|
434
440
|
params: Object.keys(merged).length ? merged : void 0
|
|
435
441
|
});
|
|
442
|
+
if (this.events.length >= this.maxBatchSize) {
|
|
443
|
+
this.onFlushNeeded?.();
|
|
444
|
+
}
|
|
436
445
|
}
|
|
437
446
|
/** Mini-service activo (para inyectarlo en la metadata del survey, #33). */
|
|
438
447
|
getMiniService() {
|
|
@@ -470,44 +479,55 @@ var AnalyticsManager = class {
|
|
|
470
479
|
// src/analytics/feedback-payload.ts
|
|
471
480
|
function pushKV(list, key, value) {
|
|
472
481
|
if (value === void 0 || value === null || value === "") return;
|
|
473
|
-
list.push({ key, value: String(value) });
|
|
482
|
+
list.push({ key, value: [String(value)] });
|
|
474
483
|
}
|
|
475
484
|
function buildAnalyticsFeedbackBody(envelope, keys, feedbackSessionId) {
|
|
476
485
|
const { context } = envelope;
|
|
477
|
-
const metrics = envelope.events.map((e) => ({
|
|
478
|
-
key: e.name,
|
|
479
|
-
value: JSON.stringify({ timestamp: e.timestamp, ...e.params ?? {} })
|
|
480
|
-
}));
|
|
481
486
|
const profile = [];
|
|
482
487
|
pushKV(profile, "external-user-id", envelope.userId);
|
|
483
488
|
const metadata = [];
|
|
484
|
-
pushKV(metadata, "
|
|
485
|
-
pushKV(metadata, "
|
|
486
|
-
pushKV(metadata, "
|
|
487
|
-
pushKV(metadata, "
|
|
489
|
+
pushKV(metadata, "deepdots_user_id", envelope.userId);
|
|
490
|
+
pushKV(metadata, "deepdots_session_id", envelope.sessionId);
|
|
491
|
+
pushKV(metadata, "deepdots_platform", context.platform);
|
|
492
|
+
pushKV(metadata, "deepdots_language", context.language);
|
|
488
493
|
if (context.device) {
|
|
489
|
-
|
|
490
|
-
pushKV(metadata, "
|
|
491
|
-
pushKV(metadata, "
|
|
492
|
-
pushKV(metadata, "
|
|
493
|
-
pushKV(metadata, "
|
|
494
|
+
const d = context.device;
|
|
495
|
+
pushKV(metadata, "deepdots_device_type", d.device_type);
|
|
496
|
+
pushKV(metadata, "deepdots_os_version", d.os_version);
|
|
497
|
+
pushKV(metadata, "deepdots_device_model", d.device_model);
|
|
498
|
+
pushKV(metadata, "deepdots_app_version", d.app_version);
|
|
499
|
+
pushKV(metadata, "deepdots_user_agent", d.user_agent);
|
|
500
|
+
pushKV(metadata, "deepdots_timezone", d.timezone);
|
|
501
|
+
pushKV(metadata, "deepdots_referrer", d.referrer);
|
|
502
|
+
pushKV(metadata, "deepdots_viewport_size", d.viewport_size);
|
|
503
|
+
pushKV(metadata, "deepdots_screen_resolution", d.screen_resolution);
|
|
504
|
+
pushKV(metadata, "deepdots_pixel_ratio", d.pixel_ratio);
|
|
505
|
+
pushKV(metadata, "deepdots_entry_type", d.entry_type);
|
|
506
|
+
pushKV(metadata, "deepdots_page_load_ms", d.page_load_ms);
|
|
507
|
+
pushKV(metadata, "deepdots_connection_type", d.connection_type);
|
|
508
|
+
pushKV(metadata, "deepdots_country", d.country);
|
|
509
|
+
pushKV(metadata, "deepdots_city", d.city);
|
|
494
510
|
}
|
|
495
511
|
for (const [k, v] of Object.entries(context.attributes ?? {})) {
|
|
496
512
|
pushKV(metadata, k, v);
|
|
497
513
|
}
|
|
514
|
+
for (const e of envelope.events) {
|
|
515
|
+
metadata.push({
|
|
516
|
+
key: e.name,
|
|
517
|
+
value: [JSON.stringify({ timestamp: e.timestamp, ...e.params ?? {} })]
|
|
518
|
+
});
|
|
519
|
+
}
|
|
498
520
|
return {
|
|
499
521
|
feedback: {
|
|
500
522
|
text: "",
|
|
501
523
|
answers: [],
|
|
502
524
|
metadata,
|
|
503
|
-
metrics,
|
|
504
525
|
profile,
|
|
505
526
|
finished: false
|
|
506
527
|
},
|
|
507
528
|
publicKey: keys.publicKey,
|
|
508
529
|
integration: keys.integration,
|
|
509
530
|
completed: false,
|
|
510
|
-
// finished: false,
|
|
511
531
|
...feedbackSessionId ? { sessionId: feedbackSessionId } : {}
|
|
512
532
|
};
|
|
513
533
|
}
|
|
@@ -532,6 +552,7 @@ function createFeedbackSink(options) {
|
|
|
532
552
|
if (data?.sessionId && data.sessionId !== feedbackSessionId) {
|
|
533
553
|
feedbackSessionId = data.sessionId;
|
|
534
554
|
options.log?.("[DeepdotsAnalytics] feedbackSessionId cacheado:", feedbackSessionId);
|
|
555
|
+
options.onSessionId?.(feedbackSessionId);
|
|
535
556
|
}
|
|
536
557
|
} catch {
|
|
537
558
|
}
|
|
@@ -645,15 +666,57 @@ function parseDeviceType(ua) {
|
|
|
645
666
|
}
|
|
646
667
|
return "desktop";
|
|
647
668
|
}
|
|
669
|
+
function getEntryType() {
|
|
670
|
+
if (typeof performance === "undefined") return void 0;
|
|
671
|
+
const entries = performance.getEntriesByType("navigation");
|
|
672
|
+
if (!entries.length) return void 0;
|
|
673
|
+
return entries[0].type;
|
|
674
|
+
}
|
|
675
|
+
function getPageLoadMs() {
|
|
676
|
+
if (typeof performance === "undefined") return void 0;
|
|
677
|
+
const entries = performance.getEntriesByType("navigation");
|
|
678
|
+
if (!entries.length) return void 0;
|
|
679
|
+
const load = entries[0].loadEventEnd;
|
|
680
|
+
return load > 0 ? Math.round(load) : void 0;
|
|
681
|
+
}
|
|
682
|
+
function getConnectionType() {
|
|
683
|
+
if (typeof navigator === "undefined") return void 0;
|
|
684
|
+
return navigator.connection?.effectiveType ?? void 0;
|
|
685
|
+
}
|
|
648
686
|
function collectDeviceInfo(appVersion) {
|
|
649
687
|
const ua = typeof navigator !== "undefined" ? navigator.userAgent : "";
|
|
650
688
|
return {
|
|
651
689
|
device_type: parseDeviceType(ua),
|
|
652
690
|
user_agent: ua || void 0,
|
|
653
|
-
app_version: appVersion
|
|
691
|
+
app_version: appVersion,
|
|
692
|
+
timezone: typeof Intl !== "undefined" ? Intl.DateTimeFormat().resolvedOptions().timeZone : void 0,
|
|
693
|
+
referrer: typeof document !== "undefined" && document.referrer ? document.referrer : void 0,
|
|
694
|
+
viewport_size: typeof window !== "undefined" ? `${window.innerWidth}x${window.innerHeight}` : void 0,
|
|
695
|
+
screen_resolution: typeof screen !== "undefined" ? `${screen.width}x${screen.height}` : void 0,
|
|
696
|
+
pixel_ratio: typeof window !== "undefined" ? window.devicePixelRatio : void 0,
|
|
697
|
+
entry_type: getEntryType(),
|
|
698
|
+
page_load_ms: getPageLoadMs(),
|
|
699
|
+
connection_type: getConnectionType()
|
|
654
700
|
};
|
|
655
701
|
}
|
|
656
702
|
|
|
703
|
+
// src/analytics/geo-info.ts
|
|
704
|
+
async function collectGeoInfo(fetchImpl) {
|
|
705
|
+
const f = fetchImpl ?? (typeof fetch !== "undefined" ? fetch : void 0);
|
|
706
|
+
if (!f) return null;
|
|
707
|
+
try {
|
|
708
|
+
const res = await f("https://ipapi.co/json/");
|
|
709
|
+
if (!res.ok) return null;
|
|
710
|
+
const data = await res.json();
|
|
711
|
+
const country = data.country_code || void 0;
|
|
712
|
+
const city = data.city || void 0;
|
|
713
|
+
if (!country && !city) return null;
|
|
714
|
+
return { country, city };
|
|
715
|
+
} catch {
|
|
716
|
+
return null;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
657
720
|
// src/analytics/engagement-tracker.ts
|
|
658
721
|
var EngagementTracker = class {
|
|
659
722
|
constructor(now = () => Date.now()) {
|
|
@@ -724,6 +787,8 @@ var ContactManager = class {
|
|
|
724
787
|
// src/core/deepdots-popups.ts
|
|
725
788
|
var EXIT_QUEUE_STORAGE_KEY = "__deepdots_exit_popup_queue__";
|
|
726
789
|
var DAY_IN_MS = 24 * 60 * 60 * 1e3;
|
|
790
|
+
var ANALYTICS_MAX_BATCH_SIZE = 20;
|
|
791
|
+
var ANALYTICS_FLUSH_INTERVAL_MS = 3e4;
|
|
727
792
|
var DeepdotsPopups = class {
|
|
728
793
|
constructor() {
|
|
729
794
|
this.config = null;
|
|
@@ -749,6 +814,10 @@ var DeepdotsPopups = class {
|
|
|
749
814
|
this.tracking = null;
|
|
750
815
|
/** Capa de analytics (canal separado del feedback). Null hasta init(). */
|
|
751
816
|
this.analytics = null;
|
|
817
|
+
/** feedbackSessionId cacheado del canal de analytics (devuelto por POST /sdk/feedback). */
|
|
818
|
+
this.analyticsFeedbackSessionId = void 0;
|
|
819
|
+
/** Timer del flush periódico de analytics (cada ANALYTICS_FLUSH_INTERVAL_MS). */
|
|
820
|
+
this.analyticsFlushTimer = void 0;
|
|
752
821
|
/** Observador de navegación (Fase 2): emite page_view por el canal de analytics. */
|
|
753
822
|
this.navObserver = null;
|
|
754
823
|
/** Tiempo activo (engagement time, #8). */
|
|
@@ -795,14 +864,23 @@ var DeepdotsPopups = class {
|
|
|
795
864
|
const analyticsSink = config.analytics ? createFeedbackSink({
|
|
796
865
|
baseUrl: this.baseUrl,
|
|
797
866
|
keys: config.analytics,
|
|
798
|
-
log: (...a) => this.log(...a)
|
|
867
|
+
log: (...a) => this.log(...a),
|
|
868
|
+
onSessionId: (id) => {
|
|
869
|
+
this.analyticsFeedbackSessionId = id;
|
|
870
|
+
}
|
|
799
871
|
}) : void 0;
|
|
800
872
|
this.analytics = new AnalyticsManager({
|
|
801
873
|
sink: analyticsSink,
|
|
802
874
|
publicKey: config.analytics?.publicKey ?? this.config.apiKey,
|
|
803
875
|
language: typeof navigator !== "undefined" ? navigator.language : void 0,
|
|
804
876
|
platform: config.platform ?? "web",
|
|
805
|
-
device: config.device ?? collectDeviceInfo(config.appVersion)
|
|
877
|
+
device: config.device ?? collectDeviceInfo(config.appVersion),
|
|
878
|
+
maxBatchSize: ANALYTICS_MAX_BATCH_SIZE,
|
|
879
|
+
onFlushNeeded: () => this.flushAnalytics()
|
|
880
|
+
});
|
|
881
|
+
collectGeoInfo().then((geo) => {
|
|
882
|
+
if (geo) this.analytics?.updateDevice(geo);
|
|
883
|
+
}).catch(() => {
|
|
806
884
|
});
|
|
807
885
|
this.navObserver = new NavigationObserver();
|
|
808
886
|
this.navObserver.onVisit((v) => this.track("page_view", { screen: v.screen, duration_seconds: v.durationSeconds }));
|
|
@@ -943,7 +1021,9 @@ var DeepdotsPopups = class {
|
|
|
943
1021
|
/** Flush automático al ocultar/cerrar la página (no perder el lote pendiente). */
|
|
944
1022
|
setupAnalyticsFlush() {
|
|
945
1023
|
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
1024
|
+
this.analyticsFlushTimer = setInterval(() => this.flushAnalytics(), ANALYTICS_FLUSH_INTERVAL_MS);
|
|
946
1025
|
window.addEventListener("pagehide", () => {
|
|
1026
|
+
clearInterval(this.analyticsFlushTimer);
|
|
947
1027
|
this.navObserver?.stop();
|
|
948
1028
|
this.exitMiniService();
|
|
949
1029
|
this.flushEngagement();
|
|
@@ -1387,7 +1467,8 @@ var DeepdotsPopups = class {
|
|
|
1387
1467
|
const userId = this.tracking?.getUserId() ?? this.config?.userId;
|
|
1388
1468
|
const sessionId = this.tracking?.getSessionId() ?? void 0;
|
|
1389
1469
|
const miniService = this.analytics?.getMiniService() ?? void 0;
|
|
1390
|
-
|
|
1470
|
+
const analyticsFeedbackSessionId = this.analyticsFeedbackSessionId;
|
|
1471
|
+
this.log("tracking \xB7 survey identity \u2192", { userId: userId ?? null, sessionId: sessionId ?? null, miniService: miniService ?? null, analyticsFeedbackSessionId: analyticsFeedbackSessionId ?? null });
|
|
1391
1472
|
if (this.renderer) {
|
|
1392
1473
|
this.renderer.show(
|
|
1393
1474
|
surveyId,
|
|
@@ -1399,13 +1480,14 @@ var DeepdotsPopups = class {
|
|
|
1399
1480
|
userId,
|
|
1400
1481
|
style,
|
|
1401
1482
|
sessionId,
|
|
1402
|
-
miniService
|
|
1483
|
+
miniService,
|
|
1484
|
+
analyticsFeedbackSessionId
|
|
1403
1485
|
);
|
|
1404
1486
|
return;
|
|
1405
1487
|
}
|
|
1406
1488
|
if (!this.popupContainer) return;
|
|
1407
1489
|
const container = this.popupContainer;
|
|
1408
|
-
void import("./renderPopup-
|
|
1490
|
+
void import("./renderPopup-KBDWWSUU.mjs").then(({ renderPopup }) => {
|
|
1409
1491
|
renderPopup(
|
|
1410
1492
|
container,
|
|
1411
1493
|
surveyId,
|
|
@@ -1417,7 +1499,8 @@ var DeepdotsPopups = class {
|
|
|
1417
1499
|
userId,
|
|
1418
1500
|
style,
|
|
1419
1501
|
sessionId,
|
|
1420
|
-
miniService
|
|
1502
|
+
miniService,
|
|
1503
|
+
analyticsFeedbackSessionId
|
|
1421
1504
|
);
|
|
1422
1505
|
});
|
|
1423
1506
|
}
|