@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/index.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
TrackingManager,
|
|
5
5
|
buildSurveyIdentity,
|
|
6
6
|
createDefaultStorage
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-6WTOQGET.mjs";
|
|
8
8
|
|
|
9
9
|
// src/types/index.ts
|
|
10
10
|
var POPUP_TRIGGER_CONDITION_STATUSES = [
|
|
@@ -253,12 +253,12 @@ var ReactNativePopupRenderer = class {
|
|
|
253
253
|
}
|
|
254
254
|
init() {
|
|
255
255
|
}
|
|
256
|
-
show(surveyId, productId, _actions, emit, onClose, env = "production", userId, _style, sessionId, miniService) {
|
|
256
|
+
show(surveyId, productId, _actions, emit, onClose, env = "production", userId, _style, sessionId, miniService, analyticsFeedbackSessionId) {
|
|
257
257
|
this.emitFn = emit;
|
|
258
258
|
this.onCloseFn = onClose;
|
|
259
259
|
this.currentSurveyId = surveyId;
|
|
260
260
|
this.partialEmitted = false;
|
|
261
|
-
const { profile, metadata } = buildSurveyIdentity(userId ?? null, sessionId ?? null, miniService ?? null);
|
|
261
|
+
const { profile, metadata } = buildSurveyIdentity(userId ?? null, sessionId ?? null, miniService ?? null, analyticsFeedbackSessionId ?? null);
|
|
262
262
|
const html = buildSurveyHtml({ surveyId, productId, env, profile, metadata });
|
|
263
263
|
if (this.options.onShow) {
|
|
264
264
|
this.options.onShow({ surveyId, productId, html });
|
|
@@ -349,14 +349,14 @@ var BrowserPopupRenderer = class {
|
|
|
349
349
|
document.body.appendChild(this.container);
|
|
350
350
|
}
|
|
351
351
|
}
|
|
352
|
-
show(surveyId, productId, actions, emit, onClose, env = "production", userId, style, sessionId, miniService) {
|
|
352
|
+
show(surveyId, productId, actions, emit, onClose, env = "production", userId, style, sessionId, miniService, analyticsFeedbackSessionId) {
|
|
353
353
|
if (this.visible) return;
|
|
354
354
|
if (!this.container || !document.body.contains(this.container)) this.init();
|
|
355
355
|
if (!this.container) return;
|
|
356
356
|
this.visible = true;
|
|
357
357
|
const container = this.container;
|
|
358
|
-
void import("./renderPopup-
|
|
359
|
-
renderPopup(container, surveyId, productId, actions, emit, onClose, env, userId, style, sessionId, miniService);
|
|
358
|
+
void import("./renderPopup-YLFRGPQN.mjs").then(({ renderPopup }) => {
|
|
359
|
+
renderPopup(container, surveyId, productId, actions, emit, onClose, env, userId, style, sessionId, miniService, analyticsFeedbackSessionId);
|
|
360
360
|
});
|
|
361
361
|
}
|
|
362
362
|
hide() {
|
|
@@ -395,6 +395,12 @@ var AnalyticsManager = class {
|
|
|
395
395
|
this.language = options.language;
|
|
396
396
|
this.device = options.device;
|
|
397
397
|
this.platform = options.platform ?? "web";
|
|
398
|
+
this.maxBatchSize = options.maxBatchSize ?? 20;
|
|
399
|
+
this.onFlushNeeded = options.onFlushNeeded;
|
|
400
|
+
}
|
|
401
|
+
/** Actualiza campos de device en runtime (p.ej. country/city tras resolver geo). */
|
|
402
|
+
updateDevice(partial) {
|
|
403
|
+
this.device = { ...this.device, ...partial };
|
|
398
404
|
}
|
|
399
405
|
/** Mezcla user attributes (se coercionan a string). Mutable en runtime. */
|
|
400
406
|
setUserAttributes(attrs) {
|
|
@@ -428,6 +434,9 @@ var AnalyticsManager = class {
|
|
|
428
434
|
timestamp: this.now(),
|
|
429
435
|
params: Object.keys(merged).length ? merged : void 0
|
|
430
436
|
});
|
|
437
|
+
if (this.events.length >= this.maxBatchSize) {
|
|
438
|
+
this.onFlushNeeded?.();
|
|
439
|
+
}
|
|
431
440
|
}
|
|
432
441
|
/** Mini-service activo (para inyectarlo en la metadata del survey, #33). */
|
|
433
442
|
getMiniService() {
|
|
@@ -465,44 +474,55 @@ var AnalyticsManager = class {
|
|
|
465
474
|
// src/analytics/feedback-payload.ts
|
|
466
475
|
function pushKV(list, key, value) {
|
|
467
476
|
if (value === void 0 || value === null || value === "") return;
|
|
468
|
-
list.push({ key, value: String(value) });
|
|
477
|
+
list.push({ key, value: [String(value)] });
|
|
469
478
|
}
|
|
470
479
|
function buildAnalyticsFeedbackBody(envelope, keys, feedbackSessionId) {
|
|
471
480
|
const { context } = envelope;
|
|
472
|
-
const metrics = envelope.events.map((e) => ({
|
|
473
|
-
key: e.name,
|
|
474
|
-
value: JSON.stringify({ timestamp: e.timestamp, ...e.params ?? {} })
|
|
475
|
-
}));
|
|
476
481
|
const profile = [];
|
|
477
482
|
pushKV(profile, "external-user-id", envelope.userId);
|
|
478
483
|
const metadata = [];
|
|
479
|
-
pushKV(metadata, "
|
|
480
|
-
pushKV(metadata, "
|
|
481
|
-
pushKV(metadata, "
|
|
482
|
-
pushKV(metadata, "
|
|
484
|
+
pushKV(metadata, "deepdots_user_id", envelope.userId);
|
|
485
|
+
pushKV(metadata, "deepdots_session_id", envelope.sessionId);
|
|
486
|
+
pushKV(metadata, "deepdots_platform", context.platform);
|
|
487
|
+
pushKV(metadata, "deepdots_language", context.language);
|
|
483
488
|
if (context.device) {
|
|
484
|
-
|
|
485
|
-
pushKV(metadata, "
|
|
486
|
-
pushKV(metadata, "
|
|
487
|
-
pushKV(metadata, "
|
|
488
|
-
pushKV(metadata, "
|
|
489
|
+
const d = context.device;
|
|
490
|
+
pushKV(metadata, "deepdots_device_type", d.device_type);
|
|
491
|
+
pushKV(metadata, "deepdots_os_version", d.os_version);
|
|
492
|
+
pushKV(metadata, "deepdots_device_model", d.device_model);
|
|
493
|
+
pushKV(metadata, "deepdots_app_version", d.app_version);
|
|
494
|
+
pushKV(metadata, "deepdots_user_agent", d.user_agent);
|
|
495
|
+
pushKV(metadata, "deepdots_timezone", d.timezone);
|
|
496
|
+
pushKV(metadata, "deepdots_referrer", d.referrer);
|
|
497
|
+
pushKV(metadata, "deepdots_viewport_size", d.viewport_size);
|
|
498
|
+
pushKV(metadata, "deepdots_screen_resolution", d.screen_resolution);
|
|
499
|
+
pushKV(metadata, "deepdots_pixel_ratio", d.pixel_ratio);
|
|
500
|
+
pushKV(metadata, "deepdots_entry_type", d.entry_type);
|
|
501
|
+
pushKV(metadata, "deepdots_page_load_ms", d.page_load_ms);
|
|
502
|
+
pushKV(metadata, "deepdots_connection_type", d.connection_type);
|
|
503
|
+
pushKV(metadata, "deepdots_country", d.country);
|
|
504
|
+
pushKV(metadata, "deepdots_city", d.city);
|
|
489
505
|
}
|
|
490
506
|
for (const [k, v] of Object.entries(context.attributes ?? {})) {
|
|
491
507
|
pushKV(metadata, k, v);
|
|
492
508
|
}
|
|
509
|
+
for (const e of envelope.events) {
|
|
510
|
+
metadata.push({
|
|
511
|
+
key: e.name,
|
|
512
|
+
value: [JSON.stringify({ timestamp: e.timestamp, ...e.params ?? {} })]
|
|
513
|
+
});
|
|
514
|
+
}
|
|
493
515
|
return {
|
|
494
516
|
feedback: {
|
|
495
517
|
text: "",
|
|
496
518
|
answers: [],
|
|
497
519
|
metadata,
|
|
498
|
-
metrics,
|
|
499
520
|
profile,
|
|
500
521
|
finished: false
|
|
501
522
|
},
|
|
502
523
|
publicKey: keys.publicKey,
|
|
503
524
|
integration: keys.integration,
|
|
504
525
|
completed: false,
|
|
505
|
-
// finished: false,
|
|
506
526
|
...feedbackSessionId ? { sessionId: feedbackSessionId } : {}
|
|
507
527
|
};
|
|
508
528
|
}
|
|
@@ -527,6 +547,7 @@ function createFeedbackSink(options) {
|
|
|
527
547
|
if (data?.sessionId && data.sessionId !== feedbackSessionId) {
|
|
528
548
|
feedbackSessionId = data.sessionId;
|
|
529
549
|
options.log?.("[DeepdotsAnalytics] feedbackSessionId cacheado:", feedbackSessionId);
|
|
550
|
+
options.onSessionId?.(feedbackSessionId);
|
|
530
551
|
}
|
|
531
552
|
} catch {
|
|
532
553
|
}
|
|
@@ -640,15 +661,57 @@ function parseDeviceType(ua) {
|
|
|
640
661
|
}
|
|
641
662
|
return "desktop";
|
|
642
663
|
}
|
|
664
|
+
function getEntryType() {
|
|
665
|
+
if (typeof performance === "undefined") return void 0;
|
|
666
|
+
const entries = performance.getEntriesByType("navigation");
|
|
667
|
+
if (!entries.length) return void 0;
|
|
668
|
+
return entries[0].type;
|
|
669
|
+
}
|
|
670
|
+
function getPageLoadMs() {
|
|
671
|
+
if (typeof performance === "undefined") return void 0;
|
|
672
|
+
const entries = performance.getEntriesByType("navigation");
|
|
673
|
+
if (!entries.length) return void 0;
|
|
674
|
+
const load = entries[0].loadEventEnd;
|
|
675
|
+
return load > 0 ? Math.round(load) : void 0;
|
|
676
|
+
}
|
|
677
|
+
function getConnectionType() {
|
|
678
|
+
if (typeof navigator === "undefined") return void 0;
|
|
679
|
+
return navigator.connection?.effectiveType ?? void 0;
|
|
680
|
+
}
|
|
643
681
|
function collectDeviceInfo(appVersion) {
|
|
644
682
|
const ua = typeof navigator !== "undefined" ? navigator.userAgent : "";
|
|
645
683
|
return {
|
|
646
684
|
device_type: parseDeviceType(ua),
|
|
647
685
|
user_agent: ua || void 0,
|
|
648
|
-
app_version: appVersion
|
|
686
|
+
app_version: appVersion,
|
|
687
|
+
timezone: typeof Intl !== "undefined" ? Intl.DateTimeFormat().resolvedOptions().timeZone : void 0,
|
|
688
|
+
referrer: typeof document !== "undefined" && document.referrer ? document.referrer : void 0,
|
|
689
|
+
viewport_size: typeof window !== "undefined" ? `${window.innerWidth}x${window.innerHeight}` : void 0,
|
|
690
|
+
screen_resolution: typeof screen !== "undefined" ? `${screen.width}x${screen.height}` : void 0,
|
|
691
|
+
pixel_ratio: typeof window !== "undefined" ? window.devicePixelRatio : void 0,
|
|
692
|
+
entry_type: getEntryType(),
|
|
693
|
+
page_load_ms: getPageLoadMs(),
|
|
694
|
+
connection_type: getConnectionType()
|
|
649
695
|
};
|
|
650
696
|
}
|
|
651
697
|
|
|
698
|
+
// src/analytics/geo-info.ts
|
|
699
|
+
async function collectGeoInfo(fetchImpl) {
|
|
700
|
+
const f = fetchImpl ?? (typeof fetch !== "undefined" ? fetch : void 0);
|
|
701
|
+
if (!f) return null;
|
|
702
|
+
try {
|
|
703
|
+
const res = await f("https://ipapi.co/json/");
|
|
704
|
+
if (!res.ok) return null;
|
|
705
|
+
const data = await res.json();
|
|
706
|
+
const country = data.country_code || void 0;
|
|
707
|
+
const city = data.city || void 0;
|
|
708
|
+
if (!country && !city) return null;
|
|
709
|
+
return { country, city };
|
|
710
|
+
} catch {
|
|
711
|
+
return null;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
652
715
|
// src/analytics/engagement-tracker.ts
|
|
653
716
|
var EngagementTracker = class {
|
|
654
717
|
constructor(now = () => Date.now()) {
|
|
@@ -719,6 +782,8 @@ var ContactManager = class {
|
|
|
719
782
|
// src/core/deepdots-popups.ts
|
|
720
783
|
var EXIT_QUEUE_STORAGE_KEY = "__deepdots_exit_popup_queue__";
|
|
721
784
|
var DAY_IN_MS = 24 * 60 * 60 * 1e3;
|
|
785
|
+
var ANALYTICS_MAX_BATCH_SIZE = 20;
|
|
786
|
+
var ANALYTICS_FLUSH_INTERVAL_MS = 3e4;
|
|
722
787
|
var DeepdotsPopups = class {
|
|
723
788
|
constructor() {
|
|
724
789
|
this.config = null;
|
|
@@ -744,6 +809,10 @@ var DeepdotsPopups = class {
|
|
|
744
809
|
this.tracking = null;
|
|
745
810
|
/** Capa de analytics (canal separado del feedback). Null hasta init(). */
|
|
746
811
|
this.analytics = null;
|
|
812
|
+
/** feedbackSessionId cacheado del canal de analytics (devuelto por POST /sdk/feedback). */
|
|
813
|
+
this.analyticsFeedbackSessionId = void 0;
|
|
814
|
+
/** Timer del flush periódico de analytics (cada ANALYTICS_FLUSH_INTERVAL_MS). */
|
|
815
|
+
this.analyticsFlushTimer = void 0;
|
|
747
816
|
/** Observador de navegación (Fase 2): emite page_view por el canal de analytics. */
|
|
748
817
|
this.navObserver = null;
|
|
749
818
|
/** Tiempo activo (engagement time, #8). */
|
|
@@ -790,14 +859,23 @@ var DeepdotsPopups = class {
|
|
|
790
859
|
const analyticsSink = config.analytics ? createFeedbackSink({
|
|
791
860
|
baseUrl: this.baseUrl,
|
|
792
861
|
keys: config.analytics,
|
|
793
|
-
log: (...a) => this.log(...a)
|
|
862
|
+
log: (...a) => this.log(...a),
|
|
863
|
+
onSessionId: (id) => {
|
|
864
|
+
this.analyticsFeedbackSessionId = id;
|
|
865
|
+
}
|
|
794
866
|
}) : void 0;
|
|
795
867
|
this.analytics = new AnalyticsManager({
|
|
796
868
|
sink: analyticsSink,
|
|
797
869
|
publicKey: config.analytics?.publicKey ?? this.config.apiKey,
|
|
798
870
|
language: typeof navigator !== "undefined" ? navigator.language : void 0,
|
|
799
871
|
platform: config.platform ?? "web",
|
|
800
|
-
device: config.device ?? collectDeviceInfo(config.appVersion)
|
|
872
|
+
device: config.device ?? collectDeviceInfo(config.appVersion),
|
|
873
|
+
maxBatchSize: ANALYTICS_MAX_BATCH_SIZE,
|
|
874
|
+
onFlushNeeded: () => this.flushAnalytics()
|
|
875
|
+
});
|
|
876
|
+
collectGeoInfo().then((geo) => {
|
|
877
|
+
if (geo) this.analytics?.updateDevice(geo);
|
|
878
|
+
}).catch(() => {
|
|
801
879
|
});
|
|
802
880
|
this.navObserver = new NavigationObserver();
|
|
803
881
|
this.navObserver.onVisit((v) => this.track("page_view", { screen: v.screen, duration_seconds: v.durationSeconds }));
|
|
@@ -938,7 +1016,9 @@ var DeepdotsPopups = class {
|
|
|
938
1016
|
/** Flush automático al ocultar/cerrar la página (no perder el lote pendiente). */
|
|
939
1017
|
setupAnalyticsFlush() {
|
|
940
1018
|
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
1019
|
+
this.analyticsFlushTimer = setInterval(() => this.flushAnalytics(), ANALYTICS_FLUSH_INTERVAL_MS);
|
|
941
1020
|
window.addEventListener("pagehide", () => {
|
|
1021
|
+
clearInterval(this.analyticsFlushTimer);
|
|
942
1022
|
this.navObserver?.stop();
|
|
943
1023
|
this.exitMiniService();
|
|
944
1024
|
this.flushEngagement();
|
|
@@ -1382,7 +1462,8 @@ var DeepdotsPopups = class {
|
|
|
1382
1462
|
const userId = this.tracking?.getUserId() ?? this.config?.userId;
|
|
1383
1463
|
const sessionId = this.tracking?.getSessionId() ?? void 0;
|
|
1384
1464
|
const miniService = this.analytics?.getMiniService() ?? void 0;
|
|
1385
|
-
|
|
1465
|
+
const analyticsFeedbackSessionId = this.analyticsFeedbackSessionId;
|
|
1466
|
+
this.log("tracking \xB7 survey identity \u2192", { userId: userId ?? null, sessionId: sessionId ?? null, miniService: miniService ?? null, analyticsFeedbackSessionId: analyticsFeedbackSessionId ?? null });
|
|
1386
1467
|
if (this.renderer) {
|
|
1387
1468
|
this.renderer.show(
|
|
1388
1469
|
surveyId,
|
|
@@ -1394,13 +1475,14 @@ var DeepdotsPopups = class {
|
|
|
1394
1475
|
userId,
|
|
1395
1476
|
style,
|
|
1396
1477
|
sessionId,
|
|
1397
|
-
miniService
|
|
1478
|
+
miniService,
|
|
1479
|
+
analyticsFeedbackSessionId
|
|
1398
1480
|
);
|
|
1399
1481
|
return;
|
|
1400
1482
|
}
|
|
1401
1483
|
if (!this.popupContainer) return;
|
|
1402
1484
|
const container = this.popupContainer;
|
|
1403
|
-
void import("./renderPopup-
|
|
1485
|
+
void import("./renderPopup-YLFRGPQN.mjs").then(({ renderPopup }) => {
|
|
1404
1486
|
renderPopup(
|
|
1405
1487
|
container,
|
|
1406
1488
|
surveyId,
|
|
@@ -1412,7 +1494,8 @@ var DeepdotsPopups = class {
|
|
|
1412
1494
|
userId,
|
|
1413
1495
|
style,
|
|
1414
1496
|
sessionId,
|
|
1415
|
-
miniService
|
|
1497
|
+
miniService,
|
|
1498
|
+
analyticsFeedbackSessionId
|
|
1416
1499
|
);
|
|
1417
1500
|
});
|
|
1418
1501
|
}
|