cryptique-sdk 1.1.8 → 1.1.9

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/lib/cjs/index.js CHANGED
@@ -6063,6 +6063,30 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
6063
6063
  }
6064
6064
  }
6065
6065
 
6066
+ // Build auto_event_data for custom events (heatmap/position context when possible)
6067
+ let customAutoEventData = {};
6068
+ if (typeof window !== 'undefined' && window.document) {
6069
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
6070
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
6071
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
6072
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
6073
+ customAutoEventData = {
6074
+ scroll_x: scrollX,
6075
+ scroll_y: scrollY,
6076
+ document_height: docHeight,
6077
+ document_width: docWidth
6078
+ };
6079
+ const srcEvent = options.sourceEvent;
6080
+ if (srcEvent && typeof srcEvent === 'object' && (srcEvent.pageX != null || srcEvent.clientX != null)) {
6081
+ customAutoEventData.page_x = srcEvent.pageX != null ? srcEvent.pageX : (srcEvent.clientX + (window.scrollX || window.pageXOffset || 0));
6082
+ customAutoEventData.page_y = srcEvent.pageY != null ? srcEvent.pageY : (srcEvent.clientY + (window.scrollY || window.pageYOffset || 0));
6083
+ customAutoEventData.click_coordinates = {
6084
+ x: srcEvent.clientX != null ? srcEvent.clientX : srcEvent.pageX - (window.scrollX || window.pageXOffset || 0),
6085
+ y: srcEvent.clientY != null ? srcEvent.clientY : srcEvent.pageY - (window.scrollY || window.pageYOffset || 0)
6086
+ };
6087
+ }
6088
+ }
6089
+
6066
6090
  // Prepare event data
