@magicfeedback/popup-sdk 1.1.6 → 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/index.d.mts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +123 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +121 -12
- package/dist/index.mjs.map +1 -1
- package/dist/react-native.d.mts +15 -1
- package/dist/react-native.d.ts +15 -1
- package/dist/react-native.js +123 -14
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +121 -12
- package/dist/react-native.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react-native.mjs
CHANGED
|
@@ -399,6 +399,8 @@ var AnalyticsManager = class {
|
|
|
399
399
|
constructor(options = {}) {
|
|
400
400
|
this.events = [];
|
|
401
401
|
this.attributes = {};
|
|
402
|
+
/** Métricas del host (valores medibles persistentes). Sobrescriben por key; se reenvían en cada flush. */
|
|
403
|
+
this.metrics = {};
|
|
402
404
|
/** Mini-services activos: nombre → timestamp de entrada. El orden de inserción marca el "más reciente". */
|
|
403
405
|
this.activeMiniServices = /* @__PURE__ */ new Map();
|
|
404
406
|
this.sink = options.sink ?? dryRunSink;
|
|
@@ -421,6 +423,14 @@ var AnalyticsManager = class {
|
|
|
421
423
|
this.attributes[k] = String(v);
|
|
422
424
|
}
|
|
423
425
|
}
|
|
426
|
+
/**
|
|
427
|
+
* Registra/actualiza una métrica (valor medible). Persistente: se reenvía en cada flush.
|
|
428
|
+
* Repetir la misma key SOBRESCRIBE; el valor se coerciona a string; ignora key vacía.
|
|
429
|
+
*/
|
|
430
|
+
setMetric(key, value) {
|
|
431
|
+
if (!key) return;
|
|
432
|
+
this.metrics[key] = String(value);
|
|
433
|
+
}
|
|
424
434
|
/**
|
|
425
435
|
* Marca el inicio de un mini-service; etiqueta los eventos siguientes con `mini_service`.
|
|
426
436
|
* Admite varios activos a la vez (concurrencia); el "actual" para etiquetar es el más reciente.
|
|
@@ -484,7 +494,8 @@ var AnalyticsManager = class {
|
|
|
484
494
|
platform: this.platform,
|
|
485
495
|
language: this.language,
|
|
486
496
|
device: this.device,
|
|
487
|
-
attributes: { ...this.attributes }
|
|
497
|
+
attributes: { ...this.attributes },
|
|
498
|
+
metrics: { ...this.metrics }
|
|
488
499
|
},
|
|
489
500
|
events: [...this.events]
|
|
490
501
|
};
|
|
@@ -540,10 +551,15 @@ function buildAnalyticsFeedbackBody(envelope, keys, feedbackSessionId) {
|
|
|
540
551
|
value: [JSON.stringify({ timestamp: e.timestamp, ...e.params ?? {} })]
|
|
541
552
|
});
|
|
542
553
|
}
|
|
554
|
+
const metrics = [];
|
|
555
|
+
for (const [k, v] of Object.entries(context.metrics ?? {})) {
|
|
556
|
+
pushKV(metrics, k, v);
|
|
557
|
+
}
|
|
543
558
|
return {
|
|
544
559
|
feedback: {
|
|
545
560
|
text: "",
|
|
546
561
|
answers: [],
|
|
562
|
+
metrics,
|
|
547
563
|
metadata,
|
|
548
564
|
profile,
|
|
549
565
|
finished: false
|
|
@@ -724,20 +740,95 @@ function collectDeviceInfo(appVersion) {
|
|
|
724
740
|
}
|
|
725
741
|
|
|
726
742
|
// src/analytics/geo-info.ts
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
743
|
+
var GEO_STORAGE_KEY = "deepdots.geo";
|
|
744
|
+
var GEO_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
745
|
+
var GEO_TIMEOUT_MS = 3e3;
|
|
746
|
+
function readCachedGeo(storage, now) {
|
|
730
747
|
try {
|
|
731
|
-
const
|
|
748
|
+
const raw = storage.getItem(GEO_STORAGE_KEY);
|
|
749
|
+
if (!raw) return null;
|
|
750
|
+
const cached = JSON.parse(raw);
|
|
751
|
+
if (typeof cached.ts !== "number" || now - cached.ts > GEO_TTL_MS) return null;
|
|
752
|
+
const geo = {};
|
|
753
|
+
if (cached.country) geo.country = cached.country;
|
|
754
|
+
if (cached.city) geo.city = cached.city;
|
|
755
|
+
return geo.country || geo.city ? geo : null;
|
|
756
|
+
} catch {
|
|
757
|
+
return null;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
function writeCachedGeo(storage, geo, now) {
|
|
761
|
+
try {
|
|
762
|
+
const payload = { ...geo, ts: now };
|
|
763
|
+
storage.setItem(GEO_STORAGE_KEY, JSON.stringify(payload));
|
|
764
|
+
} catch {
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
var DEFAULT_GEO_PROVIDERS = [
|
|
768
|
+
{
|
|
769
|
+
// https://ipapi.co/json/
|
|
770
|
+
url: "https://ipapi.co/json/",
|
|
771
|
+
parse: (d) => geoFrom(d.country_code, d.city)
|
|
772
|
+
},
|
|
773
|
+
{
|
|
774
|
+
// https://ipwho.is/ (devuelve success:false con 200 en errores)
|
|
775
|
+
url: "https://ipwho.is/",
|
|
776
|
+
parse: (d) => d.success === false ? null : geoFrom(d.country_code, d.city)
|
|
777
|
+
},
|
|
778
|
+
{
|
|
779
|
+
// https://ipinfo.io/json (country = código ISO)
|
|
780
|
+
url: "https://ipinfo.io/json",
|
|
781
|
+
parse: (d) => geoFrom(d.country, d.city)
|
|
782
|
+
}
|
|
783
|
+
];
|
|
784
|
+
function geoFrom(country, city) {
|
|
785
|
+
const c = typeof country === "string" && country ? country : void 0;
|
|
786
|
+
const t = typeof city === "string" && city ? city : void 0;
|
|
787
|
+
if (!c && !t) return null;
|
|
788
|
+
return { country: c, city: t };
|
|
789
|
+
}
|
|
790
|
+
async function fetchOne(provider, f, timeoutMs) {
|
|
791
|
+
const controller = new AbortController();
|
|
792
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
793
|
+
try {
|
|
794
|
+
const res = await f(provider.url, { signal: controller.signal });
|
|
732
795
|
if (!res.ok) return null;
|
|
733
796
|
const data = await res.json();
|
|
734
|
-
|
|
735
|
-
const city = data.city || void 0;
|
|
736
|
-
if (!country && !city) return null;
|
|
737
|
-
return { country, city };
|
|
797
|
+
return provider.parse(data);
|
|
738
798
|
} catch {
|
|
739
799
|
return null;
|
|
800
|
+
} finally {
|
|
801
|
+
clearTimeout(timer);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
async function fetchGeo(options = {}) {
|
|
805
|
+
const f = options.fetchImpl ?? (typeof fetch !== "undefined" ? fetch : void 0);
|
|
806
|
+
if (!f) return null;
|
|
807
|
+
const providers = options.providers ?? DEFAULT_GEO_PROVIDERS;
|
|
808
|
+
const timeoutMs = options.timeoutMs ?? GEO_TIMEOUT_MS;
|
|
809
|
+
for (const provider of providers) {
|
|
810
|
+
const geo = await fetchOne(provider, f, timeoutMs);
|
|
811
|
+
if (geo) return geo;
|
|
812
|
+
}
|
|
813
|
+
return null;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// src/analytics/language.ts
|
|
817
|
+
function clean(value) {
|
|
818
|
+
const trimmed = value?.trim();
|
|
819
|
+
return trimmed ? trimmed : void 0;
|
|
820
|
+
}
|
|
821
|
+
function resolveLanguage(sources) {
|
|
822
|
+
const explicit = clean(sources.explicit);
|
|
823
|
+
if (explicit) return explicit;
|
|
824
|
+
const navLang = clean(sources.navigator?.language);
|
|
825
|
+
if (navLang) return navLang;
|
|
826
|
+
try {
|
|
827
|
+
const locale = clean(sources.intl?.DateTimeFormat().resolvedOptions().locale);
|
|
828
|
+
if (locale) return locale;
|
|
829
|
+
} catch {
|
|
740
830
|
}
|
|
831
|
+
return void 0;
|
|
741
832
|
}
|
|
742
833
|
|
|
743
834
|
// src/analytics/engagement-tracker.ts
|
|
@@ -1044,7 +1135,11 @@ var DeepdotsPopups = class {
|
|
|
1044
1135
|
this.analytics = new AnalyticsManager({
|
|
1045
1136
|
sink: analyticsSink,
|
|
1046
1137
|
publicKey: config.analytics?.publicKey ?? this.config.apiKey,
|
|
1047
|
-
language:
|
|
1138
|
+
language: resolveLanguage({
|
|
1139
|
+
explicit: config.language,
|
|
1140
|
+
navigator: typeof navigator !== "undefined" ? navigator : void 0,
|
|
1141
|
+
intl: typeof Intl !== "undefined" ? Intl : void 0
|
|
1142
|
+
}),
|
|
1048
1143
|
platform: config.platform ?? "web",
|
|
1049
1144
|
device,
|
|
1050
1145
|
maxBatchSize: ANALYTICS_MAX_BATCH_SIZE,
|
|
@@ -1061,8 +1156,13 @@ var DeepdotsPopups = class {
|
|
|
1061
1156
|
if (this.tracking?.isTrackingEnabled()) {
|
|
1062
1157
|
this.crashReporter.install();
|
|
1063
1158
|
}
|
|
1064
|
-
|
|
1065
|
-
|
|
1159
|
+
const cachedGeo = readCachedGeo(storage, Date.now());
|
|
1160
|
+
if (cachedGeo) this.analytics.updateDevice(cachedGeo);
|
|
1161
|
+
fetchGeo().then((geo) => {
|
|
1162
|
+
if (geo) {
|
|
1163
|
+
this.analytics?.updateDevice(geo);
|
|
1164
|
+
writeCachedGeo(storage, geo, Date.now());
|
|
1165
|
+
}
|
|
1066
1166
|
}).catch(() => {
|
|
1067
1167
|
});
|
|
1068
1168
|
this.navObserver = new NavigationObserver();
|
|
@@ -1119,6 +1219,15 @@ var DeepdotsPopups = class {
|
|
|
1119
1219
|
if (!this.tracking?.isTrackingEnabled()) return;
|
|
1120
1220
|
this.analytics?.setUserAttributes(attributes);
|
|
1121
1221
|
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Registra/actualiza una métrica (valor medible) → `feedback.metrics` del body.
|
|
1224
|
+
* Persistente y sobrescribe por key. No-op si tracking off.
|
|
1225
|
+
*/
|
|
1226
|
+
setMetric(key, value) {
|
|
1227
|
+
if (!this.tracking?.isTrackingEnabled()) return;
|
|
1228
|
+
this.analytics?.setMetric(key, value);
|
|
1229
|
+
this.log("analytics \xB7 setMetric:", key, value);
|
|
1230
|
+
}
|
|
1122
1231
|
/** Reporta un error del host (manejado o no) → evento `deepdots_app_crash`. No-op si tracking off. */
|
|
1123
1232
|
reportError(error, options) {
|
|
1124
1233
|
if (!this.tracking?.isTrackingEnabled()) return;
|