@magicfeedback/popup-sdk 1.1.5 → 1.1.7
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-LSTKGFU7.mjs → chunk-4UXOEIAB.mjs} +21 -2
- package/dist/chunk-4UXOEIAB.mjs.map +1 -0
- package/dist/{chunk-7TOLYAFL.mjs → chunk-XOTM5CHX.mjs} +21 -2
- package/dist/chunk-XOTM5CHX.mjs.map +1 -0
- package/dist/index.d.mts +32 -2
- package/dist/index.d.ts +32 -2
- package/dist/index.js +167 -26
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +141 -24
- package/dist/index.mjs.map +1 -1
- package/dist/react-native.d.mts +30 -1
- package/dist/react-native.d.ts +30 -1
- package/dist/react-native.js +167 -26
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +141 -24
- package/dist/react-native.mjs.map +1 -1
- package/dist/{renderPopup-MES7IINW.mjs → renderPopup-EZKDMLVZ.mjs} +10 -7
- package/dist/renderPopup-EZKDMLVZ.mjs.map +1 -0
- package/dist/{renderPopup-YNH2TD3B.mjs → renderPopup-PS3NJDUR.mjs} +10 -7
- package/dist/renderPopup-PS3NJDUR.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-7TOLYAFL.mjs.map +0 -1
- package/dist/chunk-LSTKGFU7.mjs.map +0 -1
- package/dist/renderPopup-MES7IINW.mjs.map +0 -1
- package/dist/renderPopup-YNH2TD3B.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -5,8 +5,10 @@ import {
|
|
|
5
5
|
buildFontFaceCss,
|
|
6
6
|
buildFontFamilyValue,
|
|
7
7
|
buildSurveyIdentity,
|
|
8
|
-
createDefaultStorage
|
|
9
|
-
|
|
8
|
+
createDefaultStorage,
|
|
9
|
+
sdkWarn,
|
|
10
|
+
setLogger
|
|
11
|
+
} from "./chunk-XOTM5CHX.mjs";
|
|
10
12
|
|
|
11
13
|
// src/types/index.ts
|
|
12
14
|
var POPUP_TRIGGER_CONDITION_STATUSES = [
|
|
@@ -267,7 +269,7 @@ var ReactNativePopupRenderer = class {
|
|
|
267
269
|
if (this.options.onShow) {
|
|
268
270
|
this.options.onShow({ surveyId, productId, html });
|
|
269
271
|
} else {
|
|
270
|
-
|
|
272
|
+
sdkWarn(
|
|
271
273
|
"[Deepdots] ReactNativePopupRenderer sin onShow: pasa { onShow } a new ReactNativePopupRenderer({...}) para montar el WebView del survey."
|
|
272
274
|
);
|
|
273
275
|
}
|
|
@@ -359,7 +361,7 @@ var BrowserPopupRenderer = class {
|
|
|
359
361
|
if (!this.container) return;
|
|
360
362
|
this.visible = true;
|
|
361
363
|
const container = this.container;
|
|
362
|
-
void import("./renderPopup-
|
|
364
|
+
void import("./renderPopup-EZKDMLVZ.mjs").then(({ renderPopup }) => {
|
|
363
365
|
renderPopup(container, surveyId, productId, actions, emit, onClose, env, userId, style, sessionId, miniService, analyticsFeedbackSessionId);
|
|
364
366
|
});
|
|
365
367
|
}
|
|
@@ -381,16 +383,19 @@ function createDefaultRenderer() {
|
|
|
381
383
|
}
|
|
382
384
|
|
|
383
385
|
// src/analytics/analytics-manager.ts
|
|
384
|
-
|
|
385
|
-
|
|
386
|
+
function createDryRunSink(log = console.log) {
|
|
387
|
+
return (payload) => log(
|
|
386
388
|
"[DeepdotsAnalytics] (dry-run \xB7 NO enviado \xB7 sin init.analytics) POST /sdk/feedback \u2192",
|
|
387
389
|
JSON.stringify(payload, null, 2)
|
|
388
390
|
);
|
|
389
|
-
}
|
|
391
|
+
}
|
|
392
|
+
var dryRunSink = createDryRunSink();
|
|
390
393
|
var AnalyticsManager = class {
|
|
391
394
|
constructor(options = {}) {
|
|
392
395
|
this.events = [];
|
|
393
396
|
this.attributes = {};
|
|
397
|
+
/** Métricas del host (valores medibles persistentes). Sobrescriben por key; se reenvían en cada flush. */
|
|
398
|
+
this.metrics = {};
|
|
394
399
|
/** Mini-services activos: nombre → timestamp de entrada. El orden de inserción marca el "más reciente". */
|
|
395
400
|
this.activeMiniServices = /* @__PURE__ */ new Map();
|
|
396
401
|
this.sink = options.sink ?? dryRunSink;
|
|
@@ -413,6 +418,14 @@ var AnalyticsManager = class {
|
|
|
413
418
|
this.attributes[k] = String(v);
|
|
414
419
|
}
|
|
415
420
|
}
|
|
421
|
+
/**
|
|
422
|
+
* Registra/actualiza una métrica (valor medible). Persistente: se reenvía en cada flush.
|
|
423
|
+
* Repetir la misma key SOBRESCRIBE; el valor se coerciona a string; ignora key vacía.
|
|
424
|
+
*/
|
|
425
|
+
setMetric(key, value) {
|
|
426
|
+
if (!key) return;
|
|
427
|
+
this.metrics[key] = String(value);
|
|
428
|
+
}
|
|
416
429
|
/**
|
|
417
430
|
* Marca el inicio de un mini-service; etiqueta los eventos siguientes con `mini_service`.
|
|
418
431
|
* Admite varios activos a la vez (concurrencia); el "actual" para etiquetar es el más reciente.
|
|
@@ -476,7 +489,8 @@ var AnalyticsManager = class {
|
|
|
476
489
|
platform: this.platform,
|
|
477
490
|
language: this.language,
|
|
478
491
|
device: this.device,
|
|
479
|
-
attributes: { ...this.attributes }
|
|
492
|
+
attributes: { ...this.attributes },
|
|
493
|
+
metrics: { ...this.metrics }
|
|
480
494
|
},
|
|
481
495
|
events: [...this.events]
|
|
482
496
|
};
|
|
@@ -532,10 +546,15 @@ function buildAnalyticsFeedbackBody(envelope, keys, feedbackSessionId) {
|
|
|
532
546
|
value: [JSON.stringify({ timestamp: e.timestamp, ...e.params ?? {} })]
|
|
533
547
|
});
|
|
534
548
|
}
|
|
549
|
+
const metrics = [];
|
|
550
|
+
for (const [k, v] of Object.entries(context.metrics ?? {})) {
|
|
551
|
+
pushKV(metrics, k, v);
|
|
552
|
+
}
|
|
535
553
|
return {
|
|
536
554
|
feedback: {
|
|
537
555
|
text: "",
|
|
538
556
|
answers: [],
|
|
557
|
+
metrics,
|
|
539
558
|
metadata,
|
|
540
559
|
profile,
|
|
541
560
|
finished: false
|
|
@@ -716,20 +735,95 @@ function collectDeviceInfo(appVersion) {
|
|
|
716
735
|
}
|
|
717
736
|
|
|
718
737
|
// src/analytics/geo-info.ts
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
738
|
+
var GEO_STORAGE_KEY = "deepdots.geo";
|
|
739
|
+
var GEO_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
740
|
+
var GEO_TIMEOUT_MS = 3e3;
|
|
741
|
+
function readCachedGeo(storage, now) {
|
|
742
|
+
try {
|
|
743
|
+
const raw = storage.getItem(GEO_STORAGE_KEY);
|
|
744
|
+
if (!raw) return null;
|
|
745
|
+
const cached = JSON.parse(raw);
|
|
746
|
+
if (typeof cached.ts !== "number" || now - cached.ts > GEO_TTL_MS) return null;
|
|
747
|
+
const geo = {};
|
|
748
|
+
if (cached.country) geo.country = cached.country;
|
|
749
|
+
if (cached.city) geo.city = cached.city;
|
|
750
|
+
return geo.country || geo.city ? geo : null;
|
|
751
|
+
} catch {
|
|
752
|
+
return null;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
function writeCachedGeo(storage, geo, now) {
|
|
756
|
+
try {
|
|
757
|
+
const payload = { ...geo, ts: now };
|
|
758
|
+
storage.setItem(GEO_STORAGE_KEY, JSON.stringify(payload));
|
|
759
|
+
} catch {
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
var DEFAULT_GEO_PROVIDERS = [
|
|
763
|
+
{
|
|
764
|
+
// https://ipapi.co/json/
|
|
765
|
+
url: "https://ipapi.co/json/",
|
|
766
|
+
parse: (d) => geoFrom(d.country_code, d.city)
|
|
767
|
+
},
|
|
768
|
+
{
|
|
769
|
+
// https://ipwho.is/ (devuelve success:false con 200 en errores)
|
|
770
|
+
url: "https://ipwho.is/",
|
|
771
|
+
parse: (d) => d.success === false ? null : geoFrom(d.country_code, d.city)
|
|
772
|
+
},
|
|
773
|
+
{
|
|
774
|
+
// https://ipinfo.io/json (country = código ISO)
|
|
775
|
+
url: "https://ipinfo.io/json",
|
|
776
|
+
parse: (d) => geoFrom(d.country, d.city)
|
|
777
|
+
}
|
|
778
|
+
];
|
|
779
|
+
function geoFrom(country, city) {
|
|
780
|
+
const c = typeof country === "string" && country ? country : void 0;
|
|
781
|
+
const t = typeof city === "string" && city ? city : void 0;
|
|
782
|
+
if (!c && !t) return null;
|
|
783
|
+
return { country: c, city: t };
|
|
784
|
+
}
|
|
785
|
+
async function fetchOne(provider, f, timeoutMs) {
|
|
786
|
+
const controller = new AbortController();
|
|
787
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
722
788
|
try {
|
|
723
|
-
const res = await f(
|
|
789
|
+
const res = await f(provider.url, { signal: controller.signal });
|
|
724
790
|
if (!res.ok) return null;
|
|
725
791
|
const data = await res.json();
|
|
726
|
-
|
|
727
|
-
const city = data.city || void 0;
|
|
728
|
-
if (!country && !city) return null;
|
|
729
|
-
return { country, city };
|
|
792
|
+
return provider.parse(data);
|
|
730
793
|
} catch {
|
|
731
794
|
return null;
|
|
795
|
+
} finally {
|
|
796
|
+
clearTimeout(timer);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
async function fetchGeo(options = {}) {
|
|
800
|
+
const f = options.fetchImpl ?? (typeof fetch !== "undefined" ? fetch : void 0);
|
|
801
|
+
if (!f) return null;
|
|
802
|
+
const providers = options.providers ?? DEFAULT_GEO_PROVIDERS;
|
|
803
|
+
const timeoutMs = options.timeoutMs ?? GEO_TIMEOUT_MS;
|
|
804
|
+
for (const provider of providers) {
|
|
805
|
+
const geo = await fetchOne(provider, f, timeoutMs);
|
|
806
|
+
if (geo) return geo;
|
|
807
|
+
}
|
|
808
|
+
return null;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// src/analytics/language.ts
|
|
812
|
+
function clean(value) {
|
|
813
|
+
const trimmed = value?.trim();
|
|
814
|
+
return trimmed ? trimmed : void 0;
|
|
815
|
+
}
|
|
816
|
+
function resolveLanguage(sources) {
|
|
817
|
+
const explicit = clean(sources.explicit);
|
|
818
|
+
if (explicit) return explicit;
|
|
819
|
+
const navLang = clean(sources.navigator?.language);
|
|
820
|
+
if (navLang) return navLang;
|
|
821
|
+
try {
|
|
822
|
+
const locale = clean(sources.intl?.DateTimeFormat().resolvedOptions().locale);
|
|
823
|
+
if (locale) return locale;
|
|
824
|
+
} catch {
|
|
732
825
|
}
|
|
826
|
+
return void 0;
|
|
733
827
|
}
|
|
734
828
|
|
|
735
829
|
// src/analytics/engagement-tracker.ts
|
|
@@ -901,7 +995,7 @@ var CrashReporter = class {
|
|
|
901
995
|
}
|
|
902
996
|
/** Instala los handlers globales de errores no capturados (no-op sin `window`). */
|
|
903
997
|
install() {
|
|
904
|
-
if (typeof window === "undefined") return;
|
|
998
|
+
if (typeof window === "undefined" || typeof window.addEventListener !== "function") return;
|
|
905
999
|
window.addEventListener("error", (e) => {
|
|
906
1000
|
if (!this.isEnabled()) return;
|
|
907
1001
|
this.captureUnhandled(e.error ?? e.message ?? "error");
|
|
@@ -953,6 +1047,8 @@ var DeepdotsPopups = class {
|
|
|
953
1047
|
this.triggers = [];
|
|
954
1048
|
this.initialized = false;
|
|
955
1049
|
this.renderer = createDefaultRenderer();
|
|
1050
|
+
/** Logger para el output de debug. Default `console`; el host puede inyectar el suyo en init(). */
|
|
1051
|
+
this.logger = console;
|
|
956
1052
|
this.popupContainer = null;
|
|
957
1053
|
// deprecated: mantenido para compatibilidad interna
|
|
958
1054
|
this.popupDefinitions = [];
|
|
@@ -988,6 +1084,8 @@ var DeepdotsPopups = class {
|
|
|
988
1084
|
}
|
|
989
1085
|
/** Initialize the SDK with configuration */
|
|
990
1086
|
init(config) {
|
|
1087
|
+
this.logger = config.logger ?? console;
|
|
1088
|
+
setLogger(this.logger);
|
|
991
1089
|
if (this.initialized) {
|
|
992
1090
|
this.log("SDK already initialized");
|
|
993
1091
|
return;
|
|
@@ -1027,12 +1125,16 @@ var DeepdotsPopups = class {
|
|
|
1027
1125
|
onSessionId: (id) => {
|
|
1028
1126
|
this.analyticsFeedbackSessionId = id;
|
|
1029
1127
|
}
|
|
1030
|
-
}) :
|
|
1128
|
+
}) : createDryRunSink((...a) => this.logger.log(...a));
|
|
1031
1129
|
const device = config.device ?? collectDeviceInfo(config.appVersion);
|
|
1032
1130
|
this.analytics = new AnalyticsManager({
|
|
1033
1131
|
sink: analyticsSink,
|
|
1034
1132
|
publicKey: config.analytics?.publicKey ?? this.config.apiKey,
|
|
1035
|
-
language:
|
|
1133
|
+
language: resolveLanguage({
|
|
1134
|
+
explicit: config.language,
|
|
1135
|
+
navigator: typeof navigator !== "undefined" ? navigator : void 0,
|
|
1136
|
+
intl: typeof Intl !== "undefined" ? Intl : void 0
|
|
1137
|
+
}),
|
|
1036
1138
|
platform: config.platform ?? "web",
|
|
1037
1139
|
device,
|
|
1038
1140
|
maxBatchSize: ANALYTICS_MAX_BATCH_SIZE,
|
|
@@ -1049,8 +1151,13 @@ var DeepdotsPopups = class {
|
|
|
1049
1151
|
if (this.tracking?.isTrackingEnabled()) {
|
|
1050
1152
|
this.crashReporter.install();
|
|
1051
1153
|
}
|
|
1052
|
-
|
|
1053
|
-
|
|
1154
|
+
const cachedGeo = readCachedGeo(storage, Date.now());
|
|
1155
|
+
if (cachedGeo) this.analytics.updateDevice(cachedGeo);
|
|
1156
|
+
fetchGeo().then((geo) => {
|
|
1157
|
+
if (geo) {
|
|
1158
|
+
this.analytics?.updateDevice(geo);
|
|
1159
|
+
writeCachedGeo(storage, geo, Date.now());
|
|
1160
|
+
}
|
|
1054
1161
|
}).catch(() => {
|
|
1055
1162
|
});
|
|
1056
1163
|
this.navObserver = new NavigationObserver();
|
|
@@ -1107,6 +1214,15 @@ var DeepdotsPopups = class {
|
|
|
1107
1214
|
if (!this.tracking?.isTrackingEnabled()) return;
|
|
1108
1215
|
this.analytics?.setUserAttributes(attributes);
|
|
1109
1216
|
}
|
|
1217
|
+
/**
|
|
1218
|
+
* Registra/actualiza una métrica (valor medible) → `feedback.metrics` del body.
|
|
1219
|
+
* Persistente y sobrescribe por key. No-op si tracking off.
|
|
1220
|
+
*/
|
|
1221
|
+
setMetric(key, value) {
|
|
1222
|
+
if (!this.tracking?.isTrackingEnabled()) return;
|
|
1223
|
+
this.analytics?.setMetric(key, value);
|
|
1224
|
+
this.log("analytics \xB7 setMetric:", key, value);
|
|
1225
|
+
}
|
|
1110
1226
|
/** Reporta un error del host (manejado o no) → evento `deepdots_app_crash`. No-op si tracking off. */
|
|
1111
1227
|
reportError(error, options) {
|
|
1112
1228
|
if (!this.tracking?.isTrackingEnabled()) return;
|
|
@@ -1680,7 +1796,7 @@ var DeepdotsPopups = class {
|
|
|
1680
1796
|
}
|
|
1681
1797
|
if (!this.popupContainer) return;
|
|
1682
1798
|
const container = this.popupContainer;
|
|
1683
|
-
void import("./renderPopup-
|
|
1799
|
+
void import("./renderPopup-EZKDMLVZ.mjs").then(({ renderPopup }) => {
|
|
1684
1800
|
renderPopup(
|
|
1685
1801
|
container,
|
|
1686
1802
|
surveyId,
|
|
@@ -1736,7 +1852,8 @@ var DeepdotsPopups = class {
|
|
|
1736
1852
|
try {
|
|
1737
1853
|
listener(event);
|
|
1738
1854
|
} catch (error) {
|
|
1739
|
-
|
|
1855
|
+
if (this.logger.error) this.logger.error("Error in event listener:", error);
|
|
1856
|
+
else this.logger.log("Error in event listener:", error);
|
|
1740
1857
|
}
|
|
1741
1858
|
});
|
|
1742
1859
|
}
|
|
@@ -1744,7 +1861,7 @@ var DeepdotsPopups = class {
|
|
|
1744
1861
|
/** Log debug messages */
|
|
1745
1862
|
log(...args) {
|
|
1746
1863
|
if (this.config?.debug) {
|
|
1747
|
-
|
|
1864
|
+
this.logger.log("[DeepdotsPopups]", ...args);
|
|
1748
1865
|
}
|
|
1749
1866
|
}
|
|
1750
1867
|
/** External debug method for triggers */
|