6067
6091
  const eventData = {
6068
6092
  event_type: 'custom',
@@ -6072,6 +6096,7 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
6072
6096
  user_id: userId,
6073
6097
  // Only include user-provided properties in custom_properties (filtered)
6074
6098
  custom_properties: filteredProperties,
6099
+ auto_event_data: customAutoEventData,
6075
6100
  // Page context and screen/viewport data go in page_data (not custom_properties)
6076
6101
  page_data: {
6077
6102
  current_url: window.location.href,
@@ -6886,7 +6911,18 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
6886
6911
  if (element === lastClickElement && now - lastClickTime < 1000) {
6887
6912
  clickCount++;
6888
6913
  if (clickCount >= 3) {
6914
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
6915
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
6916
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
6917
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
6889
6918
  EventsManager.trackAutoEvent('rage_click', {
6919
+ click_coordinates: { x: event.clientX, y: event.clientY },
6920
+ page_x: event.pageX,
6921
+ page_y: event.pageY,
6922
+ scroll_x: scrollX,
6923
+ scroll_y: scrollY,
6924
+ document_height: docHeight,
6925
+ document_width: docWidth,
6890
6926
  click_count: clickCount,
6891
6927
  time_span: now - lastClickTime,
6892
6928
  element_area: element.offsetWidth * element.offsetHeight,
@@ -7004,11 +7040,17 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
7004
7040
 
7005
7041
  if (scrollDepth > maxScrollDepth) {
7006
7042
  maxScrollDepth = scrollDepth;
7007
-
7043
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
7044
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
7045
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
7008
7046
  EventsManager.trackAutoEvent('page_scroll', {
7009
7047
  scroll_depth: scrollDepth,
7010
7048
  max_scroll_reached: maxScrollDepth,
7011
- scroll_position: window.scrollY
7049
+ scroll_position: window.scrollY,
7050
+ scroll_x: scrollX,
7051
+ scroll_y: window.scrollY,
7052
+ document_height: docHeight,
7053
+ document_width: docWidth
7012
7054
  }).catch(err => {
7013
7055
  console.error('❌ [AutoEvents] Failed to track page_scroll:', err);
7014
7056
  });
@@ -7026,10 +7068,24 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
7026
7068
  document.addEventListener('submit', (event) => {
7027
7069
  const form = event.target;
7028
7070
  if (form.tagName === 'FORM') {
7071
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
7072
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
7073
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
7074
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
7075
+ const rect = form.getBoundingClientRect();
7076
+ const pageX = rect.left + scrollX;
7077
+ const pageY = rect.top + scrollY;
7029
7078
  EventsManager.trackAutoEvent('form_submit', {
7030
7079
  form_id: form.id || null,
7031
7080
  form_action: form.action || null,
7032
- form_method: form.method || 'get'
7081
+ form_method: form.method || 'get',
7082
+ scroll_x: scrollX,
7083
+ scroll_y: scrollY,
7084
+ document_height: docHeight,
7085
+ document_width: docWidth,
7086
+ page_x: pageX,
7087
+ page_y: pageY,
7088
+ click_coordinates: { x: event.clientX != null ? event.clientX : rect.left + rect.width / 2, y: event.clientY != null ? event.clientY : rect.top + rect.height / 2 }
7033
7089
  }, {
7034
7090
  element_tag_name: 'form',
7035
7091
  element_id: form.id || null,
@@ -7038,8 +7094,8 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
7038
7094
  element_type: form.method || 'get', // FIX: Added element_type (form method)
7039
7095
  element_text: form.textContent?.trim().substring(0, 100) || null, // FIX: Added element_text
7040
7096
  element_position: { // FIX: Added element_position
7041
- x: event.clientX || 0,
7042
- y: event.clientY || 0,
7097
+ x: event.clientX || rect.left,
7098
+ y: event.clientY || rect.top,
7043
7099
  width: form.offsetWidth || 0,
7044
7100
  height: form.offsetHeight || 0
7045
7101
  }
@@ -7051,10 +7107,24 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
7051
7107
  document.addEventListener('focus', (event) => {
7052
7108
  const element = event.target;
7053
7109
  if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA' || element.tagName === 'SELECT') {
7110
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
7111
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
7112
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
7113
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
7114
+ const rect = element.getBoundingClientRect();
7115
+ const pageX = rect.left + scrollX;
7116
+ const pageY = rect.top + scrollY;
7054
7117
  EventsManager.trackAutoEvent('form_focus', {
7055
7118
  field_name: element.name || null,
7056
7119
  field_type: element.type || null,
7057
- field_id: element.id || null
7120
+ field_id: element.id || null,
7121
+ scroll_x: scrollX,
7122
+ scroll_y: scrollY,
7123
+ document_height: docHeight,
7124
+ document_width: docWidth,
7125
+ page_x: pageX,
7126
+ page_y: pageY,
7127
+ click_coordinates: { x: event.clientX != null ? event.clientX : rect.left + rect.width / 2, y: event.clientY != null ? event.clientY : rect.top + rect.height / 2 }
7058
7128
  }, {
7059
7129
  element_tag_name: element.tagName.toLowerCase(),
7060
7130
  element_id: element.id || null,
@@ -7063,8 +7133,8 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
7063
7133
  element_type: element.type || null,
7064
7134
  element_text: element.value ? element.value.toString().trim().substring(0, 100) : null, // FIX: Added element_text (value for form fields)
7065
7135
  element_position: { // FIX: Added element_position
7066
- x: event.clientX || 0,
7067
- y: event.clientY || 0,
7136
+ x: event.clientX != null ? event.clientX : rect.left,
7137
+ y: event.clientY != null ? event.clientY : rect.top,
7068
7138
  width: element.offsetWidth || 0,
7069
7139
  height: element.offsetHeight || 0
7070
7140
  }
@@ -7077,23 +7147,54 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
7077
7147
  * Setup media tracking
7078
7148
  */
7079
7149
  setupMediaTracking() {
7150
+ function getPageContext() {
7151
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
7152
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
7153
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
7154
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
7155
+ return { scrollX, scrollY, docHeight, docWidth };
7156
+ }
7080
7157
  ['video', 'audio'].forEach(mediaType => {
7081
7158
  document.addEventListener('play', (event) => {
7082
7159
  if (event.target.tagName.toLowerCase() === mediaType) {
7160
+ const el = event.target;
7161
+ const { scrollX, scrollY, docHeight, docWidth } = getPageContext();
7162
+ const rect = el.getBoundingClientRect();
7163
+ const pageX = rect.left + scrollX;
7164
+ const pageY = rect.top + scrollY;
7083
7165
  EventsManager.trackAutoEvent('media_play', {
7084
7166
  media_type: mediaType,
7085
- media_src: event.target.src || null,
7086
- media_duration: event.target.duration || null
7167
+ media_src: el.src || null,
7168
+ media_duration: el.duration || null,
7169
+ scroll_x: scrollX,
7170
+ scroll_y: scrollY,
7171
+ document_height: docHeight,
7172
+ document_width: docWidth,
7173
+ page_x: pageX,
7174
+ page_y: pageY,
7175
+ click_coordinates: { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 }
7087
7176
  });
7088
7177
  }
7089
7178
  }, true);
7090
7179
 
7091
7180
  document.addEventListener('pause', (event) => {
7092
7181
  if (event.target.tagName.toLowerCase() === mediaType) {
7182
+ const el = event.target;
7183
+ const { scrollX, scrollY, docHeight, docWidth } = getPageContext();
7184
+ const rect = el.getBoundingClientRect();
7185
+ const pageX = rect.left + scrollX;
7186
+ const pageY = rect.top + scrollY;
7093
7187
  EventsManager.trackAutoEvent('media_pause', {
7094
7188
  media_type: mediaType,
7095
- media_current_time: event.target.currentTime || null,
7096
- media_duration: event.target.duration || null
7189
+ media_current_time: el.currentTime || null,
7190
+ media_duration: el.duration || null,
7191
+ scroll_x: scrollX,
7192
+ scroll_y: scrollY,
7193
+ document_height: docHeight,
7194
+ document_width: docWidth,
7195
+ page_x: pageX,
7196
+ page_y: pageY,
7197
+ click_coordinates: { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 }
7097
7198
  });
7098
7199
  }
7099
7200
  }, true);
@@ -7175,11 +7276,33 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
7175
7276
  focus_offset: selection.focusOffset || null
7176
7277
  };
7177
7278
 
7178
- // Get page context
7279
+ // Get page context and selection position for heatmaps
7280
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
7281
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
7282
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
7283
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
7284
+ let pageX = null;
7285
+ let pageY = null;
7286
+ if (range) {
7287
+ try {
7288
+ const selRect = range.getBoundingClientRect();
7289
+ if (selRect.width > 0 || selRect.height > 0) {
7290
+ pageX = selRect.left + scrollX;
7291
+ pageY = selRect.top + scrollY;
7292
+ }
7293
+ } catch (e) { /* getBoundingClientRect can throw in some edge cases */ }
7294
+ }
7179
7295
  const pageData = {
7180
7296
  page_url: window.location.href,
7181
7297
  page_title: document.title,
7182
- page_path: window.location.pathname
7298
+ page_path: window.location.pathname,
7299
+ scroll_x: scrollX,
7300
+ scroll_y: scrollY,
7301
+ document_height: docHeight,
7302
+ document_width: docWidth,
7303
+ page_x: pageX,
7304
+ page_y: pageY,
7305
+ click_coordinates: pageX != null && pageY != null ? { x: pageX - scrollX, y: pageY - scrollY } : null
7183
7306
  };
7184
7307
 
7185
7308
  EventsManager.trackAutoEvent('text_selection', {
package/lib/esm/index.js CHANGED
@@ -6061,6 +6061,30 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
6061
6061
  }
6062
6062
  }
6063
6063
 
6064
+ // Build auto_event_data for custom events (heatmap/position context when possible)
6065
+ let customAutoEventData = {};
6066
+ if (typeof window !== 'undefined' && window.document) {
6067
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
6068
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
6069
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
6070
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
6071
+ customAutoEventData = {
6072
+ scroll_x: scrollX,
6073
+ scroll_y: scrollY,
6074
+ document_height: docHeight,
6075
+ document_width: docWidth
6076
+ };
6077
+ const srcEvent = options.sourceEvent;
6078
+ if (srcEvent && typeof srcEvent === 'object' && (srcEvent.pageX != null || srcEvent.clientX != null)) {
6079
+ customAutoEventData.page_x = srcEvent.pageX != null ? srcEvent.pageX : (srcEvent.clientX + (window.scrollX || window.pageXOffset || 0));
6080
+ customAutoEventData.page_y = srcEvent.pageY != null ? srcEvent.pageY : (srcEvent.clientY + (window.scrollY || window.pageYOffset || 0));
6081
+ customAutoEventData.click_coordinates = {
6082
+ x: srcEvent.clientX != null ? srcEvent.clientX : srcEvent.pageX - (window.scrollX || window.pageXOffset || 0),
6083
+ y: srcEvent.clientY != null ? srcEvent.clientY : srcEvent.pageY - (window.scrollY || window.pageYOffset || 0)
6084
+ };
6085
+ }
6086
+ }
6087
+
6064
6088
  // Prepare event data
6065
6089
  const eventData = {
6066
6090
  event_type: 'custom',
@@ -6070,6 +6094,7 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
6070
6094
  user_id: userId,
6071
6095
  // Only include user-provided properties in custom_properties (filtered)
6072
6096
  custom_properties: filteredProperties,
6097
+ auto_event_data: customAutoEventData,
6073
6098
  // Page context and screen/viewport data go in page_data (not custom_properties)
6074
6099
  page_data: {
6075
6100
  current_url: window.location.href,
@@ -6884,7 +6909,18 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
6884
6909
  if (element === lastClickElement && now - lastClickTime < 1000) {
6885
6910
  clickCount++;
6886
6911
  if (clickCount >= 3) {
6912
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
6913
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
6914
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
6915
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
6887
6916
  EventsManager.trackAutoEvent('rage_click', {
6917
+ click_coordinates: { x: event.clientX, y: event.clientY },
6918
+ page_x: event.pageX,
6919
+ page_y: event.pageY,
6920
+ scroll_x: scrollX,
6921
+ scroll_y: scrollY,
6922
+ document_height: docHeight,
6923
+ document_width: docWidth,
6888
6924
  click_count: clickCount,
6889
6925
  time_span: now - lastClickTime,
6890
6926
  element_area: element.offsetWidth * element.offsetHeight,
@@ -7002,11 +7038,17 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
7002
7038
 
7003
7039
  if (scrollDepth > maxScrollDepth) {
7004
7040
  maxScrollDepth = scrollDepth;
7005
-
7041
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
7042
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
7043
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
7006
7044
  EventsManager.trackAutoEvent('page_scroll', {
7007
7045
  scroll_depth: scrollDepth,
7008
7046
  max_scroll_reached: maxScrollDepth,
7009
- scroll_position: window.scrollY
7047
+ scroll_position: window.scrollY,
7048
+ scroll_x: scrollX,
7049
+ scroll_y: window.scrollY,
7050
+ document_height: docHeight,
7051
+ document_width: docWidth
7010
7052
  }).catch(err => {
7011
7053
  console.error('❌ [AutoEvents] Failed to track page_scroll:', err);
7012
7054
  });
@@ -7024,10 +7066,24 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
7024
7066
  document.addEventListener('submit', (event) => {
7025
7067
  const form = event.target;
7026
7068
  if (form.tagName === 'FORM') {
7069
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
7070
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
7071
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
7072
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
7073
+ const rect = form.getBoundingClientRect();
7074
+ const pageX = rect.left + scrollX;
7075
+ const pageY = rect.top + scrollY;
7027
7076
  EventsManager.trackAutoEvent('form_submit', {
7028
7077
  form_id: form.id || null,
7029
7078
  form_action: form.action || null,
7030
- form_method: form.method || 'get'
7079
+ form_method: form.method || 'get',
7080
+ scroll_x: scrollX,
7081
+ scroll_y: scrollY,
7082
+ document_height: docHeight,
7083
+ document_width: docWidth,
7084
+ page_x: pageX,
7085
+ page_y: pageY,
7086
+ click_coordinates: { x: event.clientX != null ? event.clientX : rect.left + rect.width / 2, y: event.clientY != null ? event.clientY : rect.top + rect.height / 2 }
7031
7087
  }, {
7032
7088
  element_tag_name: 'form',
7033
7089
  element_id: form.id || null,
@@ -7036,8 +7092,8 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
7036
7092
  element_type: form.method || 'get', // FIX: Added element_type (form method)
7037
7093
  element_text: form.textContent?.trim().substring(0, 100) || null, // FIX: Added element_text
7038
7094
  element_position: { // FIX: Added element_position
7039
- x: event.clientX || 0,
7040
- y: event.clientY || 0,
7095
+ x: event.clientX || rect.left,
7096
+ y: event.clientY || rect.top,
7041
7097
  width: form.offsetWidth || 0,
7042
7098
  height: form.offsetHeight || 0
7043
7099
  }
@@ -7049,10 +7105,24 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
7049
7105
  document.addEventListener('focus', (event) => {
7050
7106
  const element = event.target;
7051
7107
  if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA' || element.tagName === 'SELECT') {
7108
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
7109
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
7110
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
7111
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
7112
+ const rect = element.getBoundingClientRect();
7113
+ const pageX = rect.left + scrollX;
7114
+ const pageY = rect.top + scrollY;
7052
7115
  EventsManager.trackAutoEvent('form_focus', {
7053
7116
  field_name: element.name || null,
7054
7117
  field_type: element.type || null,
7055
- field_id: element.id || null
7118
+ field_id: element.id || null,
7119
+ scroll_x: scrollX,
7120
+ scroll_y: scrollY,
7121
+ document_height: docHeight,
7122
+ document_width: docWidth,
7123
+ page_x: pageX,
7124
+ page_y: pageY,
7125
+ click_coordinates: { x: event.clientX != null ? event.clientX : rect.left + rect.width / 2, y: event.clientY != null ? event.clientY : rect.top + rect.height / 2 }
7056
7126
  }, {
7057
7127
  element_tag_name: element.tagName.toLowerCase(),
7058
7128
  element_id: element.id || null,
@@ -7061,8 +7131,8 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
7061
7131
  element_type: element.type || null,
7062
7132
  element_text: element.value ? element.value.toString().trim().substring(0, 100) : null, // FIX: Added element_text (value for form fields)
7063
7133
  element_position: { // FIX: Added element_position
7064
- x: event.clientX || 0,
7065
- y: event.clientY || 0,
7134
+ x: event.clientX != null ? event.clientX : rect.left,
7135
+ y: event.clientY != null ? event.clientY : rect.top,
7066
7136
  width: element.offsetWidth || 0,
7067
7137
  height: element.offsetHeight || 0
7068
7138
  }
@@ -7075,23 +7145,54 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
7075
7145
  * Setup media tracking
7076
7146
  */
7077
7147
  setupMediaTracking() {
7148
+ function getPageContext() {
7149
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
7150
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
7151
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
7152
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
7153
+ return { scrollX, scrollY, docHeight, docWidth };
7154
+ }
7078
7155
  ['video', 'audio'].forEach(mediaType => {
7079
7156
  document.addEventListener('play', (event) => {
7080
7157
  if (event.target.tagName.toLowerCase() === mediaType) {
7158
+ const el = event.target;
7159
+ const { scrollX, scrollY, docHeight, docWidth } = getPageContext();
7160
+ const rect = el.getBoundingClientRect();
7161
+ const pageX = rect.left + scrollX;
7162
+ const pageY = rect.top + scrollY;
7081
7163
  EventsManager.trackAutoEvent('media_play', {
7082
7164
  media_type: mediaType,
7083
- media_src: event.target.src || null,
7084
- media_duration: event.target.duration || null
7165
+ media_src: el.src || null,
7166
+ media_duration: el.duration || null,
7167
+ scroll_x: scrollX,
7168
+ scroll_y: scrollY,
7169
+ document_height: docHeight,
7170
+ document_width: docWidth,
7171
+ page_x: pageX,
7172
+ page_y: pageY,
7173
+ click_coordinates: { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 }
7085
7174
  });
7086
7175
  }
7087
7176
  }, true);
7088
7177
 
7089
7178
  document.addEventListener('pause', (event) => {
7090
7179
  if (event.target.tagName.toLowerCase() === mediaType) {
7180
+ const el = event.target;
7181
+ const { scrollX, scrollY, docHeight, docWidth } = getPageContext();
7182
+ const rect = el.getBoundingClientRect();
7183
+ const pageX = rect.left + scrollX;
7184
+ const pageY = rect.top + scrollY;
7091
7185
  EventsManager.trackAutoEvent('media_pause', {
7092
7186
  media_type: mediaType,
7093
- media_current_time: event.target.currentTime || null,
7094
- media_duration: event.target.duration || null
7187
+ media_current_time: el.currentTime || null,
7188
+ media_duration: el.duration || null,
7189
+ scroll_x: scrollX,
7190
+ scroll_y: scrollY,
7191
+ document_height: docHeight,
7192
+ document_width: docWidth,
7193
+ page_x: pageX,
7194
+ page_y: pageY,
7195
+ click_coordinates: { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 }
7095
7196
  });
7096
7197
  }
7097
7198
  }, true);
@@ -7173,11 +7274,33 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
7173
7274
  focus_offset: selection.focusOffset || null
7174
7275
  };
7175
7276
 
7176
- // Get page context
7277
+ // Get page context and selection position for heatmaps
7278
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
7279
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
7280
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
7281
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
7282
+ let pageX = null;
7283
+ let pageY = null;
7284
+ if (range) {
7285
+ try {
7286
+ const selRect = range.getBoundingClientRect();
7287
+ if (selRect.width > 0 || selRect.height > 0) {
7288
+ pageX = selRect.left + scrollX;
7289
+ pageY = selRect.top + scrollY;
7290
+ }
7291
+ } catch (e) { /* getBoundingClientRect can throw in some edge cases */ }
7292
+ }
7177
7293
  const pageData = {
7178
7294
  page_url: window.location.href,
7179
7295
  page_title: document.title,
7180
- page_path: window.location.pathname
7296
+ page_path: window.location.pathname,
7297
+ scroll_x: scrollX,
7298
+ scroll_y: scrollY,
7299
+ document_height: docHeight,
7300
+ document_width: docWidth,
7301
+ page_x: pageX,
7302
+ page_y: pageY,
7303
+ click_coordinates: pageX != null && pageY != null ? { x: pageX - scrollX, y: pageY - scrollY } : null
7181
7304
  };
7182
7305
 
7183
7306
  EventsManager.trackAutoEvent('text_selection', {
package/lib/umd/index.js CHANGED
@@ -6067,6 +6067,30 @@
6067
6067
  }
6068
6068
  }
6069
6069
 
6070
+ // Build auto_event_data for custom events (heatmap/position context when possible)
6071
+ let customAutoEventData = {};
6072
+ if (typeof window !== 'undefined' && window.document) {
6073
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
6074
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
6075
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
6076
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
6077
+ customAutoEventData = {
6078
+ scroll_x: scrollX,
6079
+ scroll_y: scrollY,
6080
+ document_height: docHeight,
6081
+ document_width: docWidth
6082
+ };
6083
+ const srcEvent = options.sourceEvent;
6084
+ if (srcEvent && typeof srcEvent === 'object' && (srcEvent.pageX != null || srcEvent.clientX != null)) {
6085
+ customAutoEventData.page_x = srcEvent.pageX != null ? srcEvent.pageX : (srcEvent.clientX + (window.scrollX || window.pageXOffset || 0));
6086
+ customAutoEventData.page_y = srcEvent.pageY != null ? srcEvent.pageY : (srcEvent.clientY + (window.scrollY || window.pageYOffset || 0));
6087
+ customAutoEventData.click_coordinates = {
6088
+ x: srcEvent.clientX != null ? srcEvent.clientX : srcEvent.pageX - (window.scrollX || window.pageXOffset || 0),
6089
+ y: srcEvent.clientY != null ? srcEvent.clientY : srcEvent.pageY - (window.scrollY || window.pageYOffset || 0)
6090
+ };
6091
+ }
6092
+ }
6093
+
6070
6094
  // Prepare event data
6071
6095
  const eventData = {
6072
6096
  event_type: 'custom',
@@ -6076,6 +6100,7 @@
6076
6100
  user_id: userId,
6077
6101
  // Only include user-provided properties in custom_properties (filtered)
6078
6102
  custom_properties: filteredProperties,
6103
+ auto_event_data: customAutoEventData,
6079
6104
  // Page context and screen/viewport data go in page_data (not custom_properties)
6080
6105
  page_data: {
6081
6106
  current_url: window.location.href,
@@ -6890,7 +6915,18 @@
6890
6915
  if (element === lastClickElement && now - lastClickTime < 1000) {
6891
6916
  clickCount++;
6892
6917
  if (clickCount >= 3) {
6918
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
6919
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
6920
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
6921
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
6893
6922
  EventsManager.trackAutoEvent('rage_click', {
6923
+ click_coordinates: { x: event.clientX, y: event.clientY },
6924
+ page_x: event.pageX,
6925
+ page_y: event.pageY,
6926
+ scroll_x: scrollX,
6927
+ scroll_y: scrollY,
6928
+ document_height: docHeight,
6929
+ document_width: docWidth,
6894
6930
  click_count: clickCount,
6895
6931
  time_span: now - lastClickTime,
6896
6932
  element_area: element.offsetWidth * element.offsetHeight,
@@ -7008,11 +7044,17 @@
7008
7044
 
7009
7045
  if (scrollDepth > maxScrollDepth) {
7010
7046
  maxScrollDepth = scrollDepth;
7011
-
7047
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
7048
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
7049
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
7012
7050
  EventsManager.trackAutoEvent('page_scroll', {
7013
7051
  scroll_depth: scrollDepth,
7014
7052
  max_scroll_reached: maxScrollDepth,
7015
- scroll_position: window.scrollY
7053
+ scroll_position: window.scrollY,
7054
+ scroll_x: scrollX,
7055
+ scroll_y: window.scrollY,
7056
+ document_height: docHeight,
7057
+ document_width: docWidth
7016
7058
  }).catch(err => {
7017
7059
  console.error('❌ [AutoEvents] Failed to track page_scroll:', err);
7018
7060
  });
@@ -7030,10 +7072,24 @@
7030
7072
  document.addEventListener('submit', (event) => {
7031
7073
  const form = event.target;
7032
7074
  if (form.tagName === 'FORM') {
7075
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
7076
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
7077
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
7078
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
7079
+ const rect = form.getBoundingClientRect();
7080
+ const pageX = rect.left + scrollX;
7081
+ const pageY = rect.top + scrollY;
7033
7082
  EventsManager.trackAutoEvent('form_submit', {
7034
7083
  form_id: form.id || null,
7035
7084
  form_action: form.action || null,
7036
- form_method: form.method || 'get'
7085
+ form_method: form.method || 'get',
7086
+ scroll_x: scrollX,
7087
+ scroll_y: scrollY,
7088
+ document_height: docHeight,
7089
+ document_width: docWidth,
7090
+ page_x: pageX,
7091
+ page_y: pageY,
7092
+ click_coordinates: { x: event.clientX != null ? event.clientX : rect.left + rect.width / 2, y: event.clientY != null ? event.clientY : rect.top + rect.height / 2 }
7037
7093
  }, {
7038
7094
  element_tag_name: 'form',
7039
7095
  element_id: form.id || null,
@@ -7042,8 +7098,8 @@
7042
7098
  element_type: form.method || 'get', // FIX: Added element_type (form method)
7043
7099
  element_text: form.textContent?.trim().substring(0, 100) || null, // FIX: Added element_text
7044
7100
  element_position: { // FIX: Added element_position
7045
- x: event.clientX || 0,
7046
- y: event.clientY || 0,
7101
+ x: event.clientX || rect.left,
7102
+ y: event.clientY || rect.top,
7047
7103
  width: form.offsetWidth || 0,
7048
7104
  height: form.offsetHeight || 0
7049
7105
  }
@@ -7055,10 +7111,24 @@
7055
7111
  document.addEventListener('focus', (event) => {
7056
7112
  const element = event.target;
7057
7113
  if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA' || element.tagName === 'SELECT') {
7114
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
7115
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
7116
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
7117
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
7118
+ const rect = element.getBoundingClientRect();
7119
+ const pageX = rect.left + scrollX;
7120
+ const pageY = rect.top + scrollY;
7058
7121
  EventsManager.trackAutoEvent('form_focus', {
7059
7122
  field_name: element.name || null,
7060
7123
  field_type: element.type || null,
7061
- field_id: element.id || null
7124
+ field_id: element.id || null,
7125
+ scroll_x: scrollX,
7126
+ scroll_y: scrollY,
7127
+ document_height: docHeight,
7128
+ document_width: docWidth,
7129
+ page_x: pageX,
7130
+ page_y: pageY,
7131
+ click_coordinates: { x: event.clientX != null ? event.clientX : rect.left + rect.width / 2, y: event.clientY != null ? event.clientY : rect.top + rect.height / 2 }
7062
7132
  }, {
7063
7133
  element_tag_name: element.tagName.toLowerCase(),
7064
7134
  element_id: element.id || null,
@@ -7067,8 +7137,8 @@
7067
7137
  element_type: element.type || null,
7068
7138
  element_text: element.value ? element.value.toString().trim().substring(0, 100) : null, // FIX: Added element_text (value for form fields)
7069
7139
  element_position: { // FIX: Added element_position
7070
- x: event.clientX || 0,
7071
- y: event.clientY || 0,
7140
+ x: event.clientX != null ? event.clientX : rect.left,
7141
+ y: event.clientY != null ? event.clientY : rect.top,
7072
7142
  width: element.offsetWidth || 0,
7073
7143
  height: element.offsetHeight || 0
7074
7144
  }
@@ -7081,23 +7151,54 @@
7081
7151
  * Setup media tracking
7082
7152
  */
7083
7153
  setupMediaTracking() {
7154
+ function getPageContext() {
7155
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
7156
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
7157
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
7158
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
7159
+ return { scrollX, scrollY, docHeight, docWidth };
7160
+ }
7084
7161
  ['video', 'audio'].forEach(mediaType => {
7085
7162
  document.addEventListener('play', (event) => {
7086
7163
  if (event.target.tagName.toLowerCase() === mediaType) {
7164
+ const el = event.target;
7165
+ const { scrollX, scrollY, docHeight, docWidth } = getPageContext();
7166
+ const rect = el.getBoundingClientRect();
7167
+ const pageX = rect.left + scrollX;
7168
+ const pageY = rect.top + scrollY;
7087
7169
  EventsManager.trackAutoEvent('media_play', {
7088
7170
  media_type: mediaType,
7089
- media_src: event.target.src || null,
7090
- media_duration: event.target.duration || null
7171
+ media_src: el.src || null,
7172
+ media_duration: el.duration || null,
7173
+ scroll_x: scrollX,
7174
+ scroll_y: scrollY,
7175
+ document_height: docHeight,
7176
+ document_width: docWidth,
7177
+ page_x: pageX,
7178
+ page_y: pageY,
7179
+ click_coordinates: { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 }
7091
7180
  });
7092
7181
  }
7093
7182
  }, true);
7094
7183
 
7095
7184
  document.addEventListener('pause', (event) => {
7096
7185
  if (event.target.tagName.toLowerCase() === mediaType) {
7186
+ const el = event.target;
7187
+ const { scrollX, scrollY, docHeight, docWidth } = getPageContext();
7188
+ const rect = el.getBoundingClientRect();
7189
+ const pageX = rect.left + scrollX;
7190
+ const pageY = rect.top + scrollY;
7097
7191
  EventsManager.trackAutoEvent('media_pause', {
7098
7192
  media_type: mediaType,
7099
- media_current_time: event.target.currentTime || null,
7100
- media_duration: event.target.duration || null
7193
+ media_current_time: el.currentTime || null,
7194
+ media_duration: el.duration || null,
7195
+ scroll_x: scrollX,
7196
+ scroll_y: scrollY,
7197
+ document_height: docHeight,
7198
+ document_width: docWidth,
7199
+ page_x: pageX,
7200
+ page_y: pageY,
7201
+ click_coordinates: { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 }
7101
7202
  });
7102
7203
  }
7103
7204
  }, true);
@@ -7179,11 +7280,33 @@
7179
7280
  focus_offset: selection.focusOffset || null
7180
7281
  };
7181
7282
 
7182
- // Get page context
7283
+ // Get page context and selection position for heatmaps
7284
+ const scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
7285
+ const scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
7286
+ const docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
7287
+ const docWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
7288
+ let pageX = null;
7289
+ let pageY = null;
7290
+ if (range) {
7291
+ try {
7292
+ const selRect = range.getBoundingClientRect();
7293
+ if (selRect.width > 0 || selRect.height > 0) {
7294
+ pageX = selRect.left + scrollX;
7295
+ pageY = selRect.top + scrollY;
7296
+ }
7297
+ } catch (e) { /* getBoundingClientRect can throw in some edge cases */ }
7298
+ }
7183
7299
  const pageData = {
7184
7300
  page_url: window.location.href,
7185
7301
  page_title: document.title,
7186
- page_path: window.location.pathname
7302
+ page_path: window.location.pathname,
7303
+ scroll_x: scrollX,
7304
+ scroll_y: scrollY,
7305
+ document_height: docHeight,
7306
+ document_width: docWidth,
7307
+ page_x: pageX,
7308
+ page_y: pageY,
7309
+ click_coordinates: pageX != null && pageY != null ? { x: pageX - scrollX, y: pageY - scrollY } : null
7187
7310
  };
7188
7311
 
7189
7312
  EventsManager.trackAutoEvent('text_selection', {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cryptique-sdk",
3
- "version": "1.1.8",
3
+ "version": "1.1.9",
4
4
  "type": "module",
5
5
  "description": "Cryptique Analytics SDK - Comprehensive web analytics and user tracking for modern web applications",
6
6
  "main": "lib/cjs/index.js",