@magicfeedback/popup-sdk 1.12.0 → 1.14.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.
@@ -595,7 +595,20 @@ declare class DeepdotsPopups {
595
595
  final?: boolean;
596
596
  sessionEnd?: boolean;
597
597
  }): void;
598
- /** Emite un evento `user_engagement` con el tiempo activo acumulado (#8). */
598
+ /**
599
+ * Emite un evento `user_engagement` con el tiempo activo acumulado (#8) y la pantalla en
600
+ * curso: `screen` y `path` (los mismos que llevará su `page_view`) y `screen_seconds` (lo
601
+ * que lleva en ella, medido como el `duration_seconds` del `page_view`).
602
+ *
603
+ * El `page_view` sale al SALIR de la pantalla; si el cierre no llega nunca (pestaña dormida
604
+ * y descartada al volver, pestaña o app matada en segundo plano), la última pantalla de la
605
+ * sesión se perdía y una visita de una sola pantalla se quedaba sin ninguna. Con la pantalla
606
+ * en el latido y en el engagement de ocultar la pestaña, el backend la reconstruye.
607
+ *
608
+ * En los cierres (`closeSession`, `suspendSession`) el observador ya emitió el `page_view`
609
+ * y no tiene pantalla, así que ese engagement va sin `screen`: nunca se cuenta dos veces.
610
+ * Tampoco se emite un `page_view` aquí, por lo mismo.
611
+ */
599
612
  private flushEngagement;
600
613
  /** Tick del flush periódico: latido de engagement si toca, y envío de lo acumulado. */
601
614
  private onAnalyticsFlushTick;
@@ -595,7 +595,20 @@ declare class DeepdotsPopups {
595
595
  final?: boolean;
596
596
  sessionEnd?: boolean;
597
597
  }): void;
598
- /** Emite un evento `user_engagement` con el tiempo activo acumulado (#8). */
598
+ /**
599
+ * Emite un evento `user_engagement` con el tiempo activo acumulado (#8) y la pantalla en
600
+ * curso: `screen` y `path` (los mismos que llevará su `page_view`) y `screen_seconds` (lo
601
+ * que lleva en ella, medido como el `duration_seconds` del `page_view`).
602
+ *
603
+ * El `page_view` sale al SALIR de la pantalla; si el cierre no llega nunca (pestaña dormida
604
+ * y descartada al volver, pestaña o app matada en segundo plano), la última pantalla de la
605
+ * sesión se perdía y una visita de una sola pantalla se quedaba sin ninguna. Con la pantalla
606
+ * en el latido y en el engagement de ocultar la pestaña, el backend la reconstruye.
607
+ *
608
+ * En los cierres (`closeSession`, `suspendSession`) el observador ya emitió el `page_view`
609
+ * y no tiene pantalla, así que ese engagement va sin `screen`: nunca se cuenta dos veces.
610
+ * Tampoco se emite un `page_view` aquí, por lo mismo.
611
+ */
599
612
  private flushEngagement;
600
613
  /** Tick del flush periódico: latido de engagement si toca, y envío de lo acumulado. */
601
614
  private onAnalyticsFlushTick;
