@checkflow/sdk 1.0.1 → 1.0.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.
@@ -72,6 +72,7 @@ export declare class AnalyticsTracker {
72
72
  constructor(apiClient: APIClient, options?: Partial<AnalyticsOptions>);
73
73
  startTracking(): Promise<void>;
74
74
  stopTracking(): Promise<void>;
75
+ private saveSessionRecording;
75
76
  private createSession;
76
77
  private updateSessionEnd;
77
78
  private setupEventListeners;
@@ -45,15 +45,13 @@ export declare class APIClient {
45
45
  */
46
46
  uploadScreenshotOnly(screenshotBase64: string, url: string): Promise<APIResponse>;
47
47
  /**
48
- * Save session recording to backend
49
- * Aligns with backend /sdk/recording endpoint
48
+ * Save session recording to analytics backend
49
+ * Recordings are now part of analytics sessions (independent from feedbacks)
50
50
  */
51
51
  saveSessionRecording(recording: {
52
52
  events: any[];
53
53
  sessionId: string;
54
- startUrl: string;
55
- endUrl?: string;
56
- durationSeconds: number;
54
+ durationMs?: number;
57
55
  }): Promise<APIResponse>;
58
56
  /**
59
57
  * Report an error to the backend
package/dist/index.esm.js CHANGED
@@ -236,16 +236,13 @@ class APIClient {
236
236
  });
237
237
  }
238
238
  /**
239
- * Save session recording to backend
240
- * Aligns with backend /sdk/recording endpoint
239
+ * Save session recording to analytics backend
240
+ * Recordings are now part of analytics sessions (independent from feedbacks)
241
241
  */
242
242
  async saveSessionRecording(recording) {
243
- return this.request('POST', '/api/v1/capture/sdk/recording', {
243
+ return this.request('POST', `/api/v1/analytics/sessions/${recording.sessionId}/recording`, {
244
244
  events: recording.events,
245
- session_id: recording.sessionId,
246
- start_url: recording.startUrl,
247
- end_url: recording.endUrl,
248
- duration_seconds: recording.durationSeconds,
245
+ duration_ms: recording.durationMs || 0,
249
246
  });
250
247
  }
251
248
  /**
@@ -2707,6 +2704,10 @@ class SessionRecording {
2707
2704
  start() {
2708
2705
  if (this.isRecording || !this.config.enabled)
2709
2706
  return;
2707
+ console.log(' [SessionRecording] Starting session recording...', {
2708
+ sessionId: this.sessionId,
2709
+ config: this.config
2710
+ });
2710
2711
  this.isRecording = true;
2711
2712
  this.startTime = Date.now();
2712
2713
  this.events = [];
@@ -2715,20 +2716,25 @@ class SessionRecording {
2715
2716
  // Setup event listeners
2716
2717
  if (this.config.recordMouse) {
2717
2718
  this.setupMouseTracking();
2719
+ console.log(' [SessionRecording] Mouse tracking enabled');
2718
2720
  }
2719
2721
  if (this.config.recordScroll) {
2720
2722
  this.setupScrollTracking();
2723
+ console.log(' [SessionRecording] Scroll tracking enabled');
2721
2724
  }
2722
2725
  if (this.config.recordInput) {
2723
2726
  this.setupInputTracking();
2727
+ console.log(' [SessionRecording] Input tracking enabled');
2724
2728
  }
2725
2729
  if (this.config.recordMutations) {
2726
2730
  this.setupMutationObserver();
2731
+ console.log(' [SessionRecording] Mutation observer enabled');
2727
2732
  }
2728
2733
  // Track navigation
2729
2734
  this.setupNavigationTracking();
2730
2735
  // Track resize
2731
2736
  this.setupResizeTracking();
2737
+ console.log(' [SessionRecording] Session recording started successfully');
2732
2738
  // Auto-stop after max duration
2733
2739
  setTimeout(() => {
2734
2740
  if (this.isRecording) {
@@ -2784,13 +2790,29 @@ class SessionRecording {
2784
2790
  * Get recording data for submission
2785
2791
  */
2786
2792
  getRecordingData() {
2787
- if (this.events.length === 0)
2793
+ console.log('🎥 [SessionRecording] getRecordingData called:', {
2794
+ eventCount: this.events.length,
2795
+ sessionId: this.sessionId,
2796
+ duration: this.getDuration(),
2797
+ isRecording: this.isRecording,
2798
+ startTime: this.startTime
2799
+ });
2800
+ if (this.events.length === 0) {
2801
+ console.warn('🎥 [SessionRecording] No events to return');
2788
2802
  return null;
2789
- return {
2803
+ }
2804
+ const data = {
2790
2805
  events: [...this.events],
2791
2806
  sessionId: this.sessionId,
2792
2807
  duration: this.getDuration(),
2793
2808
  };
2809
+ console.log('🎥 [SessionRecording] Returning recording data:', {
2810
+ eventCount: data.events.length,
2811
+ duration: data.duration,
2812
+ firstEventType: data.events[0]?.type,
2813
+ lastEventType: data.events[data.events.length - 1]?.type
2814
+ });
2815
+ return data;
2794
2816
  }
2795
2817
  addEvent(type, data) {
2796
2818
  // Sample rate filtering
@@ -3602,6 +3624,8 @@ class AnalyticsTracker {
3602
3624
  try {
3603
3625
  // Flush any remaining interactions
3604
3626
  await this.flushInteractions();
3627
+ // Save session recording if available
3628
+ await this.saveSessionRecording();
3605
3629
  // Update session with end time
3606
3630
  await this.updateSessionEnd();
3607
3631
  // Remove event listeners
@@ -3622,6 +3646,56 @@ class AnalyticsTracker {
3622
3646
  console.error('Error stopping analytics tracking:', error);
3623
3647
  }
3624
3648
  }
3649
+ async saveSessionRecording() {
3650
+ // Get session recording from global CheckFlow instance if available
3651
+ try {
3652
+ console.log('🎬 [AnalyticsTracker] Starting saveSessionRecording for session:', this.sessionId);
3653
+ const checkflowInstance = window.checkflow;
3654
+ console.log('🎬 [AnalyticsTracker] CheckFlow instance found:', !!checkflowInstance);
3655
+ console.log('🎬 [AnalyticsTracker] SessionRecording instance found:', !!checkflowInstance?.sessionRecording);
3656
+ if (!checkflowInstance || !checkflowInstance.sessionRecording) {
3657
+ console.warn('🎬 [AnalyticsTracker] No session recording available - instance missing');
3658
+ this.log('No session recording available');
3659
+ return;
3660
+ }
3661
+ const recordingData = checkflowInstance.sessionRecording.getRecordingData();
3662
+ console.log('🎬 [AnalyticsTracker] Recording data retrieved:', {
3663
+ hasData: !!recordingData,
3664
+ eventCount: recordingData?.events?.length || 0,
3665
+ duration: recordingData?.duration || 0,
3666
+ sessionId: recordingData?.sessionId
3667
+ });
3668
+ if (!recordingData || recordingData.events.length === 0) {
3669
+ console.warn('🎬 [AnalyticsTracker] No recording events to save - events array empty');
3670
+ this.log('No recording events to save');
3671
+ return;
3672
+ }
3673
+ // Save recording to analytics backend
3674
+ console.log('🎬 [AnalyticsTracker] Saving recording to backend...', {
3675
+ sessionId: this.sessionId,
3676
+ eventCount: recordingData.events.length,
3677
+ durationMs: recordingData.duration * 1000
3678
+ });
3679
+ const result = await this.apiClient.saveSessionRecording({
3680
+ events: recordingData.events,
3681
+ sessionId: this.sessionId,
3682
+ durationMs: recordingData.duration * 1000
3683
+ });
3684
+ console.log('🎬 [AnalyticsTracker] Session recording saved successfully:', result);
3685
+ this.log('Session recording saved:', {
3686
+ eventCount: recordingData.events.length,
3687
+ duration: recordingData.duration
3688
+ });
3689
+ }
3690
+ catch (error) {
3691
+ console.error('🎬 [AnalyticsTracker] Failed to save session recording:', error);
3692
+ console.error('🎬 [AnalyticsTracker] Error details:', {
3693
+ message: error instanceof Error ? error.message : String(error),
3694
+ stack: error instanceof Error ? error.stack : undefined,
3695
+ sessionId: this.sessionId
3696
+ });
3697
+ }
3698
+ }
3625
3699
  // ==================== Private Methods - Session Management ====================
3626
3700
  async createSession() {
3627
3701
  const sessionData = {
@@ -4044,6 +4118,8 @@ class CheckFlow {
4044
4118
  }
4045
4119
  // Store as singleton
4046
4120
  CheckFlow.instance = this;
4121
+ // Expose globally for analytics tracker access
4122
+ window.checkflow = this;
4047
4123
  }
4048
4124
  /**
4049
4125
  * Initialize the SDK