@amplifyup/sdk 0.1.24 → 0.1.25

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 CHANGED
@@ -108,6 +108,16 @@ declare function normalizeRoute(route: string): string;
108
108
  * Must stay aligned with SESSION_GAP_MS in apps/orchestrator/lib/aws-profiles.ts.
109
109
  */
110
110
  declare const SESSION_IDLE_GAP_MS: number;
111
+ /**
112
+ * Time-on-page emit strategy (cumulative visible seconds).
113
+ * Early milestones, then sparse checkpoints — not a fixed heartbeat.
114
+ * Abandoned-but-visible tabs freeze after DWELL_ACTIVITY_IDLE_MS.
115
+ */
116
+ declare const DWELL_MILESTONES_SEC: readonly [15, 30, 60, 120, 300];
117
+ /** After the last milestone, emit at most once per this many seconds. */
118
+ declare const DWELL_CHECKPOINT_SEC: number;
119
+ /** Stop accruing dwell while visible but without user activity. */
120
+ declare const DWELL_ACTIVITY_IDLE_MS: number;
111
121
  interface EventTrackingConfig {
112
122
  eventName: string;
113
123
  eventType: string;
@@ -194,8 +204,10 @@ declare class AmplifyUpSDK {
194
204
  /** Current page path for engagement attribution. */
195
205
  private currentPath;
196
206
  /**
197
- * Automatic page-level Scroll Depth + Time on Page (dwell heartbeat).
198
- * State lives on the instance so SPA route changes can reset milestones.
207
+ * Automatic page-level Scroll Depth + Time on Page.
208
+ * Dwell uses milestones / sparse checkpoints (not a fixed 15s heartbeat),
209
+ * freezes while the tab is visible but the user is idle, and always flushes
210
+ * on hide / unload / SPA route change.
199
211
  */
200
212
  private setupPageEngagement;
201
213
  /** Flush dwell then reset — used on SPA route changes. */
@@ -505,4 +517,4 @@ declare const verifyAWSConnection: () => {
505
517
 
506
518
  declare const _default: AmplifyUpSDK;
507
519
 
508
- export { AmplifyContentMeta, AmplifyUpConfig, AmplifyUpSDK, AmplifyUpTarget, CDPAdapter, ContentSource, EdgeResolveError, EventProperties, EventTrackingConfig$1 as EventTrackingConfig, type FetchContentOptions, type FetchContentResult, IdentifyInput, IdentifyTraits, PageConfig, ProfileFieldsInput, SESSION_IDLE_GAP_MS, buildLayoutProviderUrl, buildPageRenderUrl, cleanupEventTracking, _default as default, fetchContent, fetchEdgeResolve, fetchPageConfig, getDiagnostics, getInstanceId, getOrchestratorUrl, getSDK, getStatus, getTarget, getTrackingId, getUserId, identify, init, mapResolvedToPageConfig, normalizeRoute, page, refreshEventTracking, reset, routeChange, setProfileFields, setupComponentViewTracking, setupEventTracking, testTracking, track, trackClick, trackContentEngagement, trackContentView, trackFormFieldInteraction, trackFormSubmit, verifyAWSConnection };
520
+ export { AmplifyContentMeta, AmplifyUpConfig, AmplifyUpSDK, AmplifyUpTarget, CDPAdapter, ContentSource, DWELL_ACTIVITY_IDLE_MS, DWELL_CHECKPOINT_SEC, DWELL_MILESTONES_SEC, EdgeResolveError, EventProperties, EventTrackingConfig$1 as EventTrackingConfig, type FetchContentOptions, type FetchContentResult, IdentifyInput, IdentifyTraits, PageConfig, ProfileFieldsInput, SESSION_IDLE_GAP_MS, buildLayoutProviderUrl, buildPageRenderUrl, cleanupEventTracking, _default as default, fetchContent, fetchEdgeResolve, fetchPageConfig, getDiagnostics, getInstanceId, getOrchestratorUrl, getSDK, getStatus, getTarget, getTrackingId, getUserId, identify, init, mapResolvedToPageConfig, normalizeRoute, page, refreshEventTracking, reset, routeChange, setProfileFields, setupComponentViewTracking, setupEventTracking, testTracking, track, trackClick, trackContentEngagement, trackContentView, trackFormFieldInteraction, trackFormSubmit, verifyAWSConnection };
package/dist/index.d.ts CHANGED
@@ -108,6 +108,16 @@ declare function normalizeRoute(route: string): string;
108
108
  * Must stay aligned with SESSION_GAP_MS in apps/orchestrator/lib/aws-profiles.ts.
109
109
  */
110
110
  declare const SESSION_IDLE_GAP_MS: number;
111
+ /**
112
+ * Time-on-page emit strategy (cumulative visible seconds).
113
+ * Early milestones, then sparse checkpoints — not a fixed heartbeat.
114
+ * Abandoned-but-visible tabs freeze after DWELL_ACTIVITY_IDLE_MS.
115
+ */
116
+ declare const DWELL_MILESTONES_SEC: readonly [15, 30, 60, 120, 300];
117
+ /** After the last milestone, emit at most once per this many seconds. */
118
+ declare const DWELL_CHECKPOINT_SEC: number;
119
+ /** Stop accruing dwell while visible but without user activity. */
120
+ declare const DWELL_ACTIVITY_IDLE_MS: number;
111
121
  interface EventTrackingConfig {
112
122
  eventName: string;
113
123
  eventType: string;
@@ -194,8 +204,10 @@ declare class AmplifyUpSDK {
194
204
  /** Current page path for engagement attribution. */
195
205
  private currentPath;
196
206
  /**
197
- * Automatic page-level Scroll Depth + Time on Page (dwell heartbeat).
198
- * State lives on the instance so SPA route changes can reset milestones.
207
+ * Automatic page-level Scroll Depth + Time on Page.
208
+ * Dwell uses milestones / sparse checkpoints (not a fixed 15s heartbeat),
209
+ * freezes while the tab is visible but the user is idle, and always flushes
210
+ * on hide / unload / SPA route change.
199
211
  */
200
212
  private setupPageEngagement;
201
213
  /** Flush dwell then reset — used on SPA route changes. */
@@ -505,4 +517,4 @@ declare const verifyAWSConnection: () => {
505
517
 
506
518
  declare const _default: AmplifyUpSDK;
507
519
 
508
- export { AmplifyContentMeta, AmplifyUpConfig, AmplifyUpSDK, AmplifyUpTarget, CDPAdapter, ContentSource, EdgeResolveError, EventProperties, EventTrackingConfig$1 as EventTrackingConfig, type FetchContentOptions, type FetchContentResult, IdentifyInput, IdentifyTraits, PageConfig, ProfileFieldsInput, SESSION_IDLE_GAP_MS, buildLayoutProviderUrl, buildPageRenderUrl, cleanupEventTracking, _default as default, fetchContent, fetchEdgeResolve, fetchPageConfig, getDiagnostics, getInstanceId, getOrchestratorUrl, getSDK, getStatus, getTarget, getTrackingId, getUserId, identify, init, mapResolvedToPageConfig, normalizeRoute, page, refreshEventTracking, reset, routeChange, setProfileFields, setupComponentViewTracking, setupEventTracking, testTracking, track, trackClick, trackContentEngagement, trackContentView, trackFormFieldInteraction, trackFormSubmit, verifyAWSConnection };
520
+ export { AmplifyContentMeta, AmplifyUpConfig, AmplifyUpSDK, AmplifyUpTarget, CDPAdapter, ContentSource, DWELL_ACTIVITY_IDLE_MS, DWELL_CHECKPOINT_SEC, DWELL_MILESTONES_SEC, EdgeResolveError, EventProperties, EventTrackingConfig$1 as EventTrackingConfig, type FetchContentOptions, type FetchContentResult, IdentifyInput, IdentifyTraits, PageConfig, ProfileFieldsInput, SESSION_IDLE_GAP_MS, buildLayoutProviderUrl, buildPageRenderUrl, cleanupEventTracking, _default as default, fetchContent, fetchEdgeResolve, fetchPageConfig, getDiagnostics, getInstanceId, getOrchestratorUrl, getSDK, getStatus, getTarget, getTrackingId, getUserId, identify, init, mapResolvedToPageConfig, normalizeRoute, page, refreshEventTracking, reset, routeChange, setProfileFields, setupComponentViewTracking, setupEventTracking, testTracking, track, trackClick, trackContentEngagement, trackContentView, trackFormFieldInteraction, trackFormSubmit, verifyAWSConnection };
package/dist/index.js CHANGED
@@ -510,6 +510,10 @@ async function fetchContent(options) {
510
510
 
511
511
  // src/index.ts
512
512
  var SESSION_IDLE_GAP_MS = 30 * 60 * 1e3;
513
+ var DWELL_MILESTONES_SEC = [15, 30, 60, 120, 300];
514
+ var DWELL_CHECKPOINT_SEC = 15 * 60;
515
+ var DWELL_ACTIVITY_IDLE_MS = 2 * 60 * 1e3;
516
+ var DWELL_POLL_MS = 5e3;
513
517
  function readPreviewQueryOverrides() {
514
518
  if (typeof window === "undefined") return {};
515
519
  const params = new URLSearchParams(window.location.search);
@@ -580,7 +584,10 @@ var AmplifyUpSDK = class {
580
584
  visibleSince: null,
581
585
  lastDwellSecondsSent: 0,
582
586
  /** When the tab last became hidden — used for idle-resume re-page. */
583
- hiddenAt: null
587
+ hiddenAt: null,
588
+ /** Last user interaction — freezes dwell when stale while visible. */
589
+ lastActivityAt: 0,
590
+ activityIdle: false
584
591
  };
585
592
  this.adapter = adapter || new AWSAdapter();
586
593
  if (typeof window !== "undefined") {
@@ -803,8 +810,10 @@ var AmplifyUpSDK = class {
803
810
  return window.location.pathname || "/";
804
811
  }
805
812
  /**
806
- * Automatic page-level Scroll Depth + Time on Page (dwell heartbeat).
807
- * State lives on the instance so SPA route changes can reset milestones.
813
+ * Automatic page-level Scroll Depth + Time on Page.
814
+ * Dwell uses milestones / sparse checkpoints (not a fixed 15s heartbeat),
815
+ * freezes while the tab is visible but the user is idle, and always flushes
816
+ * on hide / unload / SPA route change.
808
817
  */
809
818
  setupPageEngagement() {
810
819
  if (typeof window === "undefined" || typeof document === "undefined") return;
@@ -817,6 +826,8 @@ var AmplifyUpSDK = class {
817
826
  state.visibleSince = document.visibilityState === "visible" ? Date.now() : null;
818
827
  state.lastDwellSecondsSent = 0;
819
828
  state.hiddenAt = document.visibilityState === "hidden" ? Date.now() : null;
829
+ state.lastActivityAt = Date.now();
830
+ state.activityIdle = false;
820
831
  let scrollRaf = null;
821
832
  const path = () => this.currentPath();
822
833
  const measureScrollPercent = () => {
@@ -848,6 +859,7 @@ var AmplifyUpSDK = class {
848
859
  }
849
860
  };
850
861
  const onScroll = () => {
862
+ noteActivity();
851
863
  if (scrollRaf != null) return;
852
864
  scrollRaf = window.requestAnimationFrame(() => {
853
865
  scrollRaf = null;
@@ -859,19 +871,58 @@ var AmplifyUpSDK = class {
859
871
  state.visibleMs += Date.now() - state.visibleSince;
860
872
  state.visibleSince = Date.now();
861
873
  };
862
- const emitDwell = (_force = false) => {
863
- if (this.isPreviewMode()) return;
874
+ const freezeActivityIdle = () => {
875
+ if (state.activityIdle) return;
864
876
  accumulateVisible();
877
+ state.visibleSince = null;
878
+ state.activityIdle = true;
879
+ };
880
+ const noteActivity = () => {
881
+ state.lastActivityAt = Date.now();
882
+ if (state.activityIdle) {
883
+ state.activityIdle = false;
884
+ if (document.visibilityState === "visible" && state.visibleSince == null) {
885
+ state.visibleSince = Date.now();
886
+ }
887
+ }
888
+ };
889
+ const nextEmitTarget = (lastSent) => {
890
+ for (const m of DWELL_MILESTONES_SEC) {
891
+ if (m > lastSent) return { seconds: m, reason: "milestone" };
892
+ }
893
+ const nextCheckpoint = Math.floor(lastSent / DWELL_CHECKPOINT_SEC) * DWELL_CHECKPOINT_SEC + DWELL_CHECKPOINT_SEC;
894
+ const target = nextCheckpoint > lastSent ? nextCheckpoint : lastSent + DWELL_CHECKPOINT_SEC;
895
+ return { seconds: target, reason: "checkpoint" };
896
+ };
897
+ const emitDwell = (reason, force = false) => {
898
+ if (this.isPreviewMode()) return;
899
+ if (!state.activityIdle) {
900
+ accumulateVisible();
901
+ }
865
902
  const seconds = Math.floor(state.visibleMs / 1e3);
866
903
  if (seconds <= 0) return;
867
904
  if (seconds <= state.lastDwellSecondsSent) return;
905
+ if (!force) {
906
+ const target = nextEmitTarget(state.lastDwellSecondsSent);
907
+ if (!target || seconds < target.seconds) return;
908
+ reason = target.reason;
909
+ }
868
910
  state.lastDwellSecondsSent = seconds;
869
911
  this.track("Time on Page", {
870
912
  seconds,
871
- path: this.lastTrackedPath || path()
913
+ path: this.lastTrackedPath || path(),
914
+ reason
872
915
  });
873
916
  };
874
- this._emitPageDwell = emitDwell;
917
+ const evaluateDwell = () => {
918
+ if (document.visibilityState !== "visible") return;
919
+ if (Date.now() - state.lastActivityAt >= DWELL_ACTIVITY_IDLE_MS) {
920
+ freezeActivityIdle();
921
+ return;
922
+ }
923
+ emitDwell("milestone", false);
924
+ };
925
+ this._emitPageDwell = (force) => emitDwell("route", force !== false);
875
926
  const onVisibility = () => {
876
927
  if (document.visibilityState === "visible") {
877
928
  const idleMs = state.hiddenAt != null ? Date.now() - state.hiddenAt : 0;
@@ -889,35 +940,51 @@ var AmplifyUpSDK = class {
889
940
  );
890
941
  }
891
942
  }
943
+ noteActivity();
892
944
  state.visibleSince = Date.now();
945
+ state.activityIdle = false;
893
946
  } else {
894
- emitDwell(true);
947
+ emitDwell("hidden", true);
895
948
  state.hiddenAt = Date.now();
896
949
  state.visibleSince = null;
950
+ state.activityIdle = false;
897
951
  }
898
952
  };
899
953
  const onPageHide = () => {
900
- emitDwell(true);
954
+ emitDwell("unload", true);
901
955
  if (state.hiddenAt == null) {
902
956
  state.hiddenAt = Date.now();
903
957
  }
904
958
  state.visibleSince = null;
905
959
  };
960
+ const activityEvents = [
961
+ "pointerdown",
962
+ "keydown",
963
+ "scroll",
964
+ "touchstart"
965
+ ];
966
+ const onActivity = () => noteActivity();
906
967
  window.addEventListener("scroll", onScroll, { passive: true });
907
968
  document.addEventListener("visibilitychange", onVisibility);
908
969
  window.addEventListener("pagehide", onPageHide);
970
+ for (const evt of activityEvents) {
971
+ if (evt === "scroll") continue;
972
+ window.addEventListener(evt, onActivity, { passive: true });
973
+ }
909
974
  checkScroll();
910
975
  const heartbeat = setInterval(() => {
911
- if (document.visibilityState === "visible") {
912
- emitDwell(false);
913
- }
914
- }, 15e3);
976
+ evaluateDwell();
977
+ }, DWELL_POLL_MS);
915
978
  this.trackingIntervals.push(heartbeat);
916
979
  const previousCleanup = this.trackingCleanup;
917
980
  this.trackingCleanup = () => {
918
981
  window.removeEventListener("scroll", onScroll);
919
982
  document.removeEventListener("visibilitychange", onVisibility);
920
983
  window.removeEventListener("pagehide", onPageHide);
984
+ for (const evt of activityEvents) {
985
+ if (evt === "scroll") continue;
986
+ window.removeEventListener(evt, onActivity);
987
+ }
921
988
  if (scrollRaf != null) {
922
989
  window.cancelAnimationFrame(scrollRaf);
923
990
  scrollRaf = null;
@@ -943,6 +1010,8 @@ var AmplifyUpSDK = class {
943
1010
  state.visibleMs = 0;
944
1011
  state.lastDwellSecondsSent = 0;
945
1012
  state.hiddenAt = null;
1013
+ state.lastActivityAt = Date.now();
1014
+ state.activityIdle = false;
946
1015
  state.visibleSince = typeof document !== "undefined" && document.visibilityState === "visible" ? Date.now() : null;
947
1016
  this.componentViewSeen.clear();
948
1017
  }
@@ -2693,6 +2762,9 @@ var verifyAWSConnection = () => {
2693
2762
  var index_default = getSDK();
2694
2763
 
2695
2764
  exports.AmplifyUpSDK = AmplifyUpSDK;
2765
+ exports.DWELL_ACTIVITY_IDLE_MS = DWELL_ACTIVITY_IDLE_MS;
2766
+ exports.DWELL_CHECKPOINT_SEC = DWELL_CHECKPOINT_SEC;
2767
+ exports.DWELL_MILESTONES_SEC = DWELL_MILESTONES_SEC;
2696
2768
  exports.EdgeResolveError = EdgeResolveError;
2697
2769
  exports.SESSION_IDLE_GAP_MS = SESSION_IDLE_GAP_MS;
2698
2770
  exports.buildLayoutProviderUrl = buildLayoutProviderUrl;