@magicfeedback/popup-sdk 1.8.1 → 1.8.3
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 +32 -1
- package/dist/index.d.mts +71 -12
- package/dist/index.d.ts +71 -12
- package/dist/index.js +172 -33
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +172 -33
- package/dist/index.mjs.map +1 -1
- package/dist/react-native.d.mts +52 -5
- package/dist/react-native.d.ts +52 -5
- package/dist/react-native.js +172 -33
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +172 -33
- package/dist/react-native.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -122,6 +122,11 @@ Config fields:
|
|
|
122
122
|
- `trackingEnabled?: boolean` — starts analytics on (default) or off, for consent flows
|
|
123
123
|
- `analytics?: { publicKey: string; integration: string }` — enables the real analytics
|
|
124
124
|
delivery. Without it the analytics channel stays in dry-run and only logs the payload.
|
|
125
|
+
- `geolocation?: boolean` — IP geolocation (country/city) for analytics, default `true`. It
|
|
126
|
+
calls third-party services (`ipapi.co`, then `ipwho.is`, then `ipinfo.io` as fallbacks, 3 s
|
|
127
|
+
timeout each, stopping at the first answer). It only runs when `analytics` is set, tracking
|
|
128
|
+
is enabled and the 30-day cache is missing or expired, at most once per SDK instance. Pass
|
|
129
|
+
`false` to never call those services nor attach country/city.
|
|
125
130
|
- `appVersion?: string` — reported in the analytics device context
|
|
126
131
|
- `storage?: KeyValueStorage` — persistence override (React Native uses MMKV; the browser
|
|
127
132
|
defaults to `localStorage`)
|
|
@@ -268,7 +273,7 @@ session start/end and unhandled errors are automatic. The rest is instrumented b
|
|
|
268
273
|
| `trackFunnelStep(funnel, step, taskId, params?)` | A funnel step, correlated by `taskId` |
|
|
269
274
|
| `trackFindabilityFriction(topic, params?)` | Friction signal |
|
|
270
275
|
| `trackMeaningfulInteraction(interactionType, params?)` | A meaningful interaction, grouped by `interaction_type` |
|
|
271
|
-
| `enterMiniService(name, entryPointType?)` / `exitMiniService(name)` |
|
|
276
|
+
| `enterMiniService(name, entryPointType?)` / `exitMiniService(name)` | A task flow with a start and an end — [not a page](#mini-services--enterminiservicename-entrypointtype--exitminiservicename) |
|
|
272
277
|
| `setUserAttributes(map)` / `setMetric(key, value)` | Breakdown dimensions / measurable values |
|
|
273
278
|
| `setUserId(userId?)` | Login, logout or account switch |
|
|
274
279
|
| `endSession()` | Closes the session explicitly |
|
|
@@ -332,6 +337,32 @@ values (oldest evicted first). A rejected event does not consume state: after a
|
|
|
332
337
|
> restricted permissions, will not fire it — so a client-side `delivered` count sits below the
|
|
333
338
|
> real one. For a reliable denominator, take `delivered` from your sending provider.
|
|
334
339
|
|
|
340
|
+
### Mini-services — `enterMiniService(name, entryPointType?)` / `exitMiniService(name)`
|
|
341
|
+
|
|
342
|
+
A mini-service is a **self-contained task inside the app, with a start and an end**: a booking,
|
|
343
|
+
a checkout, an onboarding, a form the user fills in. Deepdots treats it as a flow. It reports
|
|
344
|
+
completion and drop-off per mini-service, draws it in the session journey as a lane between
|
|
345
|
+
where it was entered and where it was left, and tags every event emitted while it is active
|
|
346
|
+
with `mini_service`.
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
popups.enterMiniService('checkout', 'cart_button'); // the user starts the task
|
|
350
|
+
// ...
|
|
351
|
+
popups.exitMiniService('checkout'); // and finishes it
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
- Enter it when the task starts and exit it when the task is done. One still open when the
|
|
355
|
+
session closes is exited by the SDK.
|
|
356
|
+
- `entryPointType` is optional and says where the user started it from (a banner, a menu, a
|
|
357
|
+
deep link). It is sent as `entry_point_type`.
|
|
358
|
+
|
|
359
|
+
**A mini-service is not a page, a section or an area of the app.** Navigation is already
|
|
360
|
+
recorded as `page_view`, with the screen and how long the user stayed on it, and time per area
|
|
361
|
+
comes from grouping those page views by screen. Opening a mini-service for every section turns
|
|
362
|
+
each navigation into an abandoned flow: a move from `/feedback` to `/explorer` reads as
|
|
363
|
+
*"entered the explorer mini-service and never completed it"*, the journey loses the edge
|
|
364
|
+
between the two pages, and every section counts as drop-off.
|
|
365
|
+
|
|
335
366
|
## Supported Trigger Types
|
|
336
367
|
|
|
337
368
|
Popup definitions use these trigger types:
|
package/dist/index.d.mts
CHANGED
|
@@ -95,7 +95,8 @@ interface AnalyticsEnvelope {
|
|
|
95
95
|
interface AnalyticsFlushMeta {
|
|
96
96
|
/**
|
|
97
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 (
|
|
98
|
+
* un transporte que sobreviva al unload (`fetch` con `keepalive`) y no puede esperar
|
|
99
|
+
* respuestas.
|
|
99
100
|
*/
|
|
100
101
|
final?: boolean;
|
|
101
102
|
/**
|
|
@@ -104,6 +105,12 @@ interface AnalyticsFlushMeta {
|
|
|
104
105
|
* el `sessionId`, para que el lote siguiente abra un registro nuevo.
|
|
105
106
|
*/
|
|
106
107
|
sessionEnd?: boolean;
|
|
108
|
+
/**
|
|
109
|
+
* `true` para olvidar la sesión SIN enviar nada (el payload llega vacío): el backend ya la
|
|
110
|
+
* cerró por inactividad. El sink descarta su `sessionId` para que el lote siguiente abra un
|
|
111
|
+
* registro nuevo, igual que tras `sessionEnd`, pero sin POST.
|
|
112
|
+
*/
|
|
113
|
+
resetSession?: boolean;
|
|
107
114
|
}
|
|
108
115
|
/**
|
|
109
116
|
* Envío del lote. Si devuelve una promesa que **rechaza**, el manager re-encola los
|
|
@@ -174,9 +181,11 @@ interface FeedbackSinkOptions {
|
|
|
174
181
|
/** fetch inyectable (tests / RN). */
|
|
175
182
|
fetchImpl?: typeof fetch;
|
|
176
183
|
/**
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
184
|
+
* @deprecated Se ignora. El flush final salía por `sendBeacon`, que va SIEMPRE con
|
|
185
|
+
* credenciales; contra la API (`Access-Control-Allow-Origin: *` + `Allow-Credentials:
|
|
186
|
+
* true`) el preflight fallaba y el lote de cierre, el único con `completed:true`, no
|
|
187
|
+
* llegaba nunca. Ahora sale por `fetch` con `keepalive`. Se mantiene en el tipo para no
|
|
188
|
+
* romper a quien lo pase.
|
|
180
189
|
*/
|
|
181
190
|
sendBeaconImpl?: (url: string, body: Blob | string) => boolean;
|
|
182
191
|
/** Callback invocado cuando el backend devuelve un nuevo sessionId (primer POST). */
|
|
@@ -194,8 +203,9 @@ interface FeedbackSinkOptions {
|
|
|
194
203
|
* Garantías de entrega:
|
|
195
204
|
* - mientras no se conozca el `sessionId`, los lotes se **serializan** (esperan la primera
|
|
196
205
|
* respuesta): dos POSTs a la vez sin `sessionId` crearían dos registros y partirían los datos;
|
|
197
|
-
* - `keepalive` para que el navegador no cancele el POST al navegar fuera
|
|
198
|
-
* en el flush final (
|
|
206
|
+
* - `keepalive` para que el navegador no cancele el POST al navegar fuera ni al cerrar la
|
|
207
|
+
* página, también en el flush final (sin `sendBeacon`: ver `sendBeaconImpl`);
|
|
208
|
+
* - sin credenciales, que es lo único que pasa el CORS de la API (`Allow-Origin: *`);
|
|
199
209
|
* - la promesa **rechaza** en fallo transitorio (red, 5xx, 408, 429) para que el
|
|
200
210
|
* `AnalyticsManager` re-encole el lote; un 4xx se loguea y se descarta.
|
|
201
211
|
*/
|
|
@@ -250,6 +260,13 @@ interface DeepdotsInitParams {
|
|
|
250
260
|
* to the configured integration; if missing, it stays in dry-run mode (console.log only).
|
|
251
261
|
*/
|
|
252
262
|
analytics?: AnalyticsKeys;
|
|
263
|
+
/**
|
|
264
|
+
* IP geolocation (country/city) added to analytics. Default `true`. The lookup calls
|
|
265
|
+
* third-party services (ipapi.co, then ipwho.is, then ipinfo.io as fallbacks, 3 s timeout
|
|
266
|
+
* each) and only runs when `analytics` is configured, tracking is enabled and the 30-day
|
|
267
|
+
* cache is missing or expired. Set `false` to never call them nor attach country/city.
|
|
268
|
+
*/
|
|
269
|
+
geolocation?: boolean;
|
|
253
270
|
/**
|
|
254
271
|
* Internal user attributes known only by the host (language, age, plan, ...), sent
|
|
255
272
|
* to the backend Contact for segmentation/targeting. Requires `userId`. Equivalent to calling
|
|
@@ -326,8 +343,10 @@ type EventListener = (event: DeepdotsEvent) => void;
|
|
|
326
343
|
* - `user_change`: `setUserId()` o un `init()` con otro `userId` (login/logout del host).
|
|
327
344
|
* - `tracking_disabled`: `setTrackingEnabled(false)` (consentimiento revocado).
|
|
328
345
|
* - `manual`: `endSession()` llamado por el host.
|
|
346
|
+
* - `idle_timeout`: la pestaña vuelve a verse tras más de 30 min oculta (web). La sesión
|
|
347
|
+
* anterior se cierra y se abre otra, como hace GA con su timeout de sesión.
|
|
329
348
|
*/
|
|
330
|
-
type SessionEndReason = 'page_hide' | 'background' | 'user_change' | 'tracking_disabled' | 'manual';
|
|
349
|
+
type SessionEndReason = 'page_hide' | 'background' | 'user_change' | 'tracking_disabled' | 'manual' | 'idle_timeout';
|
|
331
350
|
/** Trigger type used by remote popup definitions */
|
|
332
351
|
type PopupTriggerType = 'time_on_page' | 'scroll' | 'exit' | 'click' | 'event';
|
|
333
352
|
type PopupTriggerConditionStatus = 'SHOWED' | 'PARTIAL' | 'COMPLETED';
|
|
@@ -700,11 +719,21 @@ declare class DeepdotsPopups {
|
|
|
700
719
|
* nueva al volver a foreground o al conceder el consentimiento más tarde.
|
|
701
720
|
*/
|
|
702
721
|
private sessionOpen;
|
|
722
|
+
/** Último `user_engagement` emitido (ms epoch): marca el latido. */
|
|
723
|
+
private lastEngagementAt;
|
|
724
|
+
/** Cuándo se ocultó la pestaña por última vez (ms epoch); null si está visible. */
|
|
725
|
+
private hiddenAt;
|
|
703
726
|
/**
|
|
704
727
|
* Idioma resuelto en init() (explícito > navigator.language > Intl). Única fuente de
|
|
705
728
|
* verdad para el context de analytics Y para la segmentación por idioma de los popups.
|
|
706
729
|
*/
|
|
707
730
|
private language;
|
|
731
|
+
/** `geolocation` del init: si es false no se usa ni la caché ni el lookup. */
|
|
732
|
+
private geoEnabled;
|
|
733
|
+
/** Solo se consulta a terceros si el país/ciudad se va a enviar (analytics configurado). */
|
|
734
|
+
private geoWanted;
|
|
735
|
+
/** Evita más de un lookup por instancia (el consentimiento puede ir y venir). */
|
|
736
|
+
private geoLookupStarted;
|
|
708
737
|
/** Initialize the SDK with configuration */
|
|
709
738
|
init(config: DeepdotsInitParams): void;
|
|
710
739
|
/** User id actual (generado por el SDK o provisto por el cliente). Null si tracking off. */
|
|
@@ -801,12 +830,14 @@ declare class DeepdotsPopups {
|
|
|
801
830
|
* se llama en init(), al volver a foreground y al conceder el consentimiento.
|
|
802
831
|
*/
|
|
803
832
|
private openSession;
|
|
833
|
+
/** Web: si la pestaña se ve. Sin `document` (RN) manda AppState vía onForeground/onBackground. */
|
|
834
|
+
private isDocumentVisible;
|
|
804
835
|
/** Payload que se ENVIARÍA al endpoint de analytics (no envía ni vacía el buffer). */
|
|
805
836
|
previewAnalytics(): AnalyticsEnvelope;
|
|
806
837
|
/**
|
|
807
838
|
* Envía el lote acumulado de analytics y vacía el buffer.
|
|
808
|
-
* `final: true` (cierre de página/app)
|
|
809
|
-
*
|
|
839
|
+
* `final: true` (cierre de página/app): el lote no espera al primer POST en vuelo, porque
|
|
840
|
+
* el documento se muere; un lote que falle por red o 5xx se re-encola para el siguiente flush.
|
|
810
841
|
*/
|
|
811
842
|
flushAnalytics(options?: {
|
|
812
843
|
final?: boolean;
|
|
@@ -814,9 +845,30 @@ declare class DeepdotsPopups {
|
|
|
814
845
|
}): void;
|
|
815
846
|
/** Emite un evento `user_engagement` con el tiempo activo acumulado (#8). */
|
|
816
847
|
private flushEngagement;
|
|
848
|
+
/** Tick del flush periódico: latido de engagement si toca, y envío de lo acumulado. */
|
|
849
|
+
private onAnalyticsFlushTick;
|
|
850
|
+
/**
|
|
851
|
+
* La pestaña vuelve a verse. Tras más de ANALYTICS_SESSION_TIMEOUT_MS oculta, la sesión
|
|
852
|
+
* anterior termina y empieza otra: seguir con el mismo sessionId mezclaba dos visitas y,
|
|
853
|
+
* si el backend ya la había cerrado por inactividad, la partía en dos feedbacks.
|
|
854
|
+
* - Oculta menos de ANALYTICS_SESSION_DISCARD_MS: el backend aún la tiene abierta → se
|
|
855
|
+
* cierra con normalidad (page_view de la pantalla, session_end `idle_timeout`, completed).
|
|
856
|
+
* - Más: ya la cerró el backend → se descarta sin enviar nada.
|
|
857
|
+
*/
|
|
858
|
+
private onDocumentVisible;
|
|
859
|
+
/** Olvida la sesión abierta sin enviar nada (ver onDocumentVisible). */
|
|
860
|
+
private discardSession;
|
|
861
|
+
/**
|
|
862
|
+
* Geolocalización por IP (país/ciudad para analytics). La caché persistente es local y se
|
|
863
|
+
* aplica siempre que `geolocation` no esté desactivado. El lookup a terceros (ipapi.co →
|
|
864
|
+
* ipwho.is → ipinfo.io, fallback con timeout) solo se hace si el dato se va a ENVIAR:
|
|
865
|
+
* analytics configurado + tracking activo + caché ausente o caducada. Una vez por instancia.
|
|
866
|
+
*/
|
|
867
|
+
private resolveGeo;
|
|
817
868
|
private analyticsIdentity;
|
|
818
869
|
/** Flush automático al ocultar/cerrar la página (no perder el lote pendiente). */
|
|
819
870
|
private setupAnalyticsFlush;
|
|
871
|
+
private startAnalyticsFlushTimer;
|
|
820
872
|
/** Enable auto-launch functionality with configured triggers */
|
|
821
873
|
autoLaunch(): void;
|
|
822
874
|
/** Inicia los triggers configurados */
|
|
@@ -896,11 +948,18 @@ declare class DeepdotsPopups {
|
|
|
896
948
|
private mapPopupTriggerType;
|
|
897
949
|
private markSurveyProgress;
|
|
898
950
|
/**
|
|
899
|
-
*
|
|
900
|
-
*
|
|
951
|
+
* Fusiona el estado de redisplay del storage con el de memoria: por cada popup/survey gana
|
|
952
|
+
* la entrada MÁS RECIENTE. Fusionar y no sustituir es lo que hace convivir a varias
|
|
953
|
+
* pestañas sobre el mismo `localStorage`: se llama en el `init()`, antes de cada decisión
|
|
954
|
+
* de mostrar y antes de cada escritura. `answeredSurveys` se reconstruye desde las
|
|
955
|
+
* entradas COMPLETED: es exactamente lo que persiste `markSurveyAnswered`.
|
|
901
956
|
*/
|
|
902
957
|
private loadPopupState;
|
|
903
|
-
/**
|
|
958
|
+
/**
|
|
959
|
+
* Vuelca el estado de redisplay al storage. Sin storage (o bloqueado) degrada a memoria.
|
|
960
|
+
* Fusiona antes de escribir: escribir solo la foto en memoria borraba lo que otra pestaña
|
|
961
|
+
* hubiese guardado desde nuestro `init()`.
|
|
962
|
+
*/
|
|
904
963
|
private persistPopupState;
|
|
905
964
|
private isPopupDefinition;
|
|
906
965
|
private isPopupTrigger;
|
package/dist/index.d.ts
CHANGED
|
@@ -95,7 +95,8 @@ interface AnalyticsEnvelope {
|
|
|
95
95
|
interface AnalyticsFlushMeta {
|
|
96
96
|
/**
|
|
97
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 (
|
|
98
|
+
* un transporte que sobreviva al unload (`fetch` con `keepalive`) y no puede esperar
|
|
99
|
+
* respuestas.
|
|
99
100
|
*/
|
|
100
101
|
final?: boolean;
|
|
101
102
|
/**
|
|
@@ -104,6 +105,12 @@ interface AnalyticsFlushMeta {
|
|
|
104
105
|
* el `sessionId`, para que el lote siguiente abra un registro nuevo.
|
|
105
106
|
*/
|
|
106
107
|
sessionEnd?: boolean;
|
|
108
|
+
/**
|
|
109
|
+
* `true` para olvidar la sesión SIN enviar nada (el payload llega vacío): el backend ya la
|
|
110
|
+
* cerró por inactividad. El sink descarta su `sessionId` para que el lote siguiente abra un
|
|
111
|
+
* registro nuevo, igual que tras `sessionEnd`, pero sin POST.
|
|
112
|
+
*/
|
|
113
|
+
resetSession?: boolean;
|
|
107
114
|
}
|
|
108
115
|
/**
|
|
109
116
|
* Envío del lote. Si devuelve una promesa que **rechaza**, el manager re-encola los
|
|
@@ -174,9 +181,11 @@ interface FeedbackSinkOptions {
|
|
|
174
181
|
/** fetch inyectable (tests / RN). */
|
|
175
182
|
fetchImpl?: typeof fetch;
|
|
176
183
|
/**
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
184
|
+
* @deprecated Se ignora. El flush final salía por `sendBeacon`, que va SIEMPRE con
|
|
185
|
+
* credenciales; contra la API (`Access-Control-Allow-Origin: *` + `Allow-Credentials:
|
|
186
|
+
* true`) el preflight fallaba y el lote de cierre, el único con `completed:true`, no
|
|
187
|
+
* llegaba nunca. Ahora sale por `fetch` con `keepalive`. Se mantiene en el tipo para no
|
|
188
|
+
* romper a quien lo pase.
|
|
180
189
|
*/
|
|
181
190
|
sendBeaconImpl?: (url: string, body: Blob | string) => boolean;
|
|
182
191
|
/** Callback invocado cuando el backend devuelve un nuevo sessionId (primer POST). */
|
|
@@ -194,8 +203,9 @@ interface FeedbackSinkOptions {
|
|
|
194
203
|
* Garantías de entrega:
|
|
195
204
|
* - mientras no se conozca el `sessionId`, los lotes se **serializan** (esperan la primera
|
|
196
205
|
* respuesta): dos POSTs a la vez sin `sessionId` crearían dos registros y partirían los datos;
|
|
197
|
-
* - `keepalive` para que el navegador no cancele el POST al navegar fuera
|
|
198
|
-
* en el flush final (
|
|
206
|
+
* - `keepalive` para que el navegador no cancele el POST al navegar fuera ni al cerrar la
|
|
207
|
+
* página, también en el flush final (sin `sendBeacon`: ver `sendBeaconImpl`);
|
|
208
|
+
* - sin credenciales, que es lo único que pasa el CORS de la API (`Allow-Origin: *`);
|
|
199
209
|
* - la promesa **rechaza** en fallo transitorio (red, 5xx, 408, 429) para que el
|
|
200
210
|
* `AnalyticsManager` re-encole el lote; un 4xx se loguea y se descarta.
|
|
201
211
|
*/
|
|
@@ -250,6 +260,13 @@ interface DeepdotsInitParams {
|
|
|
250
260
|
* to the configured integration; if missing, it stays in dry-run mode (console.log only).
|
|
251
261
|
*/
|
|
252
262
|
analytics?: AnalyticsKeys;
|
|
263
|
+
/**
|
|
264
|
+
* IP geolocation (country/city) added to analytics. Default `true`. The lookup calls
|
|
265
|
+
* third-party services (ipapi.co, then ipwho.is, then ipinfo.io as fallbacks, 3 s timeout
|
|
266
|
+
* each) and only runs when `analytics` is configured, tracking is enabled and the 30-day
|
|
267
|
+
* cache is missing or expired. Set `false` to never call them nor attach country/city.
|
|
268
|
+
*/
|
|
269
|
+
geolocation?: boolean;
|
|
253
270
|
/**
|
|
254
271
|
* Internal user attributes known only by the host (language, age, plan, ...), sent
|
|
255
272
|
* to the backend Contact for segmentation/targeting. Requires `userId`. Equivalent to calling
|
|
@@ -326,8 +343,10 @@ type EventListener = (event: DeepdotsEvent) => void;
|
|
|
326
343
|
* - `user_change`: `setUserId()` o un `init()` con otro `userId` (login/logout del host).
|
|
327
344
|
* - `tracking_disabled`: `setTrackingEnabled(false)` (consentimiento revocado).
|
|
328
345
|
* - `manual`: `endSession()` llamado por el host.
|
|
346
|
+
* - `idle_timeout`: la pestaña vuelve a verse tras más de 30 min oculta (web). La sesión
|
|
347
|
+
* anterior se cierra y se abre otra, como hace GA con su timeout de sesión.
|
|
329
348
|
*/
|
|
330
|
-
type SessionEndReason = 'page_hide' | 'background' | 'user_change' | 'tracking_disabled' | 'manual';
|
|
349
|
+
type SessionEndReason = 'page_hide' | 'background' | 'user_change' | 'tracking_disabled' | 'manual' | 'idle_timeout';
|
|
331
350
|
/** Trigger type used by remote popup definitions */
|
|
332
351
|
type PopupTriggerType = 'time_on_page' | 'scroll' | 'exit' | 'click' | 'event';
|
|
333
352
|
type PopupTriggerConditionStatus = 'SHOWED' | 'PARTIAL' | 'COMPLETED';
|
|
@@ -700,11 +719,21 @@ declare class DeepdotsPopups {
|
|
|
700
719
|
* nueva al volver a foreground o al conceder el consentimiento más tarde.
|
|
701
720
|
*/
|
|
702
721
|
private sessionOpen;
|
|
722
|
+
/** Último `user_engagement` emitido (ms epoch): marca el latido. */
|
|
723
|
+
private lastEngagementAt;
|
|
724
|
+
/** Cuándo se ocultó la pestaña por última vez (ms epoch); null si está visible. */
|
|
725
|
+
private hiddenAt;
|
|
703
726
|
/**
|
|
704
727
|
* Idioma resuelto en init() (explícito > navigator.language > Intl). Única fuente de
|
|
705
728
|
* verdad para el context de analytics Y para la segmentación por idioma de los popups.
|
|
706
729
|
*/
|
|
707
730
|
private language;
|
|
731
|
+
/** `geolocation` del init: si es false no se usa ni la caché ni el lookup. */
|
|
732
|
+
private geoEnabled;
|
|
733
|
+
/** Solo se consulta a terceros si el país/ciudad se va a enviar (analytics configurado). */
|
|
734
|
+
private geoWanted;
|
|
735
|
+
/** Evita más de un lookup por instancia (el consentimiento puede ir y venir). */
|
|
736
|
+
private geoLookupStarted;
|
|
708
737
|
/** Initialize the SDK with configuration */
|
|
709
738
|
init(config: DeepdotsInitParams): void;
|
|
710
739
|
/** User id actual (generado por el SDK o provisto por el cliente). Null si tracking off. */
|
|
@@ -801,12 +830,14 @@ declare class DeepdotsPopups {
|
|
|
801
830
|
* se llama en init(), al volver a foreground y al conceder el consentimiento.
|
|
802
831
|
*/
|
|
803
832
|
private openSession;
|
|
833
|
+
/** Web: si la pestaña se ve. Sin `document` (RN) manda AppState vía onForeground/onBackground. */
|
|
834
|
+
private isDocumentVisible;
|
|
804
835
|
/** Payload que se ENVIARÍA al endpoint de analytics (no envía ni vacía el buffer). */
|
|
805
836
|
previewAnalytics(): AnalyticsEnvelope;
|
|
806
837
|
/**
|
|
807
838
|
* Envía el lote acumulado de analytics y vacía el buffer.
|
|
808
|
-
* `final: true` (cierre de página/app)
|
|
809
|
-
*
|
|
839
|
+
* `final: true` (cierre de página/app): el lote no espera al primer POST en vuelo, porque
|
|
840
|
+
* el documento se muere; un lote que falle por red o 5xx se re-encola para el siguiente flush.
|
|
810
841
|
*/
|
|
811
842
|
flushAnalytics(options?: {
|
|
812
843
|
final?: boolean;
|
|
@@ -814,9 +845,30 @@ declare class DeepdotsPopups {
|
|
|
814
845
|
}): void;
|
|
815
846
|
/** Emite un evento `user_engagement` con el tiempo activo acumulado (#8). */
|
|
816
847
|
private flushEngagement;
|
|
848
|
+
/** Tick del flush periódico: latido de engagement si toca, y envío de lo acumulado. */
|
|
849
|
+
private onAnalyticsFlushTick;
|
|
850
|
+
/**
|
|
851
|
+
* La pestaña vuelve a verse. Tras más de ANALYTICS_SESSION_TIMEOUT_MS oculta, la sesión
|
|
852
|
+
* anterior termina y empieza otra: seguir con el mismo sessionId mezclaba dos visitas y,
|
|
853
|
+
* si el backend ya la había cerrado por inactividad, la partía en dos feedbacks.
|
|
854
|
+
* - Oculta menos de ANALYTICS_SESSION_DISCARD_MS: el backend aún la tiene abierta → se
|
|
855
|
+
* cierra con normalidad (page_view de la pantalla, session_end `idle_timeout`, completed).
|
|
856
|
+
* - Más: ya la cerró el backend → se descarta sin enviar nada.
|
|
857
|
+
*/
|
|
858
|
+
private onDocumentVisible;
|
|
859
|
+
/** Olvida la sesión abierta sin enviar nada (ver onDocumentVisible). */
|
|
860
|
+
private discardSession;
|
|
861
|
+
/**
|
|
862
|
+
* Geolocalización por IP (país/ciudad para analytics). La caché persistente es local y se
|
|
863
|
+
* aplica siempre que `geolocation` no esté desactivado. El lookup a terceros (ipapi.co →
|
|
864
|
+
* ipwho.is → ipinfo.io, fallback con timeout) solo se hace si el dato se va a ENVIAR:
|
|
865
|
+
* analytics configurado + tracking activo + caché ausente o caducada. Una vez por instancia.
|
|
866
|
+
*/
|
|
867
|
+
private resolveGeo;
|
|
817
868
|
private analyticsIdentity;
|
|
818
869
|
/** Flush automático al ocultar/cerrar la página (no perder el lote pendiente). */
|
|
819
870
|
private setupAnalyticsFlush;
|
|
871
|
+
private startAnalyticsFlushTimer;
|
|
820
872
|
/** Enable auto-launch functionality with configured triggers */
|
|
821
873
|
autoLaunch(): void;
|
|
822
874
|
/** Inicia los triggers configurados */
|
|
@@ -896,11 +948,18 @@ declare class DeepdotsPopups {
|
|
|
896
948
|
private mapPopupTriggerType;
|
|
897
949
|
private markSurveyProgress;
|
|
898
950
|
/**
|
|
899
|
-
*
|
|
900
|
-
*
|
|
951
|
+
* Fusiona el estado de redisplay del storage con el de memoria: por cada popup/survey gana
|
|
952
|
+
* la entrada MÁS RECIENTE. Fusionar y no sustituir es lo que hace convivir a varias
|
|
953
|
+
* pestañas sobre el mismo `localStorage`: se llama en el `init()`, antes de cada decisión
|
|
954
|
+
* de mostrar y antes de cada escritura. `answeredSurveys` se reconstruye desde las
|
|
955
|
+
* entradas COMPLETED: es exactamente lo que persiste `markSurveyAnswered`.
|
|
901
956
|
*/
|
|
902
957
|
private loadPopupState;
|
|
903
|
-
/**
|
|
958
|
+
/**
|
|
959
|
+
* Vuelca el estado de redisplay al storage. Sin storage (o bloqueado) degrada a memoria.
|
|
960
|
+
* Fusiona antes de escribir: escribir solo la foto en memoria borraba lo que otra pestaña
|
|
961
|
+
* hubiese guardado desde nuestro `init()`.
|
|
962
|
+
*/
|
|
904
963
|
private persistPopupState;
|
|
905
964
|
private isPopupDefinition;
|
|
906
965
|
private isPopupTrigger;
|