@@ -552,7 +552,7 @@ var init_style = __esm({
552
552
  style_default = `/**
553
553
  * NO EDITAR A MANO \u2014 generado por scripts/vendor-survey-css.mjs
554
554
  *
555
- * Copia de @magicfeedback/native@2.2.31 \u2192 dist/styles/magicfeedback-default.css
555
+ * Copia de @magicfeedback/native@2.2.33 \u2192 dist/styles/magicfeedback-default.css
556
556
  * (la hoja can\xF3nica del paquete, la que apunta su campo "style"), con estos cambios locales:
557
557
  *
558
558
  * 1. Sin el @import de Google Fonts (Nunito): no queremos una petici\xF3n externa desde la
@@ -3781,7 +3781,7 @@ function trimmedOrNull(value) {
3781
3781
  }
3782
3782
  function buildSurveyHtml(opts) {
3783
3783
  const env = opts.env === "development" ? "dev" : "prod";
3784
- const version = opts.version ?? "2.2.31";
3784
+ const version = opts.version ?? "2.2.33";
3785
3785
  const cdn = `https://cdn.jsdelivr.net/npm/@magicfeedback/native@${version}/dist/magicfeedback-sdk.browser.js`;
3786
3786
  const sid = jsonForScript(opts.surveyId);
3787
3787
  const pid = jsonForScript(opts.productId);
@@ -4979,6 +4979,23 @@ var NavigationObserver = class {
4979
4979
  if (!this.installed || this.currentScreen != null || typeof window === "undefined") return;
4980
4980
  this.begin(window.location.href);
4981
4981
  }
4982
+ /**
4983
+ * La pantalla en curso, sin cerrarla ni emitir nada; null si no hay (antes de `begin`, tras
4984
+ * `stop`/`discard`). Para que el `user_engagement` lleve la pantalla: si el cierre de la
4985
+ * sesión no llega nunca (pestaña dormida y descartada, app matada), la última pantalla no
4986
+ * tiene `page_view` y solo queda esto.
4987
+ */
4988
+ current() {
4989
+ if (this.currentScreen == null) return null;
4990
+ return {
4991
+ screen: this.currentScreen,
4992
+ path: this.currentPath ?? this.currentScreen,
4993
+ seconds: this.secondsSinceEntry(this.now())
4994
+ };
4995
+ }
4996
+ secondsSinceEntry(at) {
4997
+ return Math.max(0, Math.round((at - this.entryAt) / 1e3));
4998
+ }
4982
4999
  closeCurrent() {
4983
5000
  if (this.currentScreen == null) return;
4984
5001
  const exit = this.now();
@@ -4987,7 +5004,7 @@ var NavigationObserver = class {
4987
5004
  path: this.currentPath ?? this.currentScreen,
4988
5005
  entry: this.entryAt,
4989
5006
  exit,
4990
- durationSeconds: Math.max(0, Math.round((exit - this.entryAt) / 1e3))
5007
+ durationSeconds: this.secondsSinceEntry(exit)
4991
5008
  };
4992
5009
  this.listeners.forEach((l) => {
4993
5010
  try {
@@ -6008,12 +6025,29 @@ var DeepdotsPopups = class {
6008
6025
  if (!this.tracking?.isTrackingEnabled()) return;
6009
6026
  this.analytics?.flush(this.analyticsIdentity(), options);
6010
6027
  }
6011
- /** Emite un evento `user_engagement` con el tiempo activo acumulado (#8). */
6028
+ /**
6029
+ * Emite un evento `user_engagement` con el tiempo activo acumulado (#8) y la pantalla en
6030
+ * curso: `screen` y `path` (los mismos que llevará su `page_view`) y `screen_seconds` (lo
6031
+ * que lleva en ella, medido como el `duration_seconds` del `page_view`).
6032
+ *
6033
+ * El `page_view` sale al SALIR de la pantalla; si el cierre no llega nunca (pestaña dormida
6034
+ * y descartada al volver, pestaña o app matada en segundo plano), la última pantalla de la
6035
+ * sesión se perdía y una visita de una sola pantalla se quedaba sin ninguna. Con la pantalla
6036
+ * en el latido y en el engagement de ocultar la pestaña, el backend la reconstruye.
6037
+ *
6038
+ * En los cierres (`closeSession`, `suspendSession`) el observador ya emitió el `page_view`
6039
+ * y no tiene pantalla, así que ese engagement va sin `screen`: nunca se cuenta dos veces.
6040
+ * Tampoco se emite un `page_view` aquí, por lo mismo.
6041
+ */
6012
6042
  flushEngagement() {
6013
6043
  if (!this.tracking?.isTrackingEnabled()) return;
6014
6044
  const ms = this.engagement?.consume() ?? 0;
6015
6045
  if (ms > 0) {
6016
- this.track("deepdots_user_engagement", { engagement_time_msec: ms });
6046
+ const current = this.navObserver?.current();
6047
+ this.track("deepdots_user_engagement", {
6048
+ engagement_time_msec: ms,
6049
+ ...current ? { screen: current.screen, path: current.path, screen_seconds: current.seconds } : {}
6050
+ });
6017
6051
  this.lastEngagementAt = Date.now();
6018
6052
  }
6019
6053
  }