@magicfeedback/popup-sdk 1.8.4 → 1.9.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 +40 -0
- package/dist/assets/assets/style.css +113 -60
- package/dist/{chunk-EBJZDVC6.mjs → chunk-AKVMUQXO.mjs} +114 -61
- package/dist/chunk-AKVMUQXO.mjs.map +1 -0
- package/dist/{chunk-AV2TTQXB.mjs → chunk-MTV7T4OW.mjs} +114 -61
- package/dist/chunk-MTV7T4OW.mjs.map +1 -0
- package/dist/index.d.mts +42 -1
- package/dist/index.d.ts +42 -1
- package/dist/index.js +173 -67
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +64 -11
- package/dist/index.mjs.map +1 -1
- package/dist/react-native.d.mts +35 -0
- package/dist/react-native.d.ts +35 -0
- package/dist/react-native.js +173 -67
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +64 -11
- package/dist/react-native.mjs.map +1 -1
- package/dist/{renderPopup-3CZ6WTXF.mjs → renderPopup-LEGTSBLD.mjs} +2 -2
- package/dist/{renderPopup-E2OLIXIQ.mjs → renderPopup-LEM2MLWT.mjs} +2 -2
- package/package.json +1 -1
- package/dist/chunk-AV2TTQXB.mjs.map +0 -1
- package/dist/chunk-EBJZDVC6.mjs.map +0 -1
- /package/dist/{renderPopup-3CZ6WTXF.mjs.map → renderPopup-LEGTSBLD.mjs.map} +0 -0
- /package/dist/{renderPopup-E2OLIXIQ.mjs.map → renderPopup-LEM2MLWT.mjs.map} +0 -0
package/dist/index.mjs
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
sdkWarn,
|
|
22
22
|
setLogger,
|
|
23
23
|
style_default
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-MTV7T4OW.mjs";
|
|
25
25
|
|
|
26
26
|
// src/types/index.ts
|
|
27
27
|
var POPUP_TRIGGER_CONDITION_STATUSES = [
|
|
@@ -868,7 +868,7 @@ function createReactNativeRenderer() {
|
|
|
868
868
|
}
|
|
869
869
|
|
|
870
870
|
// src/ui/preload.ts
|
|
871
|
-
var defaultLoader = () => import("./renderPopup-
|
|
871
|
+
var defaultLoader = () => import("./renderPopup-LEGTSBLD.mjs");
|
|
872
872
|
var pending = null;
|
|
873
873
|
function preloadRenderPopup(loader = defaultLoader) {
|
|
874
874
|
if (pending) return pending;
|
|
@@ -941,7 +941,7 @@ var BrowserPopupRenderer = class {
|
|
|
941
941
|
if (!this.container) return;
|
|
942
942
|
this.visible = true;
|
|
943
943
|
const container = this.container;
|
|
944
|
-
void import("./renderPopup-
|
|
944
|
+
void import("./renderPopup-LEGTSBLD.mjs").then(({ renderPopup }) => {
|
|
945
945
|
renderPopup(container, surveyId, productId, actions, emit, onClose, env, userId, style, sessionId, miniService, analyticsFeedbackSessionId, options);
|
|
946
946
|
});
|
|
947
947
|
}
|
|
@@ -1218,8 +1218,10 @@ async function safeBodyText(res) {
|
|
|
1218
1218
|
function createFeedbackSink(options) {
|
|
1219
1219
|
let feedbackSessionId;
|
|
1220
1220
|
let firstPostInFlight = null;
|
|
1221
|
+
let generation = 0;
|
|
1221
1222
|
const url = `${options.baseUrl}/sdk/feedback`;
|
|
1222
1223
|
const post = async (body, final, sessionEnd = false) => {
|
|
1224
|
+
const postGeneration = generation;
|
|
1223
1225
|
const json = JSON.stringify(body);
|
|
1224
1226
|
const small = json.length <= KEEPALIVE_MAX_BYTES;
|
|
1225
1227
|
if (final) options.log?.("[DeepdotsAnalytics] final flush via fetch keepalive");
|
|
@@ -1249,9 +1251,25 @@ function createFeedbackSink(options) {
|
|
|
1249
1251
|
);
|
|
1250
1252
|
return;
|
|
1251
1253
|
}
|
|
1252
|
-
if (sessionEnd)
|
|
1254
|
+
if (sessionEnd) {
|
|
1255
|
+
let closedId = body.sessionId;
|
|
1256
|
+
try {
|
|
1257
|
+
const data = await res.json();
|
|
1258
|
+
closedId = data?.sessionId ?? closedId;
|
|
1259
|
+
} catch {
|
|
1260
|
+
}
|
|
1261
|
+
try {
|
|
1262
|
+
if (closedId) options.onSessionClosed?.(closedId);
|
|
1263
|
+
} catch {
|
|
1264
|
+
}
|
|
1265
|
+
return;
|
|
1266
|
+
}
|
|
1253
1267
|
try {
|
|
1254
1268
|
const data = await res.json();
|
|
1269
|
+
if (postGeneration !== generation) {
|
|
1270
|
+
options.log?.("[DeepdotsAnalytics] sessionId of a closed session ignored:", data?.sessionId);
|
|
1271
|
+
return;
|
|
1272
|
+
}
|
|
1255
1273
|
if (data?.sessionId && data.sessionId !== feedbackSessionId) {
|
|
1256
1274
|
feedbackSessionId = data.sessionId;
|
|
1257
1275
|
options.log?.("[DeepdotsAnalytics] feedbackSessionId cached:", feedbackSessionId);
|
|
@@ -1264,6 +1282,7 @@ function createFeedbackSink(options) {
|
|
|
1264
1282
|
if (meta?.resetSession) {
|
|
1265
1283
|
feedbackSessionId = void 0;
|
|
1266
1284
|
firstPostInFlight = null;
|
|
1285
|
+
generation++;
|
|
1267
1286
|
options.onSessionReset?.();
|
|
1268
1287
|
return;
|
|
1269
1288
|
}
|
|
@@ -1278,6 +1297,7 @@ function createFeedbackSink(options) {
|
|
|
1278
1297
|
if (sessionEnd) {
|
|
1279
1298
|
feedbackSessionId = void 0;
|
|
1280
1299
|
firstPostInFlight = null;
|
|
1300
|
+
generation++;
|
|
1281
1301
|
options.onSessionReset?.();
|
|
1282
1302
|
} else if (!feedbackSessionId) {
|
|
1283
1303
|
firstPostInFlight = sent.then(
|
|
@@ -1291,7 +1311,7 @@ function createFeedbackSink(options) {
|
|
|
1291
1311
|
|
|
1292
1312
|
// src/tracking/navigation-observer.ts
|
|
1293
1313
|
var UUID_PREFIX = /^[0-9a-f]{8}-[0-9a-f]{4}-/i;
|
|
1294
|
-
function
|
|
1314
|
+
function screenPath(href) {
|
|
1295
1315
|
let pathAndHash;
|
|
1296
1316
|
try {
|
|
1297
1317
|
const u = new URL(href, "http://deepdots.local");
|
|
@@ -1299,7 +1319,10 @@ function normalizeScreen(href) {
|
|
|
1299
1319
|
} catch {
|
|
1300
1320
|
pathAndHash = href;
|
|
1301
1321
|
}
|
|
1302
|
-
|
|
1322
|
+
return pathAndHash.replace(/\?[^#]*/g, "") || "/";
|
|
1323
|
+
}
|
|
1324
|
+
function normalizeScreen(href) {
|
|
1325
|
+
const pathAndHash = screenPath(href);
|
|
1303
1326
|
const collapsed = pathAndHash.split("/").map((seg) => /^[0-9]+$/.test(seg) || UUID_PREFIX.test(seg) ? ":id" : seg).join("/");
|
|
1304
1327
|
return collapsed || "/";
|
|
1305
1328
|
}
|
|
@@ -1307,6 +1330,7 @@ var NavigationObserver = class {
|
|
|
1307
1330
|
constructor(options = {}) {
|
|
1308
1331
|
this.listeners = /* @__PURE__ */ new Set();
|
|
1309
1332
|
this.currentScreen = null;
|
|
1333
|
+
this.currentPath = null;
|
|
1310
1334
|
this.entryAt = 0;
|
|
1311
1335
|
this.installed = false;
|
|
1312
1336
|
this.domHandlers = [];
|
|
@@ -1318,20 +1342,23 @@ var NavigationObserver = class {
|
|
|
1318
1342
|
/** Fija la pantalla inicial (sin emitir visita; su duración se cierra al salir). */
|
|
1319
1343
|
begin(href) {
|
|
1320
1344
|
this.currentScreen = normalizeScreen(href);
|
|
1345
|
+
this.currentPath = screenPath(href);
|
|
1321
1346
|
this.entryAt = this.now();
|
|
1322
1347
|
}
|
|
1323
1348
|
/** Navega a una pantalla nueva: cierra la anterior (emite visita) y abre la nueva. */
|
|
1324
1349
|
visit(href) {
|
|
1325
|
-
const
|
|
1326
|
-
if (
|
|
1350
|
+
const nextPath = screenPath(href);
|
|
1351
|
+
if (this.currentScreen != null && nextPath === this.currentPath) return;
|
|
1327
1352
|
this.closeCurrent();
|
|
1328
|
-
this.currentScreen =
|
|
1353
|
+
this.currentScreen = normalizeScreen(href);
|
|
1354
|
+
this.currentPath = nextPath;
|
|
1329
1355
|
this.entryAt = this.now();
|
|
1330
1356
|
}
|
|
1331
1357
|
/** Cierra la pantalla actual emitiendo su visita (p. ej. al cerrar la app/pestaña). */
|
|
1332
1358
|
stop() {
|
|
1333
1359
|
this.closeCurrent();
|
|
1334
1360
|
this.currentScreen = null;
|
|
1361
|
+
this.currentPath = null;
|
|
1335
1362
|
}
|
|
1336
1363
|
/**
|
|
1337
1364
|
* Olvida la pantalla actual SIN emitir su visita. Para una sesión que el backend ya dio
|
|
@@ -1340,6 +1367,7 @@ var NavigationObserver = class {
|
|
|
1340
1367
|
*/
|
|
1341
1368
|
discard() {
|
|
1342
1369
|
this.currentScreen = null;
|
|
1370
|
+
this.currentPath = null;
|
|
1343
1371
|
}
|
|
1344
1372
|
/**
|
|
1345
1373
|
* Retoma el seguimiento en la pantalla actual tras un `stop()`, cuando se abre una sesión
|
|
@@ -1355,6 +1383,7 @@ var NavigationObserver = class {
|
|
|
1355
1383
|
const exit = this.now();
|
|
1356
1384
|
const visit = {
|
|
1357
1385
|
screen: this.currentScreen,
|
|
1386
|
+
path: this.currentPath ?? this.currentScreen,
|
|
1358
1387
|
entry: this.entryAt,
|
|
1359
1388
|
exit,
|
|
1360
1389
|
durationSeconds: Math.max(0, Math.round((exit - this.entryAt) / 1e3))
|
|
@@ -1915,6 +1944,8 @@ var DeepdotsPopups = class {
|
|
|
1915
1944
|
this.analytics = null;
|
|
1916
1945
|
/** feedbackSessionId cacheado del canal de analytics (devuelto por POST /sdk/feedback). */
|
|
1917
1946
|
this.analyticsFeedbackSessionId = void 0;
|
|
1947
|
+
/** `init({ onFeedbackSession })`: avisa al host al abrir y cerrar cada registro. */
|
|
1948
|
+
this.onFeedbackSession = void 0;
|
|
1918
1949
|
/** Timer del flush periódico de analytics (cada ANALYTICS_FLUSH_INTERVAL_MS). */
|
|
1919
1950
|
this.analyticsFlushTimer = void 0;
|
|
1920
1951
|
/** Crash & error reporting (#14–17). Null hasta init(). */
|
|
@@ -1972,6 +2003,7 @@ var DeepdotsPopups = class {
|
|
|
1972
2003
|
this.renderChrome = config.renderChrome ?? true;
|
|
1973
2004
|
this.showProgressBar = config.showProgressBar;
|
|
1974
2005
|
this.surveyCss = config.surveyCss;
|
|
2006
|
+
this.onFeedbackSession = config.onFeedbackSession;
|
|
1975
2007
|
this.config = {
|
|
1976
2008
|
apiKey: config.apiKey || void 0,
|
|
1977
2009
|
debug: config.debug || false,
|
|
@@ -2005,7 +2037,9 @@ var DeepdotsPopups = class {
|
|
|
2005
2037
|
log: (...a) => this.log(...a),
|
|
2006
2038
|
onSessionId: (id) => {
|
|
2007
2039
|
this.analyticsFeedbackSessionId = id;
|
|
2040
|
+
this.notifyFeedbackSession(id, "open");
|
|
2008
2041
|
},
|
|
2042
|
+
onSessionClosed: (id) => this.notifyFeedbackSession(id, "closed"),
|
|
2009
2043
|
onSessionReset: () => {
|
|
2010
2044
|
this.analyticsFeedbackSessionId = void 0;
|
|
2011
2045
|
}
|
|
@@ -2043,7 +2077,9 @@ var DeepdotsPopups = class {
|
|
|
2043
2077
|
this.geoWanted = this.geoEnabled && !!config.analytics;
|
|
2044
2078
|
this.resolveGeo();
|
|
2045
2079
|
this.navObserver = new NavigationObserver();
|
|
2046
|
-
this.navObserver.onVisit(
|
|
2080
|
+
this.navObserver.onVisit(
|
|
2081
|
+
(v) => this.track("deepdots_page_view", { screen: v.screen, path: v.path, duration_seconds: v.durationSeconds })
|
|
2082
|
+
);
|
|
2047
2083
|
this.navObserver.install();
|
|
2048
2084
|
this.engagement = new EngagementTracker();
|
|
2049
2085
|
this.setupAnalyticsFlush();
|
|
@@ -2078,6 +2114,23 @@ var DeepdotsPopups = class {
|
|
|
2078
2114
|
getSessionId() {
|
|
2079
2115
|
return this.tracking?.getSessionId() ?? null;
|
|
2080
2116
|
}
|
|
2117
|
+
/**
|
|
2118
|
+
* Id del registro de analytics abierto: el `sessionId` que devolvió `POST /sdk/feedback`,
|
|
2119
|
+
* que la API guarda como `sdkSessionId` en el Feedback en que se convierte la sesión. No es
|
|
2120
|
+
* `getSessionId()`. Null hasta que el backend acepta el primer lote y de nuevo al cerrar la
|
|
2121
|
+
* sesión: para saber también qué registro se cerró, usa `init({ onFeedbackSession })`.
|
|
2122
|
+
*/
|
|
2123
|
+
getFeedbackSessionId() {
|
|
2124
|
+
return this.analyticsFeedbackSessionId ?? null;
|
|
2125
|
+
}
|
|
2126
|
+
/** Avisa al host del registro abierto o cerrado; un fallo del host no corta el envío. */
|
|
2127
|
+
notifyFeedbackSession(sessionId, status) {
|
|
2128
|
+
try {
|
|
2129
|
+
this.onFeedbackSession?.({ sessionId, status });
|
|
2130
|
+
} catch (error) {
|
|
2131
|
+
this.log("analytics \xB7 onFeedbackSession threw:", error);
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2081
2134
|
/** Activa/desactiva el tracking (identidad + sesión + analytics). Kill-switch del contrato §7bis. */
|
|
2082
2135
|
setTrackingEnabled(enabled) {
|
|
2083
2136
|
if (!enabled) this.closeSession("tracking_disabled");
|
|
@@ -2918,7 +2971,7 @@ var DeepdotsPopups = class {
|
|
|
2918
2971
|
}
|
|
2919
2972
|
if (!this.popupContainer) return;
|
|
2920
2973
|
const container = this.popupContainer;
|
|
2921
|
-
void import("./renderPopup-
|
|
2974
|
+
void import("./renderPopup-LEGTSBLD.mjs").then(({ renderPopup }) => {
|
|
2922
2975
|
renderPopup(
|
|
2923
2976
|
container,
|
|
2924
2977
|
surveyId,
|