@magicfeedback/popup-sdk 1.1.6 → 1.1.8
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 +5 -0
- package/dist/index.d.mts +63 -8
- package/dist/index.d.ts +63 -8
- package/dist/index.js +244 -43
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +242 -41
- package/dist/index.mjs.map +1 -1
- package/dist/react-native.d.mts +30 -3
- package/dist/react-native.d.ts +30 -3
- package/dist/react-native.js +244 -43
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +242 -41
- package/dist/react-native.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -177,6 +177,11 @@ Config fields:
|
|
|
177
177
|
- `mode?: 'server' | 'client'`
|
|
178
178
|
- `debug?: boolean`
|
|
179
179
|
- `popups?: PopupDefinition[]`
|
|
180
|
+
- `language?: string` — BCP-47 tag (`'en'`, `'en-US'`, …) used for popup language
|
|
181
|
+
segmentation (`segments.lang`) and for the analytics context. If omitted it is
|
|
182
|
+
auto-detected from `navigator.language`, falling back to the `Intl` locale (which is
|
|
183
|
+
what makes it work in React Native, where `navigator.language` does not exist). If no
|
|
184
|
+
source resolves a language, popups with `segments.lang` cannot be filtered and are shown.
|
|
180
185
|
|
|
181
186
|
### `autoLaunch()`
|
|
182
187
|
|
package/dist/index.d.mts
CHANGED
|
@@ -86,10 +86,25 @@ interface AnalyticsEnvelope {
|
|
|
86
86
|
device?: DeviceInfo;
|
|
87
87
|
/** User attributes del cliente, usados para breakdowns (registration_status, pass_type, …). */
|
|
88
88
|
attributes: Record<string, string>;
|
|
89
|
+
/** Métricas del host: valores medibles persistentes → van en `feedback.metrics` del body. */
|
|
90
|
+
metrics?: Record<string, string>;
|
|
89
91
|
};
|
|
90
92
|
events: AnalyticsEvent[];
|
|
91
93
|
}
|
|
92
|
-
|
|
94
|
+
/** Contexto del flush, para que el sink pueda adaptar el transporte. */
|
|
95
|
+
interface AnalyticsFlushMeta {
|
|
96
|
+
/**
|
|
97
|
+
* `true` cuando el flush ocurre porque la página/app se está cerrando. El sink debe usar
|
|
98
|
+
* un transporte que sobreviva al unload (sendBeacon) y no puede esperar respuestas.
|
|
99
|
+
*/
|
|
100
|
+
final?: boolean;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Envío del lote. Si devuelve una promesa que **rechaza**, el manager re-encola los
|
|
104
|
+
* eventos para reintentarlos en el siguiente flush (fallo transitorio: red o 5xx).
|
|
105
|
+
* Resolver = lote entregado o descartado definitivamente (no se reintenta).
|
|
106
|
+
*/
|
|
107
|
+
type AnalyticsSink = (payload: AnalyticsEnvelope, meta?: AnalyticsFlushMeta) => void | Promise<void>;
|
|
93
108
|
|
|
94
109
|
/**
|
|
95
110
|
* Mapeo del envelope de analytics → body de `POST /sdk/feedback`.
|
|
@@ -103,7 +118,8 @@ type AnalyticsSink = (payload: AnalyticsEnvelope) => void;
|
|
|
103
118
|
* - cada entrada usa `value: string[]` (array de un elemento)
|
|
104
119
|
* - eventos: {key: nombre_evento, value: [JSON(timestamp + params)]}
|
|
105
120
|
* - identidad (user_id) → `profile` como `external-user-id`
|
|
106
|
-
* -
|
|
121
|
+
* - métricas del host (setMetric) → `feedback.metrics` (mismo shape que metadata, sin prefijo)
|
|
122
|
+
* - `answers` vacío
|
|
107
123
|
* - `text` vacío
|
|
108
124
|
*/
|
|
109
125
|
|
|
@@ -119,6 +135,7 @@ interface AnalyticsFeedbackBody {
|
|
|
119
135
|
feedback: {
|
|
120
136
|
text: string;
|
|
121
137
|
answers: FeedbackKV[];
|
|
138
|
+
metrics: FeedbackKV[];
|
|
122
139
|
metadata: FeedbackKV[];
|
|
123
140
|
profile: FeedbackKV[];
|
|
124
141
|
finished: boolean;
|
|
@@ -139,15 +156,29 @@ interface FeedbackSinkOptions {
|
|
|
139
156
|
log?: (...args: unknown[]) => void;
|
|
140
157
|
/** fetch inyectable (tests / RN). */
|
|
141
158
|
fetchImpl?: typeof fetch;
|
|
159
|
+
/**
|
|
160
|
+
* `navigator.sendBeacon` inyectable. Solo se usa en el flush final (cierre de página):
|
|
161
|
+
* sobrevive al unload, a cambio de no poder leer la respuesta. Si no se pasa, el flush
|
|
162
|
+
* final usa `fetch` con `keepalive`.
|
|
163
|
+
*/
|
|
164
|
+
sendBeaconImpl?: (url: string, body: Blob | string) => boolean;
|
|
142
165
|
/** Callback invocado cuando el backend devuelve un nuevo sessionId (primer POST). */
|
|
143
166
|
onSessionId?: (id: string) => void;
|
|
144
167
|
}
|
|
145
168
|
/**
|
|
146
169
|
* Sink real: transforma el envelope y hace `POST {baseUrl}/sdk/feedback`.
|
|
147
|
-
*
|
|
148
|
-
* Stateful: cachea el `sessionId` que devuelve el backend en la primera respuesta
|
|
149
|
-
*
|
|
150
|
-
*
|
|
170
|
+
*
|
|
171
|
+
* Stateful: cachea el `sessionId` que devuelve el backend en la primera respuesta y lo
|
|
172
|
+
* envía en los siguientes POSTs para que el backend agrupe todos los eventos en un único
|
|
173
|
+
* registro de feedback.
|
|
174
|
+
*
|
|
175
|
+
* Garantías de entrega:
|
|
176
|
+
* - mientras no se conozca el `sessionId`, los lotes se **serializan** (esperan la primera
|
|
177
|
+
* respuesta): dos POSTs a la vez sin `sessionId` crearían dos registros y partirían los datos;
|
|
178
|
+
* - `keepalive` para que el navegador no cancele el POST al navegar fuera, y `sendBeacon`
|
|
179
|
+
* en el flush final (cierre de página), donde `fetch` puede morir con el documento;
|
|
180
|
+
* - la promesa **rechaza** en fallo transitorio (red, 5xx, 408, 429) para que el
|
|
181
|
+
* `AnalyticsManager` re-encole el lote; un 4xx se loguea y se descarta.
|
|
151
182
|
*/
|
|
152
183
|
declare function createFeedbackSink(options: FeedbackSinkOptions): AnalyticsSink;
|
|
153
184
|
|
|
@@ -185,6 +216,14 @@ interface DeepdotsInitParams {
|
|
|
185
216
|
storage?: KeyValueStorage;
|
|
186
217
|
/** Platform used in the analytics envelope. Default is 'web'; in RN pass 'android'/'ios'. */
|
|
187
218
|
platform?: 'web' | 'android' | 'ios';
|
|
219
|
+
/**
|
|
220
|
+
* BCP-47 language tag (e.g. 'es-ES') used for the analytics context AND for popup
|
|
221
|
+
* language segmentation (`segments.lang`). If omitted, the SDK auto-detects:
|
|
222
|
+
* `navigator.language` on web, or the `Intl` locale as a fallback (works in
|
|
223
|
+
* React Native with Hermes, where `navigator.language` is absent). If no source
|
|
224
|
+
* resolves a language, popups with `segments.lang` cannot be filtered and are shown.
|
|
225
|
+
*/
|
|
226
|
+
language?: string;
|
|
188
227
|
/** Injectable device info (RN: from react-native-device-info). If missing, it is derived from the browser. */
|
|
189
228
|
device?: DeviceInfo;
|
|
190
229
|
/**
|
|
@@ -517,6 +556,11 @@ declare class DeepdotsPopups {
|
|
|
517
556
|
private contact;
|
|
518
557
|
/** Marca si ya se inició la navegación manual (setScreen) — para RN sin History API. */
|
|
519
558
|
private navStarted;
|
|
559
|
+
/**
|
|
560
|
+
* Idioma resuelto en init() (explícito > navigator.language > Intl). Única fuente de
|
|
561
|
+
* verdad para el context de analytics Y para la segmentación por idioma de los popups.
|
|
562
|
+
*/
|
|
563
|
+
private language;
|
|
520
564
|
/** Initialize the SDK with configuration */
|
|
521
565
|
init(config: DeepdotsInitParams): void;
|
|
522
566
|
/** User id actual (generado por el SDK o provisto por el cliente). Null si tracking off. */
|
|
@@ -529,6 +573,11 @@ declare class DeepdotsPopups {
|
|
|
529
573
|
track(name: string, params?: Record<string, unknown>): void;
|
|
530
574
|
/** User attributes para breakdowns (registration_status, pass_type, sector, pass_status…). */
|
|
531
575
|
setUserAttributes(attributes: Record<string, string | number | boolean>): void;
|
|
576
|
+
/**
|
|
577
|
+
* Registra/actualiza una métrica (valor medible) → `feedback.metrics` del body.
|
|
578
|
+
* Persistente y sobrescribe por key. No-op si tracking off.
|
|
579
|
+
*/
|
|
580
|
+
setMetric(key: string, value: string | number | boolean): void;
|
|
532
581
|
/** Reporta un error del host (manejado o no) → evento `deepdots_app_crash`. No-op si tracking off. */
|
|
533
582
|
reportError(error: unknown, options?: ReportErrorOptions): void;
|
|
534
583
|
/** Engancha `global.ErrorUtils` de RN para capturar errores JS no manejados. No-op si tracking off. */
|
|
@@ -566,8 +615,14 @@ declare class DeepdotsPopups {
|
|
|
566
615
|
onBackground(): void;
|
|
567
616
|
/** Payload que se ENVIARÍA al endpoint de analytics (no envía ni vacía el buffer). */
|
|
568
617
|
previewAnalytics(): AnalyticsEnvelope;
|
|
569
|
-
/**
|
|
570
|
-
|
|
618
|
+
/**
|
|
619
|
+
* Envía el lote acumulado de analytics y vacía el buffer.
|
|
620
|
+
* `final: true` (cierre de página/app) cambia el transporte a `sendBeacon`, que sobrevive
|
|
621
|
+
* al unload; un lote que falle por red o 5xx se re-encola para el siguiente flush.
|
|
622
|
+
*/
|
|
623
|
+
flushAnalytics(options?: {
|
|
624
|
+
final?: boolean;
|
|
625
|
+
}): void;
|
|
571
626
|
/** Emite un evento `user_engagement` con el tiempo activo acumulado (#8). */
|
|
572
627
|
private flushEngagement;
|
|
573
628
|
private analyticsIdentity;
|
package/dist/index.d.ts
CHANGED
|
@@ -86,10 +86,25 @@ interface AnalyticsEnvelope {
|
|
|
86
86
|
device?: DeviceInfo;
|
|
87
87
|
/** User attributes del cliente, usados para breakdowns (registration_status, pass_type, …). */
|
|
88
88
|
attributes: Record<string, string>;
|
|
89
|
+
/** Métricas del host: valores medibles persistentes → van en `feedback.metrics` del body. */
|
|
90
|
+
metrics?: Record<string, string>;
|
|
89
91
|
};
|
|
90
92
|
events: AnalyticsEvent[];
|
|
91
93
|
}
|
|
92
|
-
|
|
94
|
+
/** Contexto del flush, para que el sink pueda adaptar el transporte. */
|
|
95
|
+
interface AnalyticsFlushMeta {
|
|
96
|
+
/**
|
|
97
|
+
* `true` cuando el flush ocurre porque la página/app se está cerrando. El sink debe usar
|
|
98
|
+
* un transporte que sobreviva al unload (sendBeacon) y no puede esperar respuestas.
|
|
99
|
+
*/
|
|
100
|
+
final?: boolean;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Envío del lote. Si devuelve una promesa que **rechaza**, el manager re-encola los
|
|
104
|
+
* eventos para reintentarlos en el siguiente flush (fallo transitorio: red o 5xx).
|
|
105
|
+
* Resolver = lote entregado o descartado definitivamente (no se reintenta).
|
|
106
|
+
*/
|
|
107
|
+
type AnalyticsSink = (payload: AnalyticsEnvelope, meta?: AnalyticsFlushMeta) => void | Promise<void>;
|
|
93
108
|
|
|
94
109
|
/**
|
|
95
110
|
* Mapeo del envelope de analytics → body de `POST /sdk/feedback`.
|
|
@@ -103,7 +118,8 @@ type AnalyticsSink = (payload: AnalyticsEnvelope) => void;
|
|
|
103
118
|
* - cada entrada usa `value: string[]` (array de un elemento)
|
|
104
119
|
* - eventos: {key: nombre_evento, value: [JSON(timestamp + params)]}
|
|
105
120
|
* - identidad (user_id) → `profile` como `external-user-id`
|
|
106
|
-
* -
|
|
121
|
+
* - métricas del host (setMetric) → `feedback.metrics` (mismo shape que metadata, sin prefijo)
|
|
122
|
+
* - `answers` vacío
|
|
107
123
|
* - `text` vacío
|
|
108
124
|
*/
|
|
109
125
|
|
|
@@ -119,6 +135,7 @@ interface AnalyticsFeedbackBody {
|
|
|
119
135
|
feedback: {
|
|
120
136
|
text: string;
|
|
121
137
|
answers: FeedbackKV[];
|
|
138
|
+
metrics: FeedbackKV[];
|
|
122
139
|
metadata: FeedbackKV[];
|
|
123
140
|
profile: FeedbackKV[];
|
|
124
141
|
finished: boolean;
|
|
@@ -139,15 +156,29 @@ interface FeedbackSinkOptions {
|
|
|
139
156
|
log?: (...args: unknown[]) => void;
|
|
140
157
|
/** fetch inyectable (tests / RN). */
|
|
141
158
|
fetchImpl?: typeof fetch;
|
|
159
|
+
/**
|
|
160
|
+
* `navigator.sendBeacon` inyectable. Solo se usa en el flush final (cierre de página):
|
|
161
|
+
* sobrevive al unload, a cambio de no poder leer la respuesta. Si no se pasa, el flush
|
|
162
|
+
* final usa `fetch` con `keepalive`.
|
|
163
|
+
*/
|
|
164
|
+
sendBeaconImpl?: (url: string, body: Blob | string) => boolean;
|
|
142
165
|
/** Callback invocado cuando el backend devuelve un nuevo sessionId (primer POST). */
|
|
143
166
|
onSessionId?: (id: string) => void;
|
|
144
167
|
}
|
|
145
168
|
/**
|
|
146
169
|
* Sink real: transforma el envelope y hace `POST {baseUrl}/sdk/feedback`.
|
|
147
|
-
*
|
|
148
|
-
* Stateful: cachea el `sessionId` que devuelve el backend en la primera respuesta
|
|
149
|
-
*
|
|
150
|
-
*
|
|
170
|
+
*
|
|
171
|
+
* Stateful: cachea el `sessionId` que devuelve el backend en la primera respuesta y lo
|
|
172
|
+
* envía en los siguientes POSTs para que el backend agrupe todos los eventos en un único
|
|
173
|
+
* registro de feedback.
|
|
174
|
+
*
|
|
175
|
+
* Garantías de entrega:
|
|
176
|
+
* - mientras no se conozca el `sessionId`, los lotes se **serializan** (esperan la primera
|
|
177
|
+
* respuesta): dos POSTs a la vez sin `sessionId` crearían dos registros y partirían los datos;
|
|
178
|
+
* - `keepalive` para que el navegador no cancele el POST al navegar fuera, y `sendBeacon`
|
|
179
|
+
* en el flush final (cierre de página), donde `fetch` puede morir con el documento;
|
|
180
|
+
* - la promesa **rechaza** en fallo transitorio (red, 5xx, 408, 429) para que el
|
|
181
|
+
* `AnalyticsManager` re-encole el lote; un 4xx se loguea y se descarta.
|
|
151
182
|
*/
|
|
152
183
|
declare function createFeedbackSink(options: FeedbackSinkOptions): AnalyticsSink;
|
|
153
184
|
|
|
@@ -185,6 +216,14 @@ interface DeepdotsInitParams {
|
|
|
185
216
|
storage?: KeyValueStorage;
|
|
186
217
|
/** Platform used in the analytics envelope. Default is 'web'; in RN pass 'android'/'ios'. */
|
|
187
218
|
platform?: 'web' | 'android' | 'ios';
|
|
219
|
+
/**
|
|
220
|
+
* BCP-47 language tag (e.g. 'es-ES') used for the analytics context AND for popup
|
|
221
|
+
* language segmentation (`segments.lang`). If omitted, the SDK auto-detects:
|
|
222
|
+
* `navigator.language` on web, or the `Intl` locale as a fallback (works in
|
|
223
|
+
* React Native with Hermes, where `navigator.language` is absent). If no source
|
|
224
|
+
* resolves a language, popups with `segments.lang` cannot be filtered and are shown.
|
|
225
|
+
*/
|
|
226
|
+
language?: string;
|
|
188
227
|
/** Injectable device info (RN: from react-native-device-info). If missing, it is derived from the browser. */
|
|
189
228
|
device?: DeviceInfo;
|
|
190
229
|
/**
|
|
@@ -517,6 +556,11 @@ declare class DeepdotsPopups {
|
|
|
517
556
|
private contact;
|
|
518
557
|
/** Marca si ya se inició la navegación manual (setScreen) — para RN sin History API. */
|
|
519
558
|
private navStarted;
|
|
559
|
+
/**
|
|
560
|
+
* Idioma resuelto en init() (explícito > navigator.language > Intl). Única fuente de
|
|
561
|
+
* verdad para el context de analytics Y para la segmentación por idioma de los popups.
|
|
562
|
+
*/
|
|
563
|
+
private language;
|
|
520
564
|
/** Initialize the SDK with configuration */
|
|
521
565
|
init(config: DeepdotsInitParams): void;
|
|
522
566
|
/** User id actual (generado por el SDK o provisto por el cliente). Null si tracking off. */
|
|
@@ -529,6 +573,11 @@ declare class DeepdotsPopups {
|
|
|
529
573
|
track(name: string, params?: Record<string, unknown>): void;
|
|
530
574
|
/** User attributes para breakdowns (registration_status, pass_type, sector, pass_status…). */
|
|
531
575
|
setUserAttributes(attributes: Record<string, string | number | boolean>): void;
|
|
576
|
+
/**
|
|
577
|
+
* Registra/actualiza una métrica (valor medible) → `feedback.metrics` del body.
|
|
578
|
+
* Persistente y sobrescribe por key. No-op si tracking off.
|
|
579
|
+
*/
|
|
580
|
+
setMetric(key: string, value: string | number | boolean): void;
|
|
532
581
|
/** Reporta un error del host (manejado o no) → evento `deepdots_app_crash`. No-op si tracking off. */
|
|
533
582
|
reportError(error: unknown, options?: ReportErrorOptions): void;
|
|
534
583
|
/** Engancha `global.ErrorUtils` de RN para capturar errores JS no manejados. No-op si tracking off. */
|
|
@@ -566,8 +615,14 @@ declare class DeepdotsPopups {
|
|
|
566
615
|
onBackground(): void;
|
|
567
616
|
/** Payload que se ENVIARÍA al endpoint de analytics (no envía ni vacía el buffer). */
|
|
568
617
|
previewAnalytics(): AnalyticsEnvelope;
|
|
569
|
-
/**
|
|
570
|
-
|
|
618
|
+
/**
|
|
619
|
+
* Envía el lote acumulado de analytics y vacía el buffer.
|
|
620
|
+
* `final: true` (cierre de página/app) cambia el transporte a `sendBeacon`, que sobrevive
|
|
621
|
+
* al unload; un lote que falle por red o 5xx se re-encola para el siguiente flush.
|
|
622
|
+
*/
|
|
623
|
+
flushAnalytics(options?: {
|
|
624
|
+
final?: boolean;
|
|
625
|
+
}): void;
|
|
571
626
|
/** Emite un evento `user_engagement` con el tiempo activo acumulado (#8). */
|
|
572
627
|
private flushEngagement;
|
|
573
628
|
private analyticsIdentity;